diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c41fb4646a..c7ac10b9cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,12 +5,22 @@ on: branches: - master - stable - - users tags: - "v*" - "!*-fdroid" - "!*-armv7a" pull_request: + paths-ignore: + - "apps/ios" + - "apps/multiplatform" + - "blog" + - "docs" + - "fastlane" + - "images" + - "packages" + - "website" + - "README.md" + - "PRIVACY.md" jobs: prepare-release: @@ -114,12 +124,12 @@ jobs: run: | echo "ignore-project: False" >> cabal.project.local echo "package simplexmq" >> cabal.project.local - echo " extra-include-dirs: /opt/homebrew/opt/openssl@1.1/include" >> cabal.project.local - echo " extra-lib-dirs: /opt/homebrew/opt/openssl@1.1/lib" >> cabal.project.local + echo " extra-include-dirs: /opt/homebrew/opt/openssl@3.0/include" >> cabal.project.local + echo " extra-lib-dirs: /opt/homebrew/opt/openssl@3.0/lib" >> cabal.project.local echo "" >> cabal.project.local echo "package direct-sqlcipher" >> cabal.project.local - echo " extra-include-dirs: /opt/homebrew/opt/openssl@1.1/include" >> cabal.project.local - echo " extra-lib-dirs: /opt/homebrew/opt/openssl@1.1/lib" >> cabal.project.local + echo " extra-include-dirs: /opt/homebrew/opt/openssl@3.0/include" >> cabal.project.local + echo " extra-lib-dirs: /opt/homebrew/opt/openssl@3.0/lib" >> cabal.project.local echo " flags: +openssl" >> cabal.project.local - name: Unix prepare cabal.project.local for Mac @@ -128,21 +138,21 @@ jobs: run: | echo "ignore-project: False" >> cabal.project.local echo "package simplexmq" >> cabal.project.local - echo " extra-include-dirs: /usr/local/opt/openssl@1.1/include" >> cabal.project.local - echo " extra-lib-dirs: /usr/local/opt/openssl@1.1/lib" >> cabal.project.local + echo " extra-include-dirs: /usr/local/opt/openssl@3.0/include" >> cabal.project.local + echo " extra-lib-dirs: /usr/local/opt/openssl@3.0/lib" >> cabal.project.local echo "" >> cabal.project.local echo "package direct-sqlcipher" >> cabal.project.local - echo " extra-include-dirs: /usr/local/opt/openssl@1.1/include" >> cabal.project.local - echo " extra-lib-dirs: /usr/local/opt/openssl@1.1/lib" >> cabal.project.local + echo " extra-include-dirs: /usr/local/opt/openssl@3.0/include" >> cabal.project.local + echo " extra-lib-dirs: /usr/local/opt/openssl@3.0/lib" >> cabal.project.local echo " flags: +openssl" >> cabal.project.local - name: Install AppImage dependencies 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 + - name: Install openssl for Mac if: matrix.os == 'macos-latest' || matrix.os == 'macos-13' - run: brew install pkg-config + run: brew install openssl@3.0 - name: Unix prepare cabal.project.local for Ubuntu if: matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04' @@ -324,7 +334,7 @@ jobs: run: | 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') + openssl_windows_style_path=$(echo `pwd`/dist-newstyle/openssl-3.0.15 | sed 's#/\([a-zA-Z]\)#\1:#' | sed 's#/#\\#g') rm cabal.project.local 2>/dev/null || true echo "ignore-project: False" >> cabal.project.local echo "package direct-sqlcipher" >> cabal.project.local diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml index 7fc66308f8..6839d48aeb 100644 --- a/.github/workflows/web.yml +++ b/.github/workflows/web.yml @@ -10,6 +10,7 @@ on: - blog/** - docs/** - .github/workflows/web.yml + - PRIVACY.md jobs: build: diff --git a/.gitignore b/.gitignore index e3ea5d267b..645b55ec9d 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,7 @@ website/package/generated* # Ignore build tool output, e.g. code coverage website/.nyc_output/ website/coverage/ +result # Ignore API documentation website/api-docs/ diff --git a/Dockerfile b/Dockerfile index 6c60195f97..7b9641777a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ RUN cp ./scripts/cabal.project.local.linux ./cabal.project.local # Compile simplex-chat RUN cabal update -RUN cabal build exe:simplex-chat +RUN cabal build exe:simplex-chat --constraint 'simplexmq +client_library' # Strip the binary from debug symbols to reduce size RUN bin=$(find /project/dist-newstyle -name "simplex-chat" -type f -executable) && \ diff --git a/PRIVACY.md b/PRIVACY.md index 66dff0e807..7c4bfbf660 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -3,63 +3,93 @@ layout: layouts/privacy.html permalink: /privacy/index.html --- -# SimpleX Chat Privacy Policy and Conditions of Use +# SimpleX Chat Operators Privacy Policy and Conditions of Use -SimpleX Chat is the first communication network based on a new protocol stack that builds on the same ideas of complete openness and decentralization as email and web, with the focus on providing security and privacy of communications, and without compromising on usability. +## Summary -SimpleX Chat communication protocol is the first protocol that has no user profile IDs of any kind, not even random numbers, cryptographic keys or hashes that identify the users. SimpleX Chat apps allow their users to send messages and files via relay server infrastructure. Relay server owners and providers do not have any access to your messages, thanks to double-ratchet end-to-end encryption algorithm (also known as Signal algorithm - do not confuse with Signal protocols or platform) and additional encryption layers, and they also have no access to your profile and contacts - as they do not provide any user accounts. +[Introduction](#introduction) and [General principles](#general-principles) cover SimpleX Chat network design, the network operators, and the principles of privacy and security provided by SimpleX network. + +[Privacy policy](#privacy-policy) covers: +- data stored only on your device - [your profiles](#user-profiles), delivered [messages and files](#messages-and-files). You can transfer this information to another device, and you are responsible for its preservation - if you delete the app it will be lost. +- [private message delivery](#private-message-delivery) that protects your IP address and connection graph from the destination servers. +- [undelivered messages and files](#storage-of-messages-and-files-on-the-servers) stored on the servers. +- [how users connect](#connections-with-other-users) without any user profile identifiers. +- [iOS push notifications](#ios-push-notifications) privacy limitations. +- [user support](#user-support), [SimpleX directory](#simplex-directory) and [any other data](#another-information-stored-on-the-servers) that may be stored on the servers. +- [preset server operators](#preset-server-operators) and the [information they may share](#information-preset-server-operators-may-share). +- [source code license](#source-code-license) and [updates to this document](#updates). + +[Conditions of Use](#conditions-of-use-of-software-and-infrastructure) are the conditions you need to accept to use SimpleX Chat applications and the relay servers of preset operators. Their purpose is to protect the users and preset server operators. + +*Please note*: this summary and any links in this document are provided for information only - they are not a part of the Privacy Policy and Conditions of Use. + +## Introduction + +SimpleX Chat (also referred to as SimpleX) is the first communication network based on a new protocol stack that builds on the same ideas of complete openness and decentralization as email and web, with the focus on providing security and privacy of communications, and without compromising on usability. + +SimpleX messaging protocol is the first protocol that has no user profile IDs of any kind, not even random numbers, cryptographic keys or hashes that identify the users. SimpleX apps allow their users to send messages and files via relay server infrastructure. Relay server owners and operators do not have any access to your messages, thanks to double-ratchet end-to-end encryption algorithm (also known as Signal algorithm - do not confuse with Signal protocols or platform) and additional encryption layers, and they also have no access to your profile and contacts - as they do not host user accounts. Double ratchet algorithm has such important properties as [forward secrecy](/docs/GLOSSARY.md#forward-secrecy), sender [repudiation](/docs/GLOSSARY.md#) and break-in recovery (also known as [post-compromise security](/docs/GLOSSARY.md#post-compromise-security)). -If you believe that any part of this document is not aligned with our mission or values, please raise it with us via [email](mailto:chat@simplex.chat) or [chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion). +If you believe that any part of this document is not aligned with SimpleX network mission or values, please raise it via [email](mailto:chat@simplex.chat) or [chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion). ## Privacy Policy -SimpleX Chat Ltd uses the best industry practices for security and encryption to provide client and server software for secure [end-to-end encrypted](/docs/GLOSSARY.md#end-to-end-encryption) messaging via private connections. This encryption cannot be compromised by the relays servers, even if they are modified or compromised, via [man-in-the-middle attack](/docs/GLOSSARY.md#man-in-the-middle-attack), unlike most other communication platforms, services and networks. +### General principles -SimpleX Chat software is built on top of SimpleX messaging and application protocols, based on a new message routing protocol allowing to establish private connections without having any kind of addresses or other identifiers assigned to its users - it does not use emails, phone numbers, usernames, identity keys or any other user profile identifiers to pass messages between the user applications. +SimpleX network software uses the best industry practices for security and encryption to provide client and server software for secure [end-to-end encrypted](/docs/GLOSSARY.md#end-to-end-encryption) messaging via private connections. This encryption is protected from being compromised by the relays servers, even if they are modified or compromised, via [man-in-the-middle attack](/docs/GLOSSARY.md#man-in-the-middle-attack). -SimpleX Chat software is similar in its design approach to email clients and browsers - it allows you to have full control of your data and freely choose the relay server providers, in the same way you choose which website or email provider to use, or use your own relay servers, simply by changing the configuration of the client software. The only current restriction to that is Apple push notifications - at the moment they can only be delivered via the preset servers that we operate, as explained below. We are exploring the solutions to deliver push notifications to iOS devices via other providers or users' own servers. +SimpleX software is built on top of SimpleX messaging and application protocols, based on a new message routing protocol allowing to establish private connections without having identifiers assigned to its users - it does not use emails, phone numbers, usernames, identity keys or any other user profile identifiers to pass messages between the user applications. -While SimpleX Chat Ltd is not a communication service provider, and provide public preset relays "as is", as experimental, without any guarantees of availability or data retention, we are committed to maintain a high level of availability, reliability and security of these preset relays. We will be adding alternative preset infrastructure providers to the software in the future, and you will continue to be able to use any other providers or your own servers. +SimpleX software is similar in its design approach to email clients and browsers - it allows you to have full control of your data and freely choose the relay server operators, in the same way you choose which website or email provider to use, or use your own relay servers, simply by changing the configuration of the client software. The only current restriction to that is Apple push notifications - at the moment they can only be delivered via the servers operated by SimpleX Chat Ltd, as explained below. We are exploring the solutions to deliver push notifications to iOS devices via other providers or users' own servers. -We see users and data sovereignty, and device and provider portability as critically important properties for any communication system. +SimpleX network operators are not communication service provider, and provide public relays "as is", as experimental, without any guarantees of availability or data retention. The operators of the relay servers preset in the app ("Preset Server Operators"), including SimpleX Chat Ltd, are committed to maintain a high level of availability, reliability and security. SimpleX client apps can have multiple preset relay server operators that you can opt-in or opt-out of using. You are and will continue to be able to use any other operators or your own servers. -SimpleX Chat security assessment was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2 – see [the announcement](/blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). +SimpleX network design is based on the principles of users and data sovereignty, and device and operator portability. + +The implementation security assessment of SimpleX cryptography and networking was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2 – see [the announcement](/blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). + +The cryptographic review of SimpleX protocols design was done in July 2024 by Trail of Bits – see [the announcement](/blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md). ### Your information #### User profiles -Servers used by SimpleX Chat apps do not create, store or identify user profiles. The profiles you can create in the app are local to your device, and can be removed at any time via the app. +Servers used by SimpleX Chat apps do not create, store or identify user chat profiles. The profiles you can create in the app are local to your device, and can be removed at any time via the app. -When you create the local profile, no records are created on any of the relay servers, and infrastructure providers, whether SimpleX Chat Ltd or any other, have no access to any part of your information, and even to the fact that you created a profile - it is a local record stored only on your device. That means that if you delete the app, and have no backup, you will permanently lose all your data and the private connections you created with other software users. +When you create the local profile, no records are created on any of the relay servers, and infrastructure operators, whether preset in the app or any other, have no access to any part of your information, and even to the fact that you created a profile - it is a local record stored only on your device. That means that if you delete the app, and have no backup, you will permanently lose all your data and the private connections you created with other software users. You can transfer the profile to another device by creating a backup of the app data and restoring it on the new device, but you cannot use more than one device with the copy of the same profile at the same time - it will disrupt any active conversations on either or both devices, as a security property of end-to-end encryption. #### Messages and Files -SimpleX relay servers cannot decrypt or otherwise access the content or even the size of your messages and files you send or receive. Each message is padded to a fixed size of 16kb. Each file is sent in chunks of 64kb, 256kb, 1mb or 8mb via all or some of the configured file relay servers. Both messages and files are sent end-to-end encrypted, and the servers do not have technical means to compromise this encryption, because part of the [key exchange](/docs/GLOSSARY.md#key-exchange) happens out-of-band. +SimpleX relay servers cannot decrypt or otherwise access the content or even the size of your messages and files you send or receive. Each message is padded to a fixed size of 16kb. Each file is sent in chunks of 64kb, 256kb, 1mb or 4mb via all or some of the configured file relay servers. Both messages and files are sent end-to-end encrypted, and the servers do not have technical means to compromise this encryption, because part of the [key exchange](/docs/GLOSSARY.md#key-exchange) happens out-of-band. Your message history is stored only on your own device and the devices of your contacts. While the recipients' devices are offline, messaging relay servers temporarily store end-to-end encrypted messages – you can configure which relay servers are used to receive the messages from the new contacts, and you can manually change them for the existing contacts too. -You do not have control over which servers are used to send messages to your contacts - they are chosen by them. To send messages your client needs to connect to these servers, therefore the servers chosen by your contacts can observe your IP address. You can use VPN or some overlay network (e.g., Tor) to hide your IP address from the servers chosen by your contacts. In the near future we will add the layer in the messaging protocol that will route sent message via the relays chosen by you as well. +#### Private message delivery -The messages are permanently removed from the used relay servers as soon as they are delivered, as long as these servers used unmodified published code. Undelivered messages are deleted after the time that is configured in the messaging servers you use (21 days for preset messaging servers). +You do not have control over which servers are used to send messages to your contacts - these servers are chosen by your contacts. To send messages your client by default uses configured servers to forward messages to the destination servers, thus protecting your IP address from the servers chosen by your contacts. + +In case you use preset servers of more than one operator, the app will prefer to use a server of an operator different from the operator of the destination server to forward messages, preventing destination server to correlate messages as belonging to one client. + +You can additionally use VPN or some overlay network (e.g., Tor) to hide your IP address from the servers chosen by you. + +*Please note*: the clients allow changing configuration to connect to the destination servers directly. It is not recommended - if you make such change, your IP address will be visible to the destination servers. + +#### Storage of messages and files on the servers + +The messages are removed from the relay servers as soon as all messages of the file they were stored in are delivered and saving new messages switches to another file, as long as these servers use unmodified published code. Undelivered messages are also marked as delivered after the time that is configured in the messaging servers you use (21 days for preset messaging servers). The files are stored on file relay servers for the time configured in the relay servers you use (48 hours for preset file servers). -If a messaging servers are restarted, the encrypted message can be stored in a backup file until it is overwritten by the next restart (usually within 1 week for preset relay servers). - -As this software is fully open-source and provided under AGPLv3 license, all infrastructure providers and owners, and the developers of the client and server applications who use the SimpleX Chat source code, are required to publish any changes to this software under the same AGPLv3 license - including any modifications to the provided servers. - -In addition to the AGPLv3 license terms, SimpleX Chat Ltd is committed to the software users that the preset relays that we provide via the apps will always be compiled from the [published open-source code](https://github.com/simplex-chat/simplexmq), without any modifications. +The encrypted messages can be stored for some time after they are delivered or expired (because servers use append-only logs for message storage). This time varies, and may be longer in connections with fewer messages, but it is usually limited to 1 month, including any backup storage. #### Connections with other users -When you create a connection with another user, two messaging queues (you can think about them as mailboxes) are created on messaging relay servers (chosen by you and your contact each), that can be the preset servers or the servers that you and your contact configured in the app. SimpleX messaging protocol uses separate queues for direct and response messages, and the apps prefer to create these queues on two different relay servers for increased privacy, in case you have more than one relay server configured in the app, which is the default. +When you create a connection with another user, two messaging queues (you can think about them as mailboxes) are created on messaging relay servers (chosen by you and your contact each), that can be the preset servers or the servers that you and your contact configured in the app. SimpleX messaging protocol uses separate queues for direct and response messages, and the apps prefer to create these queues on two different relay servers, or, if available, the relays of two different operators, for increased privacy, in case you have more than one relay server configured in the app, which is the default. -SimpleX relay servers do not store information about which queues are linked to your profile on the device, and they do not collect any information that would allow infrastructure owners and providers to establish that these queues are related to your device or your profile - the access to each queue is authorized by two anonymous unique cryptographic keys, different for each queue, and separate for sender and recipient of the messages. +Preset and unmodified SimpleX relay servers do not store information about which queues are linked to your profile on the device, and they do not collect any information that would allow infrastructure owners and operators to establish that these queues are related to your device or your profile - the access to each queue is authorized by two anonymous unique cryptographic keys, different for each queue, and separate for sender and recipient of the messages. #### Connection links privacy @@ -75,6 +105,8 @@ You can always safely replace the initial part of the link `https://simplex.chat #### iOS Push Notifications +This section applies only to the notification servers operated by SimpleX Chat Ltd. + When you choose to use instant push notifications in SimpleX iOS app, because the design of push notifications requires storing the device token on notification server, the notifications server can observe how many messaging queues your device has notifications enabled for, and approximately how many messages are sent to each queue. Preset notification server cannot observe the actual addresses of these queues, as a separate address is used to subscribe to the notifications. It also cannot observe who sends messages to you. Apple push notifications servers can only observe how many notifications are sent to you, but not from how many contacts, or from which messaging relays, as notifications are delivered to your device end-to-end encrypted by one of the preset notification servers - these notifications only contain end-to-end encrypted metadata, not even encrypted message content, and they look completely random to Apple push notification servers. @@ -83,93 +115,111 @@ You can read more about the design of iOS push notifications [here](./blog/20220 #### Another information stored on the servers -Additional technical information can be stored on our servers, including randomly generated authentication tokens, keys, push tokens, and other material that is necessary to transmit messages. SimpleX Chat design limits this additional technical information to the minimum required to operate the software and servers. To prevent server overloading or attacks, the servers can temporarily store data that can link to particular users or devices, including IP addresses, geographic location, or information related to the transport sessions. This information is not stored for the absolute majority of the app users, even for those who use the servers very actively. +Additional technical information can be stored on the network servers, including randomly generated authentication tokens, keys, push tokens, and other material that is necessary to transmit messages. SimpleX network design limits this additional technical information to the minimum required to operate the software and servers. To prevent server overloading or attacks, the servers can temporarily store data that can link to particular users or devices, including IP addresses, geographic location, or information related to the transport sessions. This information is not stored for the absolute majority of the app users, even for those who use the servers very actively. #### SimpleX Directory +This section applies only to the experimental group directory operated by SimpleX Chat Ltd. + [SimpleX Directory](/docs/DIRECTORY.md) stores: your search requests, the messages and the members profiles in the registered groups. You can connect to SimpleX Directory via [this address](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). #### User Support -If you contact SimpleX Chat Ltd, any personal data you share with us is kept only for the purposes of researching the issue and contacting you about your case. We recommend contacting support [via chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion) when it is possible, and avoid sharing any personal information. +The app includes support contact operated by SimpleX Chat Ltd. If you contact support, any personal data you share is kept only for the purposes of researching the issue and contacting you about your case. We recommend contacting support [via chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion) when it is possible, and avoid sharing any personal information. -### Information we may share +### Preset Server Operators -SimpleX Chat Ltd operates preset relay servers using third parties. While we do not have access and cannot share any user data, these third parties may access the encrypted user messages (but NOT the actual unencrypted message content or size) as it is stored or transmitted via our servers. Hosting providers can also store IP addresses and other transport information as part of their logs. +Preset server operators will not share the information on their servers with each other, other than aggregate usage statistics. -We use a third party for email services - if you ask for support via email, your and SimpleX Chat Ltd email providers may access these emails according to their privacy policies and terms. When the request is sensitive, we recommend contacting us via SimpleX Chat or using encrypted email using PGP key published at [openpgp.org](https://keys.openpgp.org/search?q=chat%40simplex.chat). +Preset server operators will not provide general access to their servers or the data on their servers to each other. -The cases when SimpleX Chat Ltd may share the data temporarily stored on the servers: +Preset server operators will provide non-administrative access to control port of preset servers to SimpleX Chat Ltd, for the purposes of removing identified illegal content. This control port access only allows deleting known links and files, and access to aggregate statistics, but does NOT allow enumerating any information on the servers. + +### Information Preset Server Operators May Share + +The preset server operators use third parties. While they do not have access and cannot share any user data, these third parties may access the encrypted user messages (but NOT the actual unencrypted message content or size) as it is stored or transmitted via the servers. Hosting and network providers can also store IP addresses and other transport information as part of their logs. + +SimpleX Chat Ltd uses a third party for email services - if you ask for support via email, your and SimpleX Chat Ltd email providers may access these emails according to their privacy policies and terms. When the request is sensitive, please contact us via SimpleX Chat apps or using encrypted email using PGP key published at [openpgp.org](https://keys.openpgp.org/search?q=chat%40simplex.chat). + +The cases when the preset server operators may share the data temporarily stored on the servers: - To meet any applicable law, or enforceable governmental request or court order. - To enforce applicable terms, including investigation of potential violations. - To detect, prevent, or otherwise address fraud, security, or technical issues. -- To protect against harm to the rights, property, or safety of software users, SimpleX Chat Ltd, or the public as required or permitted by law. +- To protect against harm to the rights, property, or safety of software users, operators of preset servers, or the public as required or permitted by law. -At the time of updating this document, we have never provided or have been requested the access to the preset relay servers or any information from the servers by any third parties. If we are ever requested to provide such access or information, we will follow the due legal process to limit any information shared with the third parties to the minimally required by law. +At the time of updating this document, the preset server operators have never provided or have been requested the access to the preset relay servers or any information from the servers by any third parties. If the preset server operators are ever requested to provide such access or information, they will follow the due legal process to limit any information shared with the third parties to the minimally required by law. -We will publish information we are legally allowed to share about such requests in the [Transparency reports](./docs/TRANSPARENCY.md). +Preset server operators will publish information they are legally allowed to share about such requests in the [Transparency reports](./docs/TRANSPARENCY.md). + +### Source code license + +As this software is fully open-source and provided under AGPLv3 license, all infrastructure owners and operators, and the developers of the client and server applications who use the SimpleX Chat source code, are required to publish any changes to this software under the same AGPLv3 license - including any modifications to the servers. + +In addition to the AGPLv3 license terms, the preset relay server operators are committed to the software users that these servers will always be compiled from the [published open-source code](https://github.com/simplex-chat/simplexmq), without any modifications. ### Updates -We will update this Privacy Policy as needed so that it is current, accurate, and as clear as possible. Your continued use of our software applications and preset relays infrastructure confirms your acceptance of our updated Privacy Policy. +This Privacy Policy applies to SimpleX Chat Ltd and all other preset server operators you use in the app. -Please also read our Conditions of Use of Software and Infrastructure below. +This Privacy Policy may be updated as needed so that it is current, accurate, and as clear as possible. When it is updated, you will have to review and accept the changed policy within 30 days of such changes to continue using preset relay servers. Even if you fail to accept the changed policy, your continued use of SimpleX Chat software applications and preset relay servers confirms your acceptance of the updated Privacy Policy. -If you have questions about our Privacy Policy please contact us via [email](mailto:chat@simplex.chat) or [chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion). +Please also read The Conditions of Use of Software and Infrastructure below. + +If you have questions about this Privacy Policy please contact SimpleX Chat Ltd via [email](mailto:chat@simplex.chat) or [chat](https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23%2F%3Fv%3D1%26dh%3DMCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion). ## Conditions of Use of Software and Infrastructure -You accept the Conditions of Use of Software and Infrastructure ("Conditions") by installing or using any of our software or using any of our server infrastructure (collectively referred to as "Applications"), whether preset in the software or not. +You accept the Conditions of Use of Software and Infrastructure ("Conditions") by installing or using any of SimpleX Chat software or using any of server infrastructure (collectively referred to as "Applications") operated by the Preset Server Operators, including SimpleX Chat Ltd, whether these servers are preset in the software or not. -**Minimal age**. You must be at least 13 years old to use our Applications. The minimum age to use our Applications without parental approval may be higher in your country. +**Minimal age**. You must be at least 13 years old to use SimpleX Chat Applications. The minimum age to use SimpleX Applications without parental approval may be higher in your country. -**Infrastructure**. Our Infrastructure includes preset messaging and file relay servers, and iOS push notification servers provided by SimpleX Chat Ltd for public use. Our infrastructure does not have any modifications from the [published open-source code](https://github.com/simplex-chat/simplexmq) available under AGPLv3 license. Any infrastructure provider, whether commercial or not, is required by the Affero clause (named after Affero Inc. company that pioneered the community-based Q&A sites in early 2000s) to publish any modifications under the same license. The statements in relation to Infrastructure and relay servers anywhere in this document assume no modifications to the published code, even in the cases when it is not explicitly stated. +**Infrastructure**. Infrastructure of the preset server operators includes messaging and file relay servers. SimpleX Chat Ltd also provides iOS push notification servers for public use. This infrastructure does not have any modifications from the [published open-source code](https://github.com/simplex-chat/simplexmq) available under AGPLv3 license. Any infrastructure provider, whether commercial or not, is required by the Affero clause (named after Affero Inc. company that pioneered the community-based Q&A sites in early 2000s) to publish any modifications under the same license. The statements in relation to Infrastructure and relay servers anywhere in this document assume no modifications to the published code, even in the cases when it is not explicitly stated. -**Client applications**. Our client application Software (referred to as "app" or "apps") also has no modifications compared with published open-source code, and any developers of the alternative client apps based on our code are required to publish any modifications under the same AGPLv3 license. Client applications should not include any tracking or analytics code, and do not share any information with SimpleX Chat Ltd or any other third parties. If you ever discover any tracking or analytics code, please report it to us, so we can remove it. +**Client applications**. SimpleX Chat client application Software (referred to as "app" or "apps") also has no modifications compared with published open-source code, and any developers of the alternative client apps based on SimpleX Chat code are required to publish any modifications under the same AGPLv3 license. Client applications should not include any tracking or analytics code, and do not share any tracking information with SimpleX Chat Ltd, preset server operators or any other third parties. If you ever discover any tracking or analytics code, please report it to SimpleX Chat Ltd, so it can be removed. -**Accessing the infrastructure**. For the efficiency of the network access, the client Software by default accesses all queues your app creates on any relay server within one user profile via the same network (TCP/IP) connection. At the cost of additional traffic this configuration can be changed to use different transport session for each connection. Relay servers do not collect information about which queues were created or accessed via the same connection, so the relay servers cannot establish which queues belong to the same user profile. Whoever might observe your network traffic would know which relay servers you use, and how much data you send, but not to whom it is sent - the data that leaves the servers is always different from the data they receive - there are no identifiers or ciphertext in common, even inside TLS encryption layer. Please refer to our [technical design document](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md) for more information about our privacy model and known security and privacy risks. +**Accessing the infrastructure**. For the efficiency of the network access, the client Software by default accesses all queues your app creates on any relay server within one user profile via the same network (TCP/IP) connection. At the cost of additional traffic this configuration can be changed to use different transport session for each connection. Relay servers do not collect information about which queues were created or accessed via the same connection, so the relay servers cannot establish which queues belong to the same user profile. Whoever might observe your network traffic would know which relay servers you use, and how much data you send, but not to whom it is sent - the data that leaves the servers is always different from the data they receive - there are no identifiers or ciphertext in common, even inside TLS encryption layer. Please refer to the [technical design document](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md) for more information about the privacy model and known security and privacy risks. -**Privacy of user data**. Servers do not retain any data we transmit for any longer than necessary to deliver the messages between apps. SimpleX Chat Ltd collects aggregate statistics across all its servers, as supported by published code and can be enabled by any infrastructure provider, but not any statistics per-user, or per geographic location, or per IP address, or per transport session. We do not have information about how many people use SimpleX Chat applications, we only know an approximate number of app installations and the aggregate traffic through the preset servers. In any case, we do not and will not sell or in any way monetize user data. Our future business model assumes charging for some optional Software features instead, in a transparent and fair way. +**Privacy of user data**. Servers do not retain any data you transmit for any longer than necessary to deliver the messages between apps. Preset server operators collect aggregate statistics across all their servers, as supported by published code and can be enabled by any infrastructure operator, but not any statistics per-user, or per geographic location, or per IP address, or per transport session. SimpleX Chat Ltd does not have information about how many people use SimpleX Chat applications, it only knows an approximate number of app installations and the aggregate traffic through the preset servers. In any case, preset server operators do not and will not sell or in any way monetize user data. The future business model assumes charging for some optional Software features instead, in a transparent and fair way. -**Operating our Infrastructure**. For the purpose of using our Software, if you continue using preset servers, you agree that your end-to-end encrypted messages are transferred via the preset servers in any countries where we have or use facilities and service providers or partners. The information about geographic location of the servers will be made available in the apps in the near future. +**Operating Infrastructure**. For the purpose of using SimpleX Chat Software, if you continue using preset servers, you agree that your end-to-end encrypted messages are transferred via the preset servers in any countries where preset server operators have or use facilities and service providers or partners. The information about geographic location and hosting providers of the preset messaging servers is available on server pages. -**Software**. You agree to downloading and installing updates to our Applications when they are available; they would only be automatic if you configure your devices in this way. +**Software**. You agree to downloading and installing updates to SimpleX Chat Applications when they are available; they would only be automatic if you configure your devices in this way. -**Traffic and device costs**. You are solely responsible for the traffic and device costs that you incur while using our Applications, and any associated taxes. +**Traffic and device costs**. You are solely responsible for the traffic and device costs that you incur while using SimpleX Chat Applications, and any associated taxes. -**Legal usage**. You agree to use our Applications only for legal purposes. You will not use (or assist others in using) our Applications in ways that: 1) violate or infringe the rights of Software users, SimpleX Chat Ltd, or others, including privacy, publicity, intellectual property, or other proprietary rights; 2) involve sending illegal communications, e.g. spam. While we cannot access content or identify messages or groups, in some cases the links to the illegal communications available via our Applications can be shared publicly on social media or websites. We reserve the right to remove such links from the preset servers and disrupt the conversations that send illegal content via our servers, whether they were reported by the users or discovered by our team. +**Legal usage**. You agree to use SimpleX Chat Applications only for legal purposes. You will not use (or assist others in using) the Applications in ways that: 1) violate or infringe the rights of Software users, SimpleX Chat Ltd, other preset server operators, or others, including privacy, publicity, intellectual property, or other proprietary rights; 2) involve sending illegal communications, e.g. spam. While server operators cannot access content or identify messages or groups, in some cases the links to the illegal communications can be shared publicly on social media or websites. Preset server operators reserve the right to remove such links from the preset servers and disrupt the conversations that send illegal content via their servers, whether they were reported by the users or discovered by the operators themselves. -**Damage to SimpleX Chat Ltd**. You must not (or assist others to) access, use, modify, distribute, transfer, or exploit our Applications in unauthorized manners, or in ways that harm Software users, SimpleX Chat Ltd, our Infrastructure, or any other systems. For example, you must not 1) access our Infrastructure or systems without authorization, in any way other than by using the Software; 2) disrupt the integrity or performance of our Infrastructure; 3) collect information about our users in any manner; or 4) sell, rent, or charge for our Infrastructure. This does not prohibit you from providing your own Infrastructure to others, whether free or for a fee, as long as you do not violate these Conditions and AGPLv3 license, including the requirement to publish any modifications of the relay server software. +**Damage to SimpleX Chat Ltd and Preset Server Operators**. You must not (or assist others to) access, use, modify, distribute, transfer, or exploit SimpleX Chat Applications in unauthorized manners, or in ways that harm Software users, SimpleX Chat Ltd, other preset server operators, their Infrastructure, or any other systems. For example, you must not 1) access preset operators' Infrastructure or systems without authorization, in any way other than by using the Software; 2) disrupt the integrity or performance of preset operators' Infrastructure; 3) collect information about the users in any manner; or 4) sell, rent, or charge for preset operators' Infrastructure. This does not prohibit you from providing your own Infrastructure to others, whether free or for a fee, as long as you do not violate these Conditions and AGPLv3 license, including the requirement to publish any modifications of the relay server software. -**Keeping your data secure**. SimpleX Chat is the first communication software that aims to be 100% private by design - server software neither has the ability to access your messages, nor it has information about who you communicate with. That means that you are solely responsible for keeping your device, your user profile and any data safe and secure. If you lose your phone or remove the Software from the device, you will not be able to recover the lost data, unless you made a back up. To protect the data you need to make regular backups, as using old backups may disrupt your communication with some of the contacts. +**Keeping your data secure**. SimpleX Chat is the first communication software that aims to be 100% private by design - server software neither has the ability to access your messages, nor it has information about who you communicate with. That means that you are solely responsible for keeping your device, your user profile and any data safe and secure. If you lose your phone or remove the Software from the device, you will not be able to recover the lost data, unless you made a back up. To protect the data you need to make regular backups, as using old backups may disrupt your communication with some of the contacts. SimpleX Chat Ltd and other preset server operators are not responsible for any data loss. **Storing the messages on the device**. The messages are stored in the encrypted database on your device. Whether and how database passphrase is stored is determined by the configuration of the Software you use. The databases created prior to 2023 or in CLI (terminal) app may remain unencrypted, and it will be indicated in the app interface. In this case, if you make a backup of the data and store it unencrypted, the backup provider may be able to access the messages. Please note, that the desktop apps can be configured to store the database passphrase in the configuration file in plaintext, and unless you set the passphrase when first running the app, a random passphrase will be used and stored on the device. You can remove it from the device via the app settings. **Storing the files on the device**. The files currently sent and received in the apps by default (except CLI app) are stored on your device encrypted using unique keys, different for each file, that are stored in the database. Once the message that the file was attached to is removed, even if the copy of the encrypted file is retained, it should be impossible to recover the key allowing to decrypt the file. This local file encryption may affect app performance, and it can be disabled via the app settings. This change will only affect the new files. If you later re-enable the encryption, it will also affect only the new files. If you make a backup of the app data and store it unencrypted, the backup provider will be able to access any unencrypted files. In any case, irrespective of the storage setting, the files are always sent by all apps end-to-end encrypted. -**No Access to Emergency Services**. Our Applications do not provide access to emergency service providers like the police, fire department, hospitals, or other public safety organizations. Make sure you can contact emergency service providers through a mobile, fixed-line telephone, or other service. +**No Access to Emergency Services**. SimpleX Chat Applications do not provide access to emergency service providers like the police, fire department, hospitals, or other public safety organizations. Make sure you can contact emergency service providers through a mobile, fixed-line telephone, or other service. -**Third-party services**. Our Applications may allow you to access, use, or interact with our or third-party websites, apps, content, and other products and services. When you use third-party services, their terms and privacy policies govern your use of those services. +**Third-party services**. SimpleX Chat Applications may allow you to access, use, or interact with the websites of SimpleX Chat Ltd, preset server operators or other third-party websites, apps, content, and other products and services. When you use third-party services, their terms and privacy policies govern your use of those services. -**Your Rights**. You own the messages and the information you transmit through our Applications. Your recipients are able to retain the messages they receive from you; there is no technical ability to delete data from their devices. While there are various app features that allow deleting messages from the recipients' devices, such as _disappearing messages_ and _full message deletion_, their functioning on your recipients' devices cannot be guaranteed or enforced, as the device may be offline or have a modified version of the Software. At the same time, repudiation property of the end-to-end encryption algorithm allows you to plausibly deny having sent the message, like you can deny what you said in a private face-to-face conversation, as the recipient cannot provide any proof to the third parties, by design. +**Your Rights**. You own the messages and the information you transmit through SimpleX Applications. Your recipients are able to retain the messages they receive from you; there is no technical ability to delete data from their devices. While there are various app features that allow deleting messages from the recipients' devices, such as _disappearing messages_ and _full message deletion_, their functioning on your recipients' devices cannot be guaranteed or enforced, as the device may be offline or have a modified version of the Software. At the same time, repudiation property of the end-to-end encryption algorithm allows you to plausibly deny having sent the message, like you can deny what you said in a private face-to-face conversation, as the recipient cannot provide any proof to the third parties, by design. -**License**. SimpleX Chat Ltd grants you a limited, revocable, non-exclusive, and non-transferable license to use our Applications in accordance with these Conditions. The source-code of Applications is available and can be used under [AGPL v3 license](https://github.com/simplex-chat/simplex-chat/blob/stable/LICENSE). +**License**. SimpleX Chat Ltd grants you a limited, revocable, non-exclusive, and non-transferable license to use SimpleX Chat Applications in accordance with these Conditions. The source-code of Applications is available and can be used under [AGPL v3 license](https://github.com/simplex-chat/simplex-chat/blob/stable/LICENSE). -**SimpleX Chat Ltd Rights**. We own all copyrights, trademarks, domains, logos, trade secrets, and other intellectual property rights associated with our Applications. You may not use our copyrights, trademarks, domains, logos, and other intellectual property rights unless you have our written permission, and unless under an open-source license distributed together with the source code. To report copyright, trademark, or other intellectual property infringement, please contact chat@simplex.chat. +**SimpleX Chat Ltd Rights**. SimpleX Chat Ltd (and, where applicable, preset server operators) owns all copyrights, trademarks, domains, logos, trade secrets, and other intellectual property rights associated with the Applications. You may not use SimpleX Chat Ltd copyrights, trademarks, domains, logos, and other intellectual property rights unless you have SimpleX Chat Ltd written permission, and unless under an open-source license distributed together with the source code. To report copyright, trademark, or other intellectual property infringement, please contact chat@simplex.chat. -**Disclaimers**. YOU USE OUR APPLICATIONS AT YOUR OWN RISK AND SUBJECT TO THE FOLLOWING DISCLAIMERS. WE PROVIDE OUR APPLICATIONS ON AN “AS IS” BASIS WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, AND FREEDOM FROM COMPUTER VIRUS OR OTHER HARMFUL CODE. SIMPLEX CHAT LTD DOES NOT WARRANT THAT ANY INFORMATION PROVIDED BY US IS ACCURATE, COMPLETE, OR USEFUL, THAT OUR APPLICATIONS WILL BE OPERATIONAL, ERROR-FREE, SECURE, OR SAFE, OR THAT OUR APPLICATIONS WILL FUNCTION WITHOUT DISRUPTIONS, DELAYS, OR IMPERFECTIONS. WE DO NOT CONTROL, AND ARE NOT RESPONSIBLE FOR, CONTROLLING HOW OR WHEN OUR USERS USE OUR APPLICATIONS. WE ARE NOT RESPONSIBLE FOR THE ACTIONS OR INFORMATION (INCLUDING CONTENT) OF OUR USERS OR OTHER THIRD PARTIES. YOU RELEASE US, AFFILIATES, DIRECTORS, OFFICERS, EMPLOYEES, PARTNERS, AND AGENTS ("SIMPLEX PARTIES") FROM ANY CLAIM, COMPLAINT, CAUSE OF ACTION, CONTROVERSY, OR DISPUTE (TOGETHER, "CLAIM") AND DAMAGES, KNOWN AND UNKNOWN, RELATING TO, ARISING OUT OF, OR IN ANY WAY CONNECTED WITH ANY SUCH CLAIM YOU HAVE AGAINST ANY THIRD PARTIES. +**Disclaimers**. YOU USE SIMPLEX APPLICATIONS AT YOUR OWN RISK AND SUBJECT TO THE FOLLOWING DISCLAIMERS. SIMPLEX CHAT LTD PROVIDES APPLICATIONS ON AN “AS IS” BASIS WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, AND FREEDOM FROM COMPUTER VIRUS OR OTHER HARMFUL CODE. SIMPLEX CHAT LTD DOES NOT WARRANT THAT ANY INFORMATION PROVIDED BY THEM IS ACCURATE, COMPLETE, OR USEFUL, THAT THEIR APPLICATIONS WILL BE OPERATIONAL, ERROR-FREE, SECURE, OR SAFE, OR THAT THEIR APPLICATIONS WILL FUNCTION WITHOUT DISRUPTIONS, DELAYS, OR IMPERFECTIONS. SIMPLEX CHAT LTD AND OTHER PRESET OPERATORS DO NOT CONTROL, AND ARE NOT RESPONSIBLE FOR, CONTROLLING HOW OR WHEN THE USERS USE APPLICATIONS. SIMPLEX CHAT LTD AND OTHER PRESET OPERATORS ARE NOT RESPONSIBLE FOR THE ACTIONS OR INFORMATION (INCLUDING CONTENT) OF THEIR USERS OR OTHER THIRD PARTIES. YOU RELEASE SIMPLEX CHAT LTD, OTHER PRESET OPERATORS, AFFILIATES, DIRECTORS, OFFICERS, EMPLOYEES, PARTNERS, AND AGENTS ("SIMPLEX PARTIES") FROM ANY CLAIM, COMPLAINT, CAUSE OF ACTION, CONTROVERSY, OR DISPUTE (TOGETHER, "CLAIM") AND DAMAGES, KNOWN AND UNKNOWN, RELATING TO, ARISING OUT OF, OR IN ANY WAY CONNECTED WITH ANY SUCH CLAIM YOU HAVE AGAINST ANY THIRD PARTIES. -**Limitation of liability**. THE SIMPLEX PARTIES WILL NOT BE LIABLE TO YOU FOR ANY LOST PROFITS OR CONSEQUENTIAL, SPECIAL, PUNITIVE, INDIRECT, OR INCIDENTAL DAMAGES RELATING TO, ARISING OUT OF, OR IN ANY WAY IN CONNECTION WITH OUR CONDITIONS, US, OR OUR APPLICATIONS, EVEN IF THE SIMPLEX PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. OUR AGGREGATE LIABILITY RELATING TO, ARISING OUT OF, OR IN ANY WAY IN CONNECTION WITH OUR CONDITIONS, US, OR OUR APPLICATIONS WILL NOT EXCEED ONE DOLLAR ($1). THE FOREGOING DISCLAIMER OF CERTAIN DAMAGES AND LIMITATION OF LIABILITY WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. THE LAWS OF SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO SOME OR ALL OF THE EXCLUSIONS AND LIMITATIONS SET FORTH ABOVE MAY NOT APPLY TO YOU. NOTWITHSTANDING ANYTHING TO THE CONTRARY IN OUR CONDITIONS, IN SUCH CASES, THE LIABILITY OF THE SIMPLEX PARTIES WILL BE LIMITED TO THE EXTENT PERMITTED BY APPLICABLE LAW. +**Limitation of liability**. THE SIMPLEX PARTIES WILL NOT BE LIABLE TO YOU FOR ANY LOST PROFITS OR CONSEQUENTIAL, SPECIAL, PUNITIVE, INDIRECT, OR INCIDENTAL DAMAGES RELATING TO, ARISING OUT OF, OR IN ANY WAY IN CONNECTION WITH OUR CONDITIONS, US, OR SIMPLEX APPLICATIONS, EVEN IF THE SIMPLEX PARTIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE AGGREGATE LIABILITY OF THE SIMPLEX PARTIES RELATING TO, ARISING OUT OF, OR IN ANY WAY IN CONNECTION WITH THESE CONDITIONS, THE SIMPLEX PARTIES, OR THE APPLICATIONS WILL NOT EXCEED ONE DOLLAR ($1). THE FOREGOING DISCLAIMER OF CERTAIN DAMAGES AND LIMITATION OF LIABILITY WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. THE LAWS OF SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO SOME OR ALL OF THE EXCLUSIONS AND LIMITATIONS SET FORTH ABOVE MAY NOT APPLY TO YOU. NOTWITHSTANDING ANYTHING TO THE CONTRARY IN THE CONDITIONS, IN SUCH CASES, THE LIABILITY OF THE SIMPLEX PARTIES WILL BE LIMITED TO THE EXTENT PERMITTED BY APPLICABLE LAW. -**Availability**. Our Applications may be disrupted, including for maintenance, upgrades, or network or equipment failures. We may discontinue some or all of our Applications, including certain features and the support for certain devices and platforms, at any time. +**Availability**. The Applications may be disrupted, including for maintenance, upgrades, or network or equipment failures. SimpleX Chat Ltd may discontinue some or all of their Applications, including certain features and the support for certain devices and platforms, at any time. Preset server operators may discontinue providing the servers, at any time. -**Resolving disputes**. You agree to resolve any Claim you have with us relating to or arising from our Conditions, us, or our Applications in the courts of England and Wales. You also agree to submit to the personal jurisdiction of such courts for the purpose of resolving all such disputes. The laws of England govern our Conditions, as well as any disputes, whether in court or arbitration, which might arise between SimpleX Chat Ltd and you, without regard to conflict of law provisions. +**Resolving disputes**. You agree to resolve any Claim you have with SimpleX Chat Ltd and/or preset server operators relating to or arising from these Conditions, them, or the Applications in the courts of England and Wales. You also agree to submit to the personal jurisdiction of such courts for the purpose of resolving all such disputes. The laws of England govern these Conditions, as well as any disputes, whether in court or arbitration, which might arise between SimpleX Chat Ltd (or preset server operators) and you, without regard to conflict of law provisions. -**Changes to the conditions**. SimpleX Chat Ltd may update the Conditions from time to time. Your continued use of our Applications confirms your acceptance of our updated Conditions and supersedes any prior Conditions. You will comply with all applicable export control and trade sanctions laws. Our Conditions cover the entire agreement between you and SimpleX Chat Ltd regarding our Applications. If you do not agree with our Conditions, you should stop using our Applications. +**Changes to the conditions**. SimpleX Chat Ltd may update the Conditions from time to time. The updated conditions have to be accepted within 30 days. Even if you fail to accept updated conditions, your continued use of SimpleX Chat Applications confirms your acceptance of the updated Conditions and supersedes any prior Conditions. You will comply with all applicable export control and trade sanctions laws. These Conditions cover the entire agreement between you and SimpleX Chat Ltd, and any preset server operators where applicable, regarding SimpleX Chat Applications. If you do not agree with these Conditions, you should stop using the Applications. -**Enforcing the conditions**. If we fail to enforce any of our Conditions, that does not mean we waive the right to enforce them. If any provision of the Conditions is deemed unlawful, void, or unenforceable, that provision shall be deemed severable from our Conditions and shall not affect the enforceability of the remaining provisions. Our Applications are not intended for distribution to or use in any country where such distribution or use would violate local law or would subject us to any regulations in another country. We reserve the right to limit our Applications in any country. If you have specific questions about these Conditions, please contact us at chat@simplex.chat. +**Enforcing the conditions**. If SimpleX Chat Ltd or preset server operators fail to enforce any of these Conditions, that does not mean they waive the right to enforce them. If any provision of the Conditions is deemed unlawful, void, or unenforceable, that provision shall be deemed severable from the Conditions and shall not affect the enforceability of the remaining provisions. The Applications are not intended for distribution to or use in any country where such distribution or use would violate local law or would subject SimpleX Chat Ltd to any regulations in another country. SimpleX Chat Ltd reserve the right to limit the access to the Applications in any country. Preset operators reserve the right to limit access to their servers in any country. If you have specific questions about these Conditions, please contact SimpleX Chat Ltd at chat@simplex.chat. -**Ending these conditions**. You may end these Conditions with SimpleX Chat Ltd at any time by deleting our Applications from your devices and discontinuing use of our Infrastructure. The provisions related to Licenses, Disclaimers, Limitation of Liability, Resolving dispute, Availability, Changes to the conditions, Enforcing the conditions, and Ending these conditions will survive termination of your relationship with SimpleX Chat Ltd. +**Ending these conditions**. You may end these Conditions with SimpleX Chat Ltd and preset server operators at any time by deleting the Applications from your devices and discontinuing use of the Infrastructure of SimpleX Chat Ltd and preset server operators. The provisions related to Licenses, Disclaimers, Limitation of Liability, Resolving dispute, Availability, Changes to the conditions, Enforcing the conditions, and Ending these conditions will survive termination of your relationship with SimpleX Chat Ltd and/or preset server operators. -Updated April 24, 2024 +Updated November 14, 2024 diff --git a/README.md b/README.md index 29ee7e189e..ad70c350e4 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ 2. ↔️ [Connect to the team](#connect-to-the-team), [join user groups](#join-user-groups) and [follow our updates](#follow-our-updates). 3. 🤝 [Make a private connection](#make-a-private-connection) with a friend. 4. 🔤 [Help translating SimpleX Chat](#help-translating-simplex-chat). -5. ⚡️ [Contribute](#contribute) and [help us with donations](#help-us-with-donations). +5. ⚡️ [Contribute](#contribute) and [support us with donations](#please-support-us-with-your-donations). [Learn more about SimpleX Chat](#contents). @@ -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 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) +You can join an English-speaking users group if you want to ask any questions: [#SimpleX users group](https://simplex.chat/contact#/?v=2-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-4&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FvYCRjIflKNMGYlfTkuHe4B40qSlQ0439%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAHNdcqNbzXZhyMoSBjT2R0-Eb1EPaLyUg3KZjn-kmM1w%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22PD20tcXjw7IpkkMCfR6HLA%3D%3D%22%7D) for developers who build on SimpleX platform: @@ -83,7 +83,7 @@ There is also a group [#simplex-devs](https://simplex.chat/contact#/?v=1-4&smp=s There are groups in other languages, that we have the apps interface translated into. These groups are for testing, and asking questions to other SimpleX Chat users: -[\#SimpleX-DE](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FkIEl7OQzcp-J6aDmjdlQbRJwqkcZE7XR%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAR16PCu02MobRmKAsjzhDWMZcWP9hS8l5AUZi-Gs8z18%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22puYPMCQt11yPUvgmI5jCiw%3D%3D%22%7D) (German-speaking), [\#SimpleX-ES](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FaJ8O1O8A8GbeoaHTo_V8dcefaCl7ouPb%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEA034qWTA3sWcTsi6aWhNf9BA34vKVCFaEBdP2R66z6Ao%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22wiZ1v_wNjLPlT-nCSB-bRA%3D%3D%22%7D) (Spanish-speaking), [\#SimpleX-FR](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fhpq7_4gGJiilmz5Rf-CswuU5kZGkm_zOIooSw6yALRg%3D%40smp5.simplex.im%2FvIHQDxTor53nwnWWTy5cHNwQQAdWN5Hw%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAPdgK1eBnETmgiqEQufbUkydKBJafoRx4iRrtrC2NAGc%253D%26srv%3Djjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%221FyUryBPza-1ZFFE80Ekbg%3D%3D%22%7D) (French-speaking), [\#SimpleX-RU](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FXZyt3hJmWsycpN7Dqve_wbrAqb6myk1R%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAMFVIoytozTEa_QXOgoZFq_oe0IwZBYKvW50trSFXzXo%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22xz05ngjA3pNIxLZ32a8Vxg%3D%3D%22%7D) (Russian-speaking), [\#SimpleX-IT](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2F0weR-ZgDUl7ruOtI_8TZwEsnJP6UiImA%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAq4PSThO9Fvb5ydF48wB0yNbpzCbuQJCW3vZ9BGUfcxk%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22e-iceLA0SctC62eARgYDWg%3D%3D%22%7D) (Italian-speaking). +[\#SimpleX-DE](https://simplex.chat/contact#/?v=1-4&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FmfiivxDKWFuowXrQOp11jsY8TuP__rBL%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAiz3pKNwvKudckFYMUfgoT0s96B0jfZ7ALHAu7rtE9HQ%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22jZeJpXGrRXQJU_-MSJ_v2A%3D%3D%22%7D) (German-speaking), [\#SimpleX-ES](https://simplex.chat/contact#/?v=2-4&smp=smp%3A%2F%2Fhpq7_4gGJiilmz5Rf-CswuU5kZGkm_zOIooSw6yALRg%3D%40smp5.simplex.im%2FJ5ES83pJimY2BRklS8fvy_iQwIU37xra%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEA0F0STP6UqN_12_k2cjjTrIjFgBGeWhOAmbY1qlk3pnM%253D%26srv%3Djjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22VmUU0fqmYdCRmVCyvStvHA%3D%3D%22%7D) (Spanish-speaking), [\#SimpleX-FR](https://simplex.chat/contact#/?v=2-7&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FxCHBE_6PBRMqNEpm4UQDHXb9cz-mN7dd%23%2F%3Fv%3D1-3%26dh%3DMCowBQYDK2VuAyEAetqlcM7zTCRw-iatnwCrvpJSto7lq5Yv6AsBMWv7GSM%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22foO5Xw4hhjOa_x7zET7otw%3D%3D%22%7D) (French-speaking), [\#SimpleX-RU](https://simplex.chat/contact#/?v=2-4&smp=smp%3A%2F%2Fhpq7_4gGJiilmz5Rf-CswuU5kZGkm_zOIooSw6yALRg%3D%40smp5.simplex.im%2FVXQTB0J2lLjYkgjWByhl6-1qmb5fgZHh%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAI6JaEWezfSwvcoTEkk6au-gkjrXR2ew2OqZYMYBvayk%253D%26srv%3Djjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22ORH9OEe8Duissh-hslfeVg%3D%3D%22%7D) (Russian-speaking), [\#SimpleX-IT](https://simplex.chat/contact#/?v=2-7&smp=smp%3A%2F%2Fhpq7_4gGJiilmz5Rf-CswuU5kZGkm_zOIooSw6yALRg%3D%40smp5.simplex.im%2FqpHu0psOUdYfc11yQCzSyq5JhijrBzZT%23%2F%3Fv%3D1-3%26dh%3DMCowBQYDK2VuAyEACZ_7fbwlM45wl6cGif8cY47oPQ_AMdP0ATqOYLA6zHY%253D%26srv%3Djjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%229uRQRTir3ealdcSfB0zsrw%3D%3D%22%7D) (Italian-speaking). You can join either by opening these links in the app or by opening them in a desktop browser and scanning the QR code. @@ -150,7 +150,7 @@ We would love to have you join the development! You can help us with: - contributing to SimpleX Chat knowledge-base. - developing features - please connect to us via chat so we can help you get started. -## Help us with donations +## Please support us with your donations Huge thank you to everybody who donated to SimpleX Chat! @@ -233,32 +233,24 @@ You can use SimpleX with your own servers and still communicate with people usin Recent and important updates: +[Dec 10, 2024. SimpleX network: preset servers operated by Flux, business chats and more with v6.2 of the apps](./20241210-simplex-network-v6-2-servers-by-flux-business-chats.md) + +[Oct 14, 2024. SimpleX network: security review of protocols design by Trail of Bits, v6.1 released with better calls and user experience.](./blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md) + +[Aug 14, 2024. SimpleX network: the investment from Jack Dorsey and Asymmetric, v6.0 released with the new user experience and private message routing](./blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.md) + [Jun 4, 2024. SimpleX network: private message routing, v5.8 released with IP address protection and chat themes](./blog/20240604-simplex-chat-v5.8-private-message-routing-chat-themes.md) -[Apr 26, 2024. SimpleX network: legally binding transparency, v5.7 released with better calls and messages.](./blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.md) - -[Mar 23, 2024. SimpleX network: real privacy and stable profits, non-profits for protocols, v5.6 released with quantum resistant e2e encryption and simple profile migration.](./blog/20240323-simplex-network-privacy-non-profit-v5-6-quantum-resistant-e2e-encryption-simple-migration.md) - [Mar 14, 2024. SimpleX Chat v5.6 beta: adding quantum resistance to Signal double ratchet algorithm.](./blog/20240314-simplex-chat-v5-6-quantum-resistance-signal-double-ratchet-algorithm.md) -[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). - -[Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md). - -[May 23, 2023. SimpleX Chat: v5.1 released with message reactions and self-destruct passcode](./blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md). - [Apr 22, 2023. SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb](./blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md). [Mar 1, 2023. SimpleX File Transfer Protocol – send large files efficiently, privately and securely, soon to be integrated into SimpleX Chat apps.](./blog/20230301-simplex-file-transfer-protocol.md). [Nov 8, 2022. Security audit by Trail of Bits, the new website and v4.2 released](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). -[Sep 28, 2022. v4.0: encrypted local chat database and many other changes](./blog/20220928-simplex-chat-v4-encrypted-database.md). - [All updates](./blog) ## :zap: Quick installation of a terminal app @@ -298,25 +290,27 @@ What is already implemented: 1. Instead of user profile identifiers used by all other platforms, even the most private ones, SimpleX uses [pairwise per-queue identifiers](./docs/GLOSSARY.md#pairwise-pseudonymous-identifier) (2 addresses for each unidirectional message queue, with an optional 3rd address for push notifications on iOS, 2 queues in each connection between the users). It makes observing the network graph on the application level more difficult, as for `n` users there can be up to `n * (n-1)` message queues. 2. [End-to-end encryption](./docs/GLOSSARY.md#end-to-end-encryption) in each message queue using [NaCl cryptobox](https://nacl.cr.yp.to/box.html). This is added to allow redundancy in the future (passing each message via several servers), to avoid having the same ciphertext in different queues (that would only be visible to the attacker if TLS is compromised). The encryption keys used for this encryption are not rotated, instead we are planning to rotate the queues. Curve25519 keys are used for key negotiation. 3. [Double ratchet](./docs/GLOSSARY.md#double-ratchet-algorithm) end-to-end encryption in each conversation between two users (or group members). This is the same algorithm that is used in Signal and many other messaging apps; it provides OTR messaging with [forward secrecy](./docs/GLOSSARY.md#forward-secrecy) (each message is encrypted by its own ephemeral key) and [break-in recovery](./docs/GLOSSARY.md#post-compromise-security) (the keys are frequently re-negotiated as part of the message exchange). Two pairs of Curve448 keys are used for the initial [key agreement](./docs/GLOSSARY.md#key-agreement-protocol), initiating party passes these keys via the connection link, accepting side - in the header of the confirmation message. -4. Additional layer of encryption using NaCL cryptobox for the messages delivered from the server to the recipient. This layer avoids having any ciphertext in common between sent and received traffic of the server inside TLS (and there are no identifiers in common as well). -5. Several levels of [content padding](./docs/GLOSSARY.md#message-padding) to frustrate message size attacks. -6. All message metadata, including the time when the message was received by the server (rounded to a second) is sent to the recipients inside an encrypted envelope, so even if TLS is compromised it cannot be observed. -7. Only TLS 1.2/1.3 are allowed for client-server connections, limited to cryptographic algorithms: CHACHA20POLY1305_SHA256, Ed25519/Ed448, Curve25519/Curve448. -8. To protect against replay attacks SimpleX servers require [tlsunique channel binding](https://www.rfc-editor.org/rfc/rfc5929.html) as session ID in each client command signed with per-queue ephemeral key. -9. To protect your IP address all SimpleX Chat clients support accessing messaging servers via Tor - see [v3.1 release announcement](./blog/20220808-simplex-chat-v3.1-chat-groups.md) for more details. -10. Local database encryption with passphrase - your contacts, groups and all sent and received messages are stored encrypted. If you used SimpleX Chat before v4.0 you need to enable the encryption via the app settings. -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. +4. [Post-quantum resistant key exchange](./docs/GLOSSARY.md#post-quantum-cryptography) in double ratchet protocol *on every ratchet step*. Read more in [this post](./blog/20240314-simplex-chat-v5-6-quantum-resistance-signal-double-ratchet-algorithm.md) and also see this [publication by Apple]( https://security.apple.com/blog/imessage-pq3/) explaining the need for post-quantum key rotation. +5. Additional layer of encryption using NaCL cryptobox for the messages delivered from the server to the recipient. This layer avoids having any ciphertext in common between sent and received traffic of the server inside TLS (and there are no identifiers in common as well). +6. Several levels of [content padding](./docs/GLOSSARY.md#message-padding) to frustrate message size attacks. +7. All message metadata, including the time when the message was received by the server (rounded to a second) is sent to the recipients inside an encrypted envelope, so even if TLS is compromised it cannot be observed. +8. Only TLS 1.2/1.3 are allowed for client-server connections, limited to cryptographic algorithms: CHACHA20POLY1305_SHA256, Ed25519/Ed448, Curve25519/Curve448. +9. To protect against replay attacks SimpleX servers require [tlsunique channel binding](https://www.rfc-editor.org/rfc/rfc5929.html) as session ID in each client command signed with per-queue ephemeral key. +10. To protect your IP address from unknown messaging relays, and for per-message transport anonymity (compared with Tor/VPN per-connection anonymity), from v6.0 all SimpleX Chat clients use private message routing by default. Read more in [this post](./blog/20240604-simplex-chat-v5.8-private-message-routing-chat-themes.md#private-message-routing). +11. To protect your IP address from unknown file relays, when SOCKS proxy is not enabled SimpleX Chat clients ask for a confirmation before downloading the files from unknown servers. +12. To protect your IP address from known servers all SimpleX Chat clients support accessing messaging servers via Tor - see [v3.1 release announcement](./blog/20220808-simplex-chat-v3.1-chat-groups.md) for more details. +13. Local database encryption with passphrase - your contacts, groups and all sent and received messages are stored encrypted. If you used SimpleX Chat before v4.0 you need to enable the encryption via the app settings. +14. Transport isolation - different TCP connections and Tor circuits are used for traffic of different user profiles, optionally - for different contacts and group member connections. +15. Manual messaging queue rotations to move conversation to another SMP relay. +16. Sending end-to-end encrypted files using [XFTP protocol](https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html). +17. Local files encryption. We plan to add: -1. Senders' SMP relays and recipients' XFTP relays to reduce traffic and conceal IP addresses from the relays chosen, and potentially controlled, by another party. -2. Post-quantum resistant key exchange in double ratchet protocol. -3. Automatic message queue rotation and redundancy. Currently the queues created between two users are used until the queue is manually changed by the user or contact is deleted. We are planning to add automatic queue rotation to make these identifiers temporary and rotate based on some schedule TBC (e.g., every X messages, or every X hours/days). -4. Message "mixing" - adding latency to message delivery, to protect against traffic correlation by message time. -5. Reproducible builds – this is the limitation of the development stack, but we will be investing into solving this problem. Users can still build all applications and services from the source code. +1. Automatic message queue rotation and redundancy. Currently the queues created between two users are used until the queue is manually changed by the user or contact is deleted. We are planning to add automatic queue rotation to make these identifiers temporary and rotate based on some schedule TBC (e.g., every X messages, or every X hours/days). +2. Message "mixing" - adding latency to message delivery, to protect against traffic correlation by message time. +3. Reproducible builds – this is the limitation of the development stack, but we will be investing into solving this problem. Users can still build all applications and services from the source code. +4. Recipients' XFTP relays to reduce traffic and conceal IP addresses from the relays chosen, and potentially controlled, by another party. ## For developers @@ -384,9 +378,11 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A - ✅ Improve sending videos (including encryption of locally stored videos). - ✅ Post-quantum resistant key exchange in double ratchet protocol. - ✅ Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). +- ✅ Support multiple network operators in the app. +- 🏗 Large groups, communities and public channels. +- 🏗 Short links to connect and join groups. - 🏗 Improve stability and reduce battery usage. - 🏗 Improve experience for the new users. -- 🏗 Large groups, communities and public channels. - Privacy & security slider - a simple way to set all settings at once. - SMP queue redundancy and rotation (manual is supported). - Include optional message into connection request sent via contact address. @@ -405,7 +401,9 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A [SimpleX protocols and security model](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md) was reviewed, and had many breaking changes and improvements in v1.0.0. -The security audit was performed in October 2022 by [Trail of Bits](https://www.trailofbits.com/about), and most fixes were released in v4.2.0 – see [the announcement](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). +The implementation security assessment of SimpleX cryptography and networking was done in October 2022 by [Trail of Bits](https://www.trailofbits.com/about) – see [the announcement](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). + +The cryptographic review of SimpleX protocols was done in July 2024 by Trail of Bits – see [the announcement](./blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.md). SimpleX Chat is still a relatively early stage platform (the mobile apps were released in March 2022), so you may discover some bugs and missing features. We would really appreciate if you let us know anything that needs to be fixed or improved. diff --git a/apps/ios/Shared/AppDelegate.swift b/apps/ios/Shared/AppDelegate.swift index d52c950d81..ad8c661e1c 100644 --- a/apps/ios/Shared/AppDelegate.swift +++ b/apps/ios/Shared/AppDelegate.swift @@ -15,35 +15,12 @@ class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { logger.debug("AppDelegate: didFinishLaunchingWithOptions") application.registerForRemoteNotifications() - if #available(iOS 17.0, *) { trackKeyboard() } - NotificationCenter.default.addObserver(self, selector: #selector(pasteboardChanged), name: UIPasteboard.changedNotification, object: nil) removePasscodesIfReinstalled() prepareForLaunch() + deleteOldChatArchive() return true } - @available(iOS 17.0, *) - private func trackKeyboard() { - NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) - } - - @available(iOS 17.0, *) - @objc func keyboardWillShow(_ notification: Notification) { - if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { - ChatModel.shared.keyboardHeight = keyboardFrame.cgRectValue.height - } - } - - @available(iOS 17.0, *) - @objc func keyboardWillHide(_ notification: Notification) { - 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/Assets.xcassets/checkmark.2.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json new file mode 100644 index 0000000000..8e38b499dd --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info": { + "author": "xcode", + "version": 1 + }, + "symbols": [ + { + "filename": "checkmark.2.svg", + "idiom": "universal" + } + ] +} \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg new file mode 100644 index 0000000000..577fa1db76 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.2.symbolset/checkmark.2.svg @@ -0,0 +1,227 @@ + + + checkmark.2 + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + + can be adjusted by modifying the x-location of the margin guidelines. + + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.5.0 + + + Requires Xcode 15 or greater + + + Generated from double.checkmark + + + Typeset at 100.0 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json new file mode 100644 index 0000000000..11a91cb811 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/Contents.json @@ -0,0 +1,12 @@ +{ + "info": { + "author": "xcode", + "version": 1 + }, + "symbols": [ + { + "filename": "checkmark.wide.svg", + "idiom": "universal" + } + ] +} \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg new file mode 100644 index 0000000000..b5dfc6b3de --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/checkmark.wide.symbolset/checkmark.wide.svg @@ -0,0 +1,218 @@ + + + checkmark.wide + + + + + + + Weight/Scale Variations + + + Ultralight + + + Thin + + + Light + + + Regular + + + Medium + + + Semibold + + + Bold + + + Heavy + + + Black + + + + + + + + + + + + + Design Variations + + + Symbols are supported in up to nine weights and three scales. + + + For optimal layout with text and other symbols, vertically align + + + symbols with the adjacent text. + + + + + + + + + Margins + + + Leading and trailing margins on the left and right side of each symbol + + + + can be adjusted by modifying the x-location of the margin guidelines. + + + + Modifications are automatically applied proportionally to all + + + scales and weights. + + + + + + Exporting + + + Symbols should be outlined when exporting to ensure the + + + design is preserved when submitting to Xcode. + + + Template v.5.0 + + + Requires Xcode 15 or greater + + + Generated from double.checkmark + + + Typeset at 100.0 points + + + Small + + + Medium + + + Large + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Contents.json b/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Contents.json new file mode 100644 index 0000000000..d3a15f9a33 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Flux_logo_blue_white.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Flux_logo_blue_white.png b/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Flux_logo_blue_white.png new file mode 100644 index 0000000000..e1d6dda4fe Binary files /dev/null and b/apps/ios/Shared/Assets.xcassets/flux_logo-light.imageset/Flux_logo_blue_white.png differ diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Contents.json b/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Contents.json new file mode 100644 index 0000000000..ad18e60448 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Flux_logo_blue.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Flux_logo_blue.png b/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Flux_logo_blue.png new file mode 100644 index 0000000000..87f1373d75 Binary files /dev/null and b/apps/ios/Shared/Assets.xcassets/flux_logo.imageset/Flux_logo_blue.png differ diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Contents.json b/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Contents.json new file mode 100644 index 0000000000..16686bdf80 --- /dev/null +++ b/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Flux_symbol_blue-white.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Flux_symbol_blue-white.png b/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Flux_symbol_blue-white.png new file mode 100644 index 0000000000..0793b0ee85 Binary files /dev/null and b/apps/ios/Shared/Assets.xcassets/flux_logo_symbol.imageset/Flux_symbol_blue-white.png differ diff --git a/apps/ios/Shared/ContentView.swift b/apps/ios/Shared/ContentView.swift index d93625986e..652258415e 100644 --- a/apps/ios/Shared/ContentView.swift +++ b/apps/ios/Shared/ContentView.swift @@ -9,10 +9,23 @@ import SwiftUI import Intents import SimpleXChat +private enum NoticesSheet: Identifiable { + case whatsNew(updatedConditions: Bool) + case updatedConditions + + var id: String { + switch self { + case .whatsNew: return "whatsNew" + case .updatedConditions: return "updatedConditions" + } + } +} + struct ContentView: View { @EnvironmentObject var chatModel: ChatModel @ObservedObject var alertManager = AlertManager.shared @ObservedObject var callController = CallController.shared + @ObservedObject var appSheetState = AppSheetState.shared @Environment(\.colorScheme) var colorScheme @EnvironmentObject var theme: AppTheme @EnvironmentObject var sceneDelegate: SceneDelegate @@ -29,14 +42,15 @@ struct ContentView: View { @AppStorage(DEFAULT_PERFORM_LA) private var prefPerformLA = false @AppStorage(DEFAULT_PRIVACY_PROTECT_SCREEN) private var protectScreen = false @AppStorage(DEFAULT_NOTIFICATION_ALERT_SHOWN) private var notificationAlertShown = false - @State private var showSettings = false - @State private var showWhatsNew = false + @State private var noticesShown = false + @State private var noticesSheetItem: NoticesSheet? = nil @State private var showChooseLAMode = false @State private var showSetPasscode = false @State private var waitingForOrPassedAuth = true @State private var chatListActionSheet: ChatListActionSheet? = nil + @State private var chatListUserPickerSheet: UserPickerSheet? = nil - private let callTopPadding: CGFloat = 50 + private let callTopPadding: CGFloat = 40 private enum ChatListActionSheet: Identifiable { case planAndConnectSheet(sheet: PlanAndConnectActionSheet) @@ -86,7 +100,7 @@ struct ContentView: View { callView(call) } - if !showSettings, let la = chatModel.laRequest { + if chatListUserPickerSheet == nil, let la = chatModel.laRequest { LocalAuthView(authRequest: la) .onDisappear { // this flag is separate from accessAuthenticated to show initializationView while we wait for authentication @@ -109,9 +123,6 @@ struct ContentView: View { } } .alert(isPresented: $alertManager.presentAlert) { alertManager.alertView! } - .sheet(isPresented: $showSettings) { - SettingsView(showSettings: $showSettings) - } .confirmationDialog("SimpleX Lock mode", isPresented: $showChooseLAMode, titleVisibility: .visible) { Button("System authentication") { initialEnableLA() } Button("Passcode entry") { showSetPasscode = true } @@ -151,12 +162,12 @@ struct ContentView: View { } } .onAppear { - reactOnDarkThemeChanges() + reactOnDarkThemeChanges(systemInDarkThemeCurrently) } .onChange(of: colorScheme) { scheme in // It's needed to update UI colors when iOS wants to make screenshot after going to background, // so when a user changes his global theme from dark to light or back, the app will adapt to it - reactOnDarkThemeChanges() + reactOnDarkThemeChanges(scheme == .dark) } .onChange(of: theme.name) { _ in ThemeManager.adjustWindowStyle() @@ -207,7 +218,7 @@ struct ContentView: View { CallDuration(call: call) } .padding(.horizontal) - .frame(height: callTopPadding - 10) + .frame(height: callTopPadding) .background(Color(uiColor: UIColor(red: 47/255, green: 208/255, blue: 88/255, alpha: 1))) .onTapGesture { chatModel.activeCallViewIsCollapsed = false @@ -253,7 +264,8 @@ struct ContentView: View { private func mainView() -> some View { ZStack(alignment: .top) { - ChatListView(showSettings: $showSettings).privacySensitive(protectScreen) + ChatListView(activeUserPickerSheet: $chatListUserPickerSheet) + .redacted(reason: appSheetState.redactionReasons(protectScreen)) .onAppear { requestNtfAuthorization() // Local Authentication notice is to be shown on next start after onboarding is complete @@ -262,8 +274,15 @@ struct ContentView: View { alertManager.showAlert(laNoticeAlert()) } else if !chatModel.showCallView && CallController.shared.activeCallInvitation == nil { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - if !showWhatsNew { - showWhatsNew = shouldShowWhatsNew() + if !noticesShown { + let showWhatsNew = shouldShowWhatsNew() + let showUpdatedConditions = chatModel.conditions.conditionsAction?.showNotice ?? false + noticesShown = showWhatsNew || showUpdatedConditions + if showWhatsNew { + noticesSheetItem = .whatsNew(updatedConditions: showUpdatedConditions) + } else if showUpdatedConditions { + noticesSheetItem = .updatedConditions + } } } } @@ -271,8 +290,22 @@ struct ContentView: View { connectViaUrl() } .onChange(of: chatModel.appOpenUrl) { _ in connectViaUrl() } - .sheet(isPresented: $showWhatsNew) { - WhatsNewView() + .sheet(item: $noticesSheetItem) { item in + switch item { + case let .whatsNew(updatedConditions): + WhatsNewView(updatedConditions: updatedConditions) + .modifier(ThemedBackground()) + .if(updatedConditions) { v in + v.task { await setConditionsNotified_() } + } + case .updatedConditions: + UsageConditionsView( + currUserServers: Binding.constant([]), + userServers: Binding.constant([]) + ) + .modifier(ThemedBackground(grouped: true)) + .task { await setConditionsNotified_() } + } } if chatModel.setDeliveryReceipts { SetDeliveryReceiptsView() @@ -284,6 +317,15 @@ struct ContentView: View { .onContinueUserActivity("INStartVideoCallIntent", perform: processUserActivity) } + private func setConditionsNotified_() async { + do { + let conditionsId = ChatModel.shared.conditions.currentConditions.conditionsId + try await setConditionsNotified(conditionsId: conditionsId) + } catch let error { + logger.error("setConditionsNotified error: \(responseError(error))") + } + } + private func processUserActivity(_ activity: NSUserActivity) { let intent = activity.interaction?.intent if let intent = intent as? INStartCallIntent { @@ -300,9 +342,18 @@ struct ContentView: View { if let contactId = contacts?.first?.personHandle?.value, let chat = chatModel.getChat(contactId), case let .direct(contact) = chat.chatInfo { - logger.debug("callToRecentContact: schedule call") - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - CallController.shared.startCall(contact, mediaType) + let activeCall = chatModel.activeCall + // This line works when a user clicks on a video button in CallKit UI while in call. + // The app tries to make another call to the same contact and overwite activeCall instance making its state broken + if let activeCall, contactId == activeCall.contact.id, mediaType == .video, !activeCall.hasVideo { + Task { + await chatModel.callCommand.processCommand(.media(source: .camera, enable: true)) + } + } else if activeCall == nil { + logger.debug("callToRecentContact: schedule call") + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + CallController.shared.startCall(contact, mediaType) + } } } } diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 347ffa7a8f..6b6b0ac03f 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -61,7 +61,7 @@ class ItemsModel: ObservableObject { init() { publisher - .throttle(for: 0.25, scheduler: DispatchQueue.main, latest: true) + .throttle(for: 0.2, scheduler: DispatchQueue.main, latest: true) .sink { self.objectWillChange.send() } .store(in: &bag) } @@ -123,6 +123,14 @@ class NetworkModel: ObservableObject { } } +/// ChatItemWithMenu can depend on previous or next item for it's appearance +/// This dummy model is used to force an update of all chat items, +/// when they might have changed appearance. +class ChatItemDummyModel: ObservableObject { + static let shared = ChatItemDummyModel() + func sendUpdate() { objectWillChange.send() } +} + final class ChatModel: ObservableObject { @Published var onboardingStage: OnboardingStage? @Published var setDeliveryReceipts = false @@ -139,11 +147,12 @@ final class ChatModel: ObservableObject { @Published var chatDbEncrypted: Bool? @Published var chatDbStatus: DBMigrationResult? @Published var ctrlInitInProgress: Bool = false + @Published var notificationResponse: UNNotificationResponse? // local authentication @Published var contentViewAccessAuthenticated: Bool = false @Published var laRequest: LocalAuthRequest? // list of chat "previews" - @Published var chats: [Chat] = [] + @Published private(set) var chats: [Chat] = [] @Published var deletedChats: Set = [] // current chat @Published var chatId: String? @@ -183,10 +192,9 @@ final class ChatModel: ObservableObject { @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 @Published var networkInfo = UserNetworkInfo(networkType: .other, online: true) + // usage conditions + @Published var conditions: ServerOperatorConditions = .empty var messageDelivery: Dictionary Void> = [:] @@ -359,25 +367,8 @@ final class ChatModel: ObservableObject { } } - func updateChats(with newChats: [ChatData]) { - for i in 0.. Bool { if let i = getChatItemIndex(cItem) { - withConditionalAnimation { - _updateChatItem(at: i, with: cItem) - } + _updateChatItem(at: i, with: cItem) + ChatItemDummyModel.shared.sendUpdate() return false } else { - withConditionalAnimation(itemAnimation()) { - var ci = cItem - if let status = chatItemStatuses.removeValue(forKey: ci.id), case .sndNew = ci.meta.itemStatus { - ci.meta.itemStatus = status - } - im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0) - im.itemAdded = true + var ci = cItem + if let status = chatItemStatuses.removeValue(forKey: ci.id), case .sndNew = ci.meta.itemStatus { + ci.meta.itemStatus = status } + im.reversedChatItems.insert(ci, at: hasLiveDummy ? 1 : 0) + im.itemAdded = true + ChatItemDummyModel.shared.sendUpdate() return true } @@ -540,7 +529,7 @@ final class ChatModel: ObservableObject { } func updateCurrentUserUiThemes(uiThemes: ThemeModeOverrides?) { - guard var current = currentUser else { return } + guard var current = currentUser, current.uiThemes != uiThemes else { return } current.uiThemes = uiThemes let i = users.firstIndex(where: { $0.user.userId == current.userId }) if let i { @@ -576,6 +565,7 @@ final class ChatModel: ObservableObject { // update preview _updateChat(cInfo.id) { chat in self.decreaseUnreadCounter(user: self.currentUser!, by: chat.chatStats.unreadCount) + self.updateFloatingButtons(unreadCount: 0) chat.chatStats = ChatStats() } // update current chat @@ -592,6 +582,12 @@ final class ChatModel: ObservableObject { } } + private func updateFloatingButtons(unreadCount: Int) { + let fbm = ChatView.FloatingButtonModel.shared + fbm.totalUnread = unreadCount + fbm.objectWillChange.send() + } + func markChatItemsRead(_ cInfo: ChatInfo, aboveItem: ChatItem? = nil) { if let cItem = aboveItem { if chatId == cInfo.id, let i = getChatItemIndex(cItem) { @@ -610,6 +606,7 @@ final class ChatModel: ObservableObject { if markedCount > 0 { chat.chatStats.unreadCount -= markedCount self.decreaseUnreadCounter(user: self.currentUser!, by: markedCount) + self.updateFloatingButtons(unreadCount: chat.chatStats.unreadCount) } } } @@ -639,19 +636,15 @@ final class ChatModel: ObservableObject { } } - func markChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) async { - if chatId == cInfo.id, - let itemIndex = getChatItemIndex(cItem), - im.reversedChatItems[itemIndex].isRcvNew { - await MainActor.run { - withTransaction(Transaction()) { - // update current chat - markChatItemRead_(itemIndex) - // update preview - unreadCollector.changeUnreadCounter(cInfo.id, by: -1) + func markChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID]) { + if self.chatId == cInfo.id { + for itemId in itemIds { + if let i = im.reversedChatItems.firstIndex(where: { $0.id == itemId }) { + markChatItemRead_(i) } } } + self.unreadCollector.changeUnreadCounter(cInfo.id, by: -itemIds.count) } private let unreadCollector = UnreadCollector() @@ -677,9 +670,10 @@ final class ChatModel: ObservableObject { } func changeUnreadCounter(_ chatId: ChatId, by count: Int) { - DispatchQueue.main.async { - self.unreadCounts[chatId] = (self.unreadCounts[chatId] ?? 0) + count + if chatId == ChatModel.shared.chatId { + ChatView.FloatingButtonModel.shared.totalUnread += count } + self.unreadCounts[chatId] = (self.unreadCounts[chatId] ?? 0) + count subject.send() } } @@ -851,7 +845,7 @@ final class ChatModel: ObservableObject { } func dismissConnReqView(_ id: String) { - if id == showingInvitation?.connId { + if id == showingInvitation?.pcc.id { markShowingInvitationUsed() dismissAllSheets() } @@ -901,39 +895,10 @@ final class ChatModel: ObservableObject { _ = upsertGroupMember(groupInfo, updatedMember) } } - - func unreadChatItemCounts(itemsInView: Set) -> UnreadChatItemCounts { - var i = 0 - var totalBelow = 0 - var unreadBelow = 0 - while i < im.reversedChatItems.count - 1 && !itemsInView.contains(im.reversedChatItems[i].viewId) { - totalBelow += 1 - if im.reversedChatItems[i].isRcvNew { - unreadBelow += 1 - } - i += 1 - } - return UnreadChatItemCounts( - // TODO these thresholds account for the fact that items are still "visible" while - // covered by compose area, they should be replaced with the actual height in pixels below the screen. - isNearBottom: totalBelow < 15, - isReallyNearBottom: totalBelow < 2, - unreadBelow: unreadBelow - ) - } - - func topItemInView(itemsInView: Set) -> ChatItem? { - let maxIx = im.reversedChatItems.count - 1 - var i = 0 - let inView = { itemsInView.contains(self.im.reversedChatItems[$0].viewId) } - while i < maxIx && !inView(i) { i += 1 } - while i < maxIx && inView(i) { i += 1 } - return im.reversedChatItems[min(i - 1, maxIx)] - } } struct ShowingInvitation { - var connId: String + var pcc: PendingContactConnection var connChatUsed: Bool } @@ -942,12 +907,6 @@ struct NTFContactRequest { var chatId: String } -struct UnreadChatItemCounts: Equatable { - var isNearBottom: Bool - var isReallyNearBottom: Bool - var unreadBelow: Int -} - final class Chat: ObservableObject, Identifiable, ChatLike { @Published var chatInfo: ChatInfo @Published var chatItems: [ChatItem] diff --git a/apps/ios/Shared/Model/NtfManager.swift b/apps/ios/Shared/Model/NtfManager.swift index 95063845f1..6c33031eeb 100644 --- a/apps/ios/Shared/Model/NtfManager.swift +++ b/apps/ios/Shared/Model/NtfManager.swift @@ -26,20 +26,37 @@ enum NtfCallAction { class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject { static let shared = NtfManager() + public var navigatingToChat = false private var granted = false private var prevNtfTime: Dictionary = [:] + override init() { + super.init() + UNUserNotificationCenter.current().delegate = self + } + // Handle notification when app is in background func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler handler: () -> Void) { logger.debug("NtfManager.userNotificationCenter: didReceive") - let content = response.notification.request.content + if appStateGroupDefault.get() == .active { + processNotificationResponse(response) + } else { + logger.debug("NtfManager.userNotificationCenter: remember response in model") + ChatModel.shared.notificationResponse = response + } + handler() + } + + func processNotificationResponse(_ ntfResponse: UNNotificationResponse) { let chatModel = ChatModel.shared - let action = response.actionIdentifier - logger.debug("NtfManager.userNotificationCenter: didReceive: action \(action), categoryIdentifier \(content.categoryIdentifier)") + let content = ntfResponse.notification.request.content + let action = ntfResponse.actionIdentifier + logger.debug("NtfManager.processNotificationResponse: didReceive: action \(action), categoryIdentifier \(content.categoryIdentifier)") if let userId = content.userInfo["userId"] as? Int64, userId != chatModel.currentUser?.userId { + logger.debug("NtfManager.processNotificationResponse changeActiveUser") changeActiveUser(userId, viewPwd: nil) } if content.categoryIdentifier == ntfCategoryContactRequest && (action == ntfActionAcceptContact || action == ntfActionAcceptContactIncognito), @@ -58,10 +75,12 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject { } } else { if let chatId = content.targetContentIdentifier { - ItemsModel.shared.loadOpenChat(chatId) + self.navigatingToChat = true + ItemsModel.shared.loadOpenChat(chatId) { + self.navigatingToChat = false + } } } - handler() } private func ntfCallAction(_ content: UNNotificationContent, _ action: String) -> (ChatId, NtfCallAction)? { @@ -76,7 +95,6 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject { return nil } - // Handle notification when the app is in foreground func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, @@ -185,6 +203,12 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject { actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: NSLocalizedString("SimpleX encrypted message or connection event", comment: "notification") + ), + UNNotificationCategory( + identifier: ntfCategoryManyEvents, + actions: [], + intentIdentifiers: [], + hiddenPreviewsBodyPlaceholder: NSLocalizedString("New events", comment: "notification") ) ]) } @@ -210,29 +234,28 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject { } } } - center.delegate = self } func notifyContactRequest(_ user: any UserLike, _ contactRequest: UserContactRequest) { logger.debug("NtfManager.notifyContactRequest") - addNotification(createContactRequestNtf(user, contactRequest)) + addNotification(createContactRequestNtf(user, contactRequest, 0)) } func notifyContactConnected(_ user: any UserLike, _ contact: Contact) { logger.debug("NtfManager.notifyContactConnected") - addNotification(createContactConnectedNtf(user, contact)) + addNotification(createContactConnectedNtf(user, contact, 0)) } func notifyMessageReceived(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) { logger.debug("NtfManager.notifyMessageReceived") if cInfo.ntfsEnabled { - addNotification(createMessageReceivedNtf(user, cInfo, cItem)) + addNotification(createMessageReceivedNtf(user, cInfo, cItem, 0)) } } func notifyCallInvitation(_ invitation: RcvCallInvitation) { logger.debug("NtfManager.notifyCallInvitation") - addNotification(createCallInvitationNtf(invitation)) + addNotification(createCallInvitationNtf(invitation, 0)) } func setNtfBadgeCount(_ count: Int) { diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 76d043b2aa..51be3191ec 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -112,9 +112,9 @@ func chatSendCmdSync(_ cmd: ChatCommand, bgTask: Bool = true, bgDelay: Double? = return resp } -func chatSendCmd(_ cmd: ChatCommand, bgTask: Bool = true, bgDelay: Double? = nil, _ ctrl: chat_ctrl? = nil) async -> ChatResponse { +func chatSendCmd(_ cmd: ChatCommand, bgTask: Bool = true, bgDelay: Double? = nil, _ ctrl: chat_ctrl? = nil, log: Bool = true) async -> ChatResponse { await withCheckedContinuation { cont in - cont.resume(returning: chatSendCmdSync(cmd, bgTask: bgTask, bgDelay: bgDelay, ctrl)) + cont.resume(returning: chatSendCmdSync(cmd, bgTask: bgTask, bgDelay: bgDelay, ctrl, log: log)) } } @@ -332,13 +332,15 @@ func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, sear throw r } -func loadChat(chat: Chat, search: String = "") async { +func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async { do { let cInfo = chat.chatInfo let m = ChatModel.shared let im = ItemsModel.shared m.chatItemStatuses = [:] - await MainActor.run { im.reversedChatItems = [] } + if clearItems { + await MainActor.run { im.reversedChatItems = [] } + } let chat = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search) await MainActor.run { im.reversedChatItems = chat.chatItems.reversed() @@ -355,17 +357,23 @@ func apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) async throws - throw r } -func apiForwardChatItem(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemId: Int64, ttl: Int?) async -> ChatItem? { - let cmd: ChatCommand = .apiForwardChatItem(toChatType: toChatType, toChatId: toChatId, fromChatType: fromChatType, fromChatId: fromChatId, itemId: itemId, ttl: ttl) +func apiPlanForwardChatItems(type: ChatType, id: Int64, itemIds: [Int64]) async throws -> ([Int64], ForwardConfirmation?) { + let r = await chatSendCmd(.apiPlanForwardChatItems(toChatType: type, toChatId: id, itemIds: itemIds)) + if case let .forwardPlan(_, chatItemIds, forwardConfimation) = r { return (chatItemIds, forwardConfimation) } + throw r +} + +func apiForwardChatItems(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemIds: [Int64], ttl: Int?) async -> [ChatItem]? { + let cmd: ChatCommand = .apiForwardChatItems(toChatType: toChatType, toChatId: toChatId, fromChatType: fromChatType, fromChatId: fromChatId, itemIds: itemIds, ttl: ttl) return await processSendMessageCmd(toChatType: toChatType, cmd: cmd) } -func apiSendMessage(type: ChatType, id: Int64, file: CryptoFile?, quotedItemId: Int64?, msg: MsgContent, live: Bool = false, ttl: Int? = nil) async -> ChatItem? { - let cmd: ChatCommand = .apiSendMessage(type: type, id: id, file: file, quotedItemId: quotedItemId, msg: msg, live: live, ttl: ttl) +func apiSendMessages(type: ChatType, id: Int64, live: Bool = false, ttl: Int? = nil, composedMessages: [ComposedMessage]) async -> [ChatItem]? { + let cmd: ChatCommand = .apiSendMessages(type: type, id: id, live: live, ttl: ttl, composedMessages: composedMessages) return await processSendMessageCmd(toChatType: type, cmd: cmd) } -private func processSendMessageCmd(toChatType: ChatType, cmd: ChatCommand) async -> ChatItem? { +private func processSendMessageCmd(toChatType: ChatType, cmd: ChatCommand) async -> [ChatItem]? { let chatModel = ChatModel.shared let r: ChatResponse if toChatType == .direct { @@ -378,10 +386,13 @@ private func processSendMessageCmd(toChatType: ChatType, cmd: ChatCommand) async } }) r = await chatSendCmd(cmd, bgTask: false) - if case let .newChatItem(_, aChatItem) = r { - cItem = aChatItem.chatItem - chatModel.messageDelivery[aChatItem.chatItem.id] = endTask - return cItem + if case let .newChatItems(_, aChatItems) = r { + let cItems = aChatItems.map { $0.chatItem } + if let cItemLast = cItems.last { + cItem = cItemLast + chatModel.messageDelivery[cItemLast.id] = endTask + } + return cItems } if let networkErrorAlert = networkErrorAlert(r) { AlertManager.shared.showAlert(networkErrorAlert) @@ -392,18 +403,18 @@ private func processSendMessageCmd(toChatType: ChatType, cmd: ChatCommand) async return nil } else { r = await chatSendCmd(cmd, bgDelay: msgDelay) - if case let .newChatItem(_, aChatItem) = r { - return aChatItem.chatItem + if case let .newChatItems(_, aChatItems) = r { + return aChatItems.map { $0.chatItem } } sendMessageErrorAlert(r) return nil } } -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) +func apiCreateChatItems(noteFolderId: Int64, composedMessages: [ComposedMessage]) async -> [ChatItem]? { + let r = await chatSendCmd(.apiCreateChatItems(noteFolderId: noteFolderId, composedMessages: composedMessages)) + if case let .newChatItems(_, aChatItems) = r { return aChatItems.map { $0.chatItem } } + createChatItemsErrorAlert(r) return nil } @@ -415,8 +426,8 @@ private func sendMessageErrorAlert(_ r: ChatResponse) { ) } -private func createChatItemErrorAlert(_ r: ChatResponse) { - logger.error("apiCreateChatItem error: \(String(describing: r))") +private func createChatItemsErrorAlert(_ r: ChatResponse) { + logger.error("apiCreateChatItems error: \(String(describing: r))") AlertManager.shared.showAlertMsg( title: "Error creating message", message: "Error: \(responseError(r))" @@ -435,6 +446,13 @@ func apiChatItemReaction(type: ChatType, id: Int64, itemId: Int64, add: Bool, re throw r } +func apiGetReactionMembers(groupId: Int64, itemId: Int64, reaction: MsgReaction) async throws -> [MemberReaction] { + let userId = try currentUserId("apiGetReactionMemebers") + let r = await chatSendCmd(.apiGetReactionMembers(userId: userId, groupId: groupId, itemId: itemId, reaction: reaction )) + if case let .reactionMembers(_, memberReactions) = r { return memberReactions } + throw r +} + func apiDeleteChatItems(type: ChatType, id: Int64, itemIds: [Int64], mode: CIDeleteMode) async throws -> [ChatItemDeletion] { let r = await chatSendCmd(.apiDeleteChatItem(type: type, id: id, itemIds: itemIds, mode: mode), bgDelay: msgDelay) if case let .chatItemsDeleted(_, items, _) = r { return items } @@ -451,7 +469,7 @@ func apiGetNtfToken() -> (DeviceToken?, NtfTknStatus?, NotificationsMode, String let r = chatSendCmdSync(.apiGetNtfToken) switch r { case let .ntfToken(token, status, ntfMode, ntfServer): return (token, status, ntfMode, ntfServer) - case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED))): return (nil, nil, .off, nil) + case .chatCmdError(_, .errorAgent(.CMD(.PROHIBITED, _))): return (nil, nil, .off, nil) default: logger.debug("apiGetNtfToken response: \(String(describing: r))") return (nil, nil, .off, nil) @@ -489,18 +507,6 @@ func apiDeleteToken(token: DeviceToken) async throws { try await sendCommandOkResp(.apiDeleteToken(token: token)) } -func getUserProtoServers(_ serverProtocol: ServerProtocol) throws -> UserProtoServers { - let userId = try currentUserId("getUserProtoServers") - let r = chatSendCmdSync(.apiGetUserProtoServers(userId: userId, serverProtocol: serverProtocol)) - if case let .userProtoServers(_, servers) = r { return servers } - throw r -} - -func setUserProtoServers(_ serverProtocol: ServerProtocol, servers: [ServerCfg]) async throws { - let userId = try currentUserId("setUserProtoServers") - try await sendCommandOkResp(.apiSetUserProtoServers(userId: userId, serverProtocol: serverProtocol, servers: servers)) -} - func testProtoServer(server: String) async throws -> Result<(), ProtocolTestFailure> { let userId = try currentUserId("testProtoServer") let r = await chatSendCmd(.apiTestProtoServer(userId: userId, server: server)) @@ -513,6 +519,72 @@ func testProtoServer(server: String) async throws -> Result<(), ProtocolTestFail throw r } +func getServerOperators() async throws -> ServerOperatorConditions { + let r = await chatSendCmd(.apiGetServerOperators) + if case let .serverOperatorConditions(conditions) = r { return conditions } + logger.error("getServerOperators error: \(String(describing: r))") + throw r +} + +func getServerOperatorsSync() throws -> ServerOperatorConditions { + let r = chatSendCmdSync(.apiGetServerOperators) + if case let .serverOperatorConditions(conditions) = r { return conditions } + logger.error("getServerOperators error: \(String(describing: r))") + throw r +} + +func setServerOperators(operators: [ServerOperator]) async throws -> ServerOperatorConditions { + let r = await chatSendCmd(.apiSetServerOperators(operators: operators)) + if case let .serverOperatorConditions(conditions) = r { return conditions } + logger.error("setServerOperators error: \(String(describing: r))") + throw r +} + +func getUserServers() async throws -> [UserOperatorServers] { + let userId = try currentUserId("getUserServers") + let r = await chatSendCmd(.apiGetUserServers(userId: userId)) + if case let .userServers(_, userServers) = r { return userServers } + logger.error("getUserServers error: \(String(describing: r))") + throw r +} + +func setUserServers(userServers: [UserOperatorServers]) async throws { + let userId = try currentUserId("setUserServers") + let r = await chatSendCmd(.apiSetUserServers(userId: userId, userServers: userServers)) + if case .cmdOk = r { return } + logger.error("setUserServers error: \(String(describing: r))") + throw r +} + +func validateServers(userServers: [UserOperatorServers]) async throws -> [UserServersError] { + let userId = try currentUserId("validateServers") + let r = await chatSendCmd(.apiValidateServers(userId: userId, userServers: userServers)) + if case let .userServersValidation(_, serverErrors) = r { return serverErrors } + logger.error("validateServers error: \(String(describing: r))") + throw r +} + +func getUsageConditions() async throws -> (UsageConditions, String?, UsageConditions?) { + let r = await chatSendCmd(.apiGetUsageConditions) + if case let .usageConditions(usageConditions, conditionsText, acceptedConditions) = r { return (usageConditions, conditionsText, acceptedConditions) } + logger.error("getUsageConditions error: \(String(describing: r))") + throw r +} + +func setConditionsNotified(conditionsId: Int64) async throws { + let r = await chatSendCmd(.apiSetConditionsNotified(conditionsId: conditionsId)) + if case .cmdOk = r { return } + logger.error("setConditionsNotified error: \(String(describing: r))") + throw r +} + +func acceptConditions(conditionsId: Int64, operatorIds: [Int64]) async throws -> ServerOperatorConditions { + let r = await chatSendCmd(.apiAcceptConditions(conditionsId: conditionsId, operatorIds: operatorIds)) + if case let .serverOperatorConditions(conditions) = r { return conditions } + logger.error("acceptConditions error: \(String(describing: r))") + throw r +} + func getChatItemTTL() throws -> ChatItemTTL { let userId = try currentUserId("getChatItemTTL") return try chatItemTTLResponse(chatSendCmdSync(.apiGetChatItemTTL(userId: userId))) @@ -574,19 +646,25 @@ func apiContactInfo(_ contactId: Int64) async throws -> (ConnectionStats?, Profi throw r } -func apiGroupMemberInfo(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, ConnectionStats?) { +func apiGroupMemberInfoSync(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, ConnectionStats?) { let r = chatSendCmdSync(.apiGroupMemberInfo(groupId: groupId, groupMemberId: groupMemberId)) if case let .groupMemberInfo(_, _, member, connStats_) = r { return (member, connStats_) } throw r } -func apiContactQueueInfo(_ contactId: Int64) async throws -> (RcvMsgInfo?, QueueInfo) { +func apiGroupMemberInfo(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (GroupMember, ConnectionStats?) { + let r = await chatSendCmd(.apiGroupMemberInfo(groupId: groupId, groupMemberId: groupMemberId)) + if case let .groupMemberInfo(_, _, member, connStats_) = r { return (member, connStats_) } + throw r +} + +func apiContactQueueInfo(_ contactId: Int64) async throws -> (RcvMsgInfo?, ServerQueueInfo) { let r = await chatSendCmd(.apiContactQueueInfo(contactId: contactId)) if case let .queueInfo(_, rcvMsgInfo, queueInfo) = r { return (rcvMsgInfo, queueInfo) } throw r } -func apiGroupMemberQueueInfo(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (RcvMsgInfo?, QueueInfo) { +func apiGroupMemberQueueInfo(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (RcvMsgInfo?, ServerQueueInfo) { let r = await chatSendCmd(.apiGroupMemberQueueInfo(groupId: groupId, groupMemberId: groupMemberId)) if case let .queueInfo(_, rcvMsgInfo, queueInfo) = r { return (rcvMsgInfo, queueInfo) } throw r @@ -634,8 +712,8 @@ func apiGetContactCode(_ contactId: Int64) async throws -> (Contact, String) { throw r } -func apiGetGroupMemberCode(_ groupId: Int64, _ groupMemberId: Int64) throws -> (GroupMember, String) { - let r = chatSendCmdSync(.apiGetGroupMemberCode(groupId: groupId, groupMemberId: groupMemberId)) +func apiGetGroupMemberCode(_ groupId: Int64, _ groupMemberId: Int64) async throws -> (GroupMember, String) { + let r = await chatSendCmd(.apiGetGroupMemberCode(groupId: groupId, groupMemberId: groupMemberId)) if case let .groupMemberCode(_, _, member, connectionCode) = r { return (member, connectionCode) } throw r } @@ -671,6 +749,13 @@ func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> P throw r } +func apiChangeConnectionUser(connId: Int64, userId: Int64) async throws -> PendingContactConnection? { + let r = await chatSendCmd(.apiChangeConnectionUser(connId: connId, userId: userId)) + + if case let .connectionUserChanged(_, _, toConnection, _) = r {return toConnection} + throw r +} + func apiConnectPlan(connReq: String) async throws -> ConnectionPlan { let userId = try currentUserId("apiConnectPlan") let r = await chatSendCmd(.apiConnectPlan(userId: userId, connReq: connReq)) @@ -719,6 +804,12 @@ func apiConnect_(incognito: Bool, connReq: String) async -> ((ConnReqType, Pendi message: "Unless your contact deleted the connection or this link was already used, it might be a bug - please report it.\nTo connect, please ask your contact to create another connection link and check that you have a stable network connection." ) return (nil, alert) + case .chatCmdError(_, .errorAgent(.SMP(_, .QUOTA))): + let alert = mkAlert( + title: "Undelivered messages", + message: "The connection reached the limit of undelivered messages, your contact may be offline." + ) + return (nil, alert) case let .chatCmdError(_, .errorAgent(.INTERNAL(internalErr))): if internalErr == "SEUniqueID" { let alert = mkAlert( @@ -984,8 +1075,12 @@ func apiRejectContactRequest(contactReqId: Int64) async throws { throw r } -func apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64)) async throws { - try await sendCommandOkResp(.apiChatRead(type: type, id: id, itemRange: itemRange)) +func apiChatRead(type: ChatType, id: Int64) async throws { + try await sendCommandOkResp(.apiChatRead(type: type, id: id)) +} + +func apiChatItemsRead(type: ChatType, id: Int64, itemIds: [Int64]) async throws { + try await sendCommandOkResp(.apiChatItemsRead(type: type, id: id, itemIds: itemIds)) } func apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) async throws { @@ -1023,77 +1118,122 @@ func standaloneFileInfo(url: String, ctrl: chat_ctrl? = nil) async -> MigrationF } func receiveFile(user: any UserLike, fileId: Int64, userApprovedRelays: Bool = false, auto: Bool = false) async { - if let chatItem = await apiReceiveFile( - fileId: fileId, - userApprovedRelays: userApprovedRelays || !privacyAskToApproveRelaysGroupDefault.get(), - encrypted: privacyEncryptLocalFilesGroupDefault.get(), + await receiveFiles( + user: user, + fileIds: [fileId], + userApprovedRelays: userApprovedRelays, auto: auto - ) { - await chatItemSimpleUpdate(user, chatItem) - } + ) } -func apiReceiveFile(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool, inline: Bool? = nil, auto: Bool = false) async -> AChatItem? { - let r = await chatSendCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline)) - let am = AlertManager.shared - if case let .rcvFileAccepted(_, chatItem) = r { return chatItem } - if case .rcvFileAcceptedSndCancelled = r { - logger.debug("apiReceiveFile error: sender cancelled file transfer") - if !auto { - am.showAlertMsg( - title: "Cannot receive file", - message: "Sender cancelled file transfer." +func receiveFiles(user: any UserLike, fileIds: [Int64], userApprovedRelays: Bool = false, auto: Bool = false) async { + var fileIdsToApprove = [Int64]() + var srvsToApprove = Set() + var otherFileErrs = [ChatResponse]() + + for fileId in fileIds { + let r = await chatSendCmd( + .receiveFile( + fileId: fileId, + userApprovedRelays: userApprovedRelays || !privacyAskToApproveRelaysGroupDefault.get(), + encrypted: privacyEncryptLocalFilesGroupDefault.get(), + inline: nil ) + ) + switch r { + case let .rcvFileAccepted(_, chatItem): + await chatItemSimpleUpdate(user, chatItem) + default: + if let chatError = chatError(r) { + switch chatError { + case let .fileNotApproved(fileId, unknownServers): + fileIdsToApprove.append(fileId) + srvsToApprove.formUnion(unknownServers) + default: + otherFileErrs.append(r) + } + } } - } else if let networkErrorAlert = networkErrorAlert(r) { - logger.error("apiReceiveFile network error: \(String(describing: r))") - if !auto { - am.showAlert(networkErrorAlert) + } + + if !auto { + let otherErrsStr = if otherFileErrs.isEmpty { + "" + } else if otherFileErrs.count == 1 { + "\(otherFileErrs[0])" + } else if otherFileErrs.count == 2 { + "\(otherFileErrs[0])\n\(otherFileErrs[1])" + } else { + "\(otherFileErrs[0])\n\(otherFileErrs[1])\nand \(otherFileErrs.count - 2) other error(s)" } - } else { - switch chatError(r) { - case .fileCancelled: - logger.debug("apiReceiveFile ignoring fileCancelled error") - case .fileAlreadyReceiving: - logger.debug("apiReceiveFile ignoring fileAlreadyReceiving error") - case let .fileNotApproved(fileId, unknownServers): - logger.debug("apiReceiveFile fileNotApproved error") - if !auto { - let srvs = unknownServers.map { s in + + // If there are not approved files, alert is shown the same way both in case of singular and plural files reception + if !fileIdsToApprove.isEmpty { + let srvs = srvsToApprove + .map { s in if let srv = parseServerAddress(s), !srv.hostnames.isEmpty { srv.hostnames[0] } else { serverHost(s) } } - am.showAlert(Alert( - title: Text("Unknown servers!"), - message: Text("Without Tor or VPN, your IP address will be visible to these XFTP relays: \(srvs.sorted().joined(separator: ", "))."), - primaryButton: .default( - Text("Download"), - action: { - Task { - logger.debug("apiReceiveFile fileNotApproved alert - in Task") - if let user = ChatModel.shared.currentUser { - await receiveFile(user: user, fileId: fileId, userApprovedRelays: true) - } + .sorted() + .joined(separator: ", ") + let fIds = fileIdsToApprove + await MainActor.run { + showAlert( + title: NSLocalizedString("Unknown servers!", comment: "alert title"), + message: ( + String.localizedStringWithFormat(NSLocalizedString("Without Tor or VPN, your IP address will be visible to these XFTP relays: %@.", comment: "alert message"), srvs) + + (otherErrsStr != "" ? "\n\n" + String.localizedStringWithFormat(NSLocalizedString("Other file errors:\n%@", comment: "alert message"), otherErrsStr) : "") + ), + buttonTitle: NSLocalizedString("Download", comment: "alert button"), + buttonAction: { + Task { + logger.debug("apiReceiveFile fileNotApproved alert - in Task") + if let user = ChatModel.shared.currentUser { + await receiveFiles(user: user, fileIds: fIds, userApprovedRelays: true) } } - ), - secondaryButton: .cancel() - )) + }, + cancelButton: true + ) } - default: - logger.error("apiReceiveFile error: \(String(describing: r))") - if !auto { - am.showAlertMsg( - title: "Error receiving file", - message: "Error: \(responseError(r))" + } else if otherFileErrs.count == 1 { // If there is a single other error, we differentiate on it + let errorResponse = otherFileErrs.first! + switch errorResponse { + case let .rcvFileAcceptedSndCancelled(_, rcvFileTransfer): + logger.debug("receiveFiles error: sender cancelled file transfer \(rcvFileTransfer.fileId)") + await MainActor.run { + showAlert( + NSLocalizedString("Cannot receive file", comment: "alert title"), + message: NSLocalizedString("Sender cancelled file transfer.", comment: "alert message") + ) + } + default: + if let chatError = chatError(errorResponse) { + switch chatError { + case .fileCancelled, .fileAlreadyReceiving: + logger.debug("receiveFiles ignoring FileCancelled or FileAlreadyReceiving error") + default: + await MainActor.run { + showAlert( + NSLocalizedString("Error receiving file", comment: "alert title"), + message: responseError(errorResponse) + ) + } + } + } + } + } else if otherFileErrs.count > 1 { // If there are multiple other errors, we show general alert + await MainActor.run { + showAlert( + NSLocalizedString("Error receiving file", comment: "alert title"), + message: String.localizedStringWithFormat(NSLocalizedString("File errors:\n%@", comment: "alert message"), otherErrsStr) ) } } } - return nil } func cancelFile(user: User, fileId: Int64) async { @@ -1216,12 +1356,18 @@ func apiEndCall(_ contact: Contact) async throws { try await sendCommandOkResp(.apiEndCall(contact: contact)) } -func apiGetCallInvitations() throws -> [RcvCallInvitation] { +func apiGetCallInvitationsSync() throws -> [RcvCallInvitation] { let r = chatSendCmdSync(.apiGetCallInvitations) if case let .callInvitations(invs) = r { return invs } throw r } +func apiGetCallInvitations() async throws -> [RcvCallInvitation] { + let r = await chatSendCmd(.apiGetCallInvitations) + if case let .callInvitations(invs) = r { return invs } + throw r +} + func apiCallStatus(_ contact: Contact, _ status: String) async throws { if let callStatus = WebRTCCallStatus.init(rawValue: status) { try await sendCommandOkResp(.apiCallStatus(contact: contact, callStatus: callStatus)) @@ -1236,15 +1382,13 @@ func apiGetNetworkStatuses() throws -> [ConnNetworkStatus] { throw r } -func markChatRead(_ chat: Chat, aboveItem: ChatItem? = nil) async { +func markChatRead(_ chat: Chat) async { do { if chat.chatStats.unreadCount > 0 { - let minItemId = chat.chatStats.minUnreadItemId - let itemRange = (minItemId, aboveItem?.id ?? chat.chatItems.last?.id ?? minItemId) let cInfo = chat.chatInfo - try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId, itemRange: itemRange) + try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId) await MainActor.run { - withAnimation { ChatModel.shared.markChatItemsRead(cInfo, aboveItem: aboveItem) } + withAnimation { ChatModel.shared.markChatItemsRead(cInfo) } } } if chat.chatStats.unreadChat { @@ -1267,13 +1411,14 @@ func markChatUnread(_ chat: Chat, unreadChat: Bool = true) async { } } -func apiMarkChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) async { +func apiMarkChatItemsRead(_ cInfo: ChatInfo, _ itemIds: [ChatItem.ID]) async { do { - logger.debug("apiMarkChatItemRead: \(cItem.id)") - try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId, itemRange: (cItem.id, cItem.id)) - await ChatModel.shared.markChatItemRead(cInfo, cItem) + try await apiChatItemsRead(type: cInfo.chatType, id: cInfo.apiId, itemIds: itemIds) + DispatchQueue.main.async { + ChatModel.shared.markChatItemsRead(cInfo, itemIds) + } } catch { - logger.error("apiMarkChatItemRead apiChatRead error: \(responseError(error))") + logger.error("apiChatItemsRead error: \(responseError(error))") } } @@ -1418,9 +1563,9 @@ func apiGetVersion() throws -> CoreVersionInfo { throw r } -func getAgentSubsTotal() throws -> (SMPServerSubs, Bool) { +func getAgentSubsTotal() async throws -> (SMPServerSubs, Bool) { let userId = try currentUserId("getAgentSubsTotal") - let r = chatSendCmdSync(.getAgentSubsTotal(userId: userId), log: false) + let r = await chatSendCmd(.getAgentSubsTotal(userId: userId), log: false) if case let .agentSubsTotal(_, subsTotal, hasSession) = r { return (subsTotal, hasSession) } logger.error("getAgentSubsTotal error: \(String(describing: r))") throw r @@ -1461,6 +1606,16 @@ func initializeChat(start: Bool, confirmStart: Bool = false, dbKey: String? = ni try apiSetEncryptLocalFiles(privacyEncryptLocalFilesGroupDefault.get()) m.chatInitialized = true m.currentUser = try apiGetActiveUser() + m.conditions = try getServerOperatorsSync() + if shouldImportAppSettingsDefault.get() { + do { + let appSettings = try apiGetAppSettings(settings: AppSettings.current.prepareForExport()) + appSettings.importIntoApp() + shouldImportAppSettingsDefault.set(false) + } catch { + logger.error("Error while importing app settings: \(error)") + } + } if m.currentUser == nil { onboardingStageDefault.set(.step1_SimpleXInfo) privacyDeliveryReceiptsSet.set(true) @@ -1505,7 +1660,7 @@ private func chatInitialized(start: Bool, refreshInvitations: Bool) throws { } } -func startChat(refreshInvitations: Bool = true) throws { +func startChat(refreshInvitations: Bool = true, onboarding: Bool = false) throws { logger.debug("startChat") let m = ChatModel.shared try setNetworkConfig(getNetCfg()) @@ -1515,7 +1670,7 @@ func startChat(refreshInvitations: Bool = true) throws { try getUserChatData() NtfManager.shared.setNtfBadgeCount(m.totalUnreadCountForAllUsers()) if (refreshInvitations) { - try refreshCallInvitations() + Task { try await refreshCallInvitations() } } (m.savedToken, m.tokenStatus, m.notificationMode, m.notificationServer) = apiGetNtfToken() _ = try apiStartChat() @@ -1524,13 +1679,15 @@ func startChat(refreshInvitations: Bool = true) throws { if let token = m.deviceToken { registerToken(token: token) } - withAnimation { - let savedOnboardingStage = onboardingStageDefault.get() - m.onboardingStage = [.step1_SimpleXInfo, .step2_CreateProfile].contains(savedOnboardingStage) && m.users.count == 1 - ? .step3_CreateSimpleXAddress - : savedOnboardingStage - if m.onboardingStage == .onboardingComplete && !privacyDeliveryReceiptsSet.get() { - m.setDeliveryReceipts = true + if !onboarding { + withAnimation { + let savedOnboardingStage = onboardingStageDefault.get() + m.onboardingStage = [.step1_SimpleXInfo, .step2_CreateProfile].contains(savedOnboardingStage) && m.users.count == 1 + ? .step3_ChooseServerOperators + : savedOnboardingStage + if m.onboardingStage == .onboardingComplete && !privacyDeliveryReceiptsSet.get() { + m.setDeliveryReceipts = true + } } } } @@ -1589,8 +1746,7 @@ func getUserChatData() throws { m.userAddress = try apiGetUserAddress() m.chatItemTTL = try getChatItemTTL() let chats = try apiGetChats() - m.chats = chats.map { Chat.init($0) } - m.popChatCollector.clear() + m.updateChats(chats) } private func getUserChatDataAsync() async throws { @@ -1602,14 +1758,12 @@ private func getUserChatDataAsync() async throws { await MainActor.run { m.userAddress = userAddress m.chatItemTTL = chatItemTTL - m.chats = chats.map { Chat.init($0) } - m.popChatCollector.clear() + m.updateChats(chats) } } else { await MainActor.run { m.userAddress = nil - m.chats = [] - m.popChatCollector.clear() + m.updateChats([]) } } } @@ -1770,36 +1924,45 @@ func processReceivedMsg(_ res: ChatResponse) async { n.networkStatuses = ns } } - case let .newChatItem(user, aChatItem): - let cInfo = aChatItem.chatInfo - let cItem = aChatItem.chatItem - await MainActor.run { - if active(user) { - m.addChatItem(cInfo, cItem) - } else if cItem.isRcvNew && cInfo.ntfsEnabled { - m.increaseUnreadCounter(user: user) + case let .newChatItems(user, chatItems): + for chatItem in chatItems { + let cInfo = chatItem.chatInfo + let cItem = chatItem.chatItem + await MainActor.run { + if active(user) { + m.addChatItem(cInfo, cItem) + } else if cItem.isRcvNew && cInfo.ntfsEnabled { + m.increaseUnreadCounter(user: user) + } + } + if let file = cItem.autoReceiveFile() { + Task { + await receiveFile(user: user, fileId: file.fileId, auto: true) + } + } + if cItem.showNotification { + NtfManager.shared.notifyMessageReceived(user, cInfo, cItem) } } - if let file = cItem.autoReceiveFile() { - Task { - await receiveFile(user: user, fileId: file.fileId, auto: true) + case let .chatItemsStatusesUpdated(user, chatItems): + for chatItem in chatItems { + let cInfo = chatItem.chatInfo + let cItem = chatItem.chatItem + if !cItem.isDeletedContent && active(user) { + await MainActor.run { m.updateChatItem(cInfo, cItem, status: cItem.meta.itemStatus) } } - } - if cItem.showNotification { - NtfManager.shared.notifyMessageReceived(user, cInfo, cItem) - } - case let .chatItemStatusUpdated(user, aChatItem): - let cInfo = aChatItem.chatInfo - let cItem = aChatItem.chatItem - if !cItem.isDeletedContent && active(user) { - await MainActor.run { m.updateChatItem(cInfo, cItem, status: cItem.meta.itemStatus) } - } - if let endTask = m.messageDelivery[cItem.id] { - switch cItem.meta.itemStatus { - case .sndSent: endTask() - case .sndErrorAuth: endTask() - case .sndError: endTask() - default: () + if let endTask = m.messageDelivery[cItem.id] { + switch cItem.meta.itemStatus { + case .sndNew: () + case .sndSent: endTask() + case .sndRcvd: endTask() + case .sndErrorAuth: endTask() + case .sndError: endTask() + case .sndWarning: endTask() + case .rcvNew: () + case .rcvRead: () + case .invalid: () + } } } case let .chatItemUpdated(user, aChatItem): @@ -1858,6 +2021,18 @@ func processReceivedMsg(_ res: ChatResponse) async { m.removeChat(hostConn.id) } } + case let .businessLinkConnecting(user, groupInfo, _, fromContact): + if !active(user) { return } + + await MainActor.run { + m.updateGroup(groupInfo) + } + if m.chatId == fromContact.id { + ItemsModel.shared.loadOpenChat(groupInfo.id) + } + await MainActor.run { + m.removeChat(fromContact.id) + } case let .joinedGroupMemberConnecting(user, groupInfo, _, member): if active(user) { await MainActor.run { @@ -1993,7 +2168,6 @@ func processReceivedMsg(_ res: ChatResponse) async { await withCall(contact) { call in await MainActor.run { call.callState = .offerReceived - call.peerMedia = callType.media call.sharedKey = sharedKey } let useRelay = UserDefaults.standard.bool(forKey: DEFAULT_WEBRTC_POLICY_RELAY) @@ -2162,32 +2336,42 @@ func chatItemSimpleUpdate(_ user: any UserLike, _ aChatItem: AChatItem) async { } } -func refreshCallInvitations() throws { +func refreshCallInvitations() async throws { let m = ChatModel.shared - let callInvitations = try justRefreshCallInvitations() - if let (chatId, ntfAction) = m.ntfCallInvitationAction, - let invitation = m.callInvitations.removeValue(forKey: chatId) { - m.ntfCallInvitationAction = nil - CallController.shared.callAction(invitation: invitation, action: ntfAction) - } else if let invitation = callInvitations.last(where: { $0.user.showNotifications }) { - activateCall(invitation) + let callInvitations = try await apiGetCallInvitations() + await MainActor.run { + m.callInvitations = callsByChat(callInvitations) + if let (chatId, ntfAction) = m.ntfCallInvitationAction, + let invitation = m.callInvitations.removeValue(forKey: chatId) { + m.ntfCallInvitationAction = nil + CallController.shared.callAction(invitation: invitation, action: ntfAction) + } else if let invitation = callInvitations.last(where: { $0.user.showNotifications }) { + activateCall(invitation) + } } } -func justRefreshCallInvitations() throws -> [RcvCallInvitation] { - let m = ChatModel.shared - let callInvitations = try apiGetCallInvitations() - m.callInvitations = callInvitations.reduce(into: [ChatId: RcvCallInvitation]()) { result, inv in result[inv.contact.id] = inv } - return callInvitations +func justRefreshCallInvitations() async throws { + let callInvitations = try apiGetCallInvitationsSync() + await MainActor.run { + ChatModel.shared.callInvitations = callsByChat(callInvitations) + } +} + +private func callsByChat(_ callInvitations: [RcvCallInvitation]) -> [ChatId: RcvCallInvitation] { + callInvitations.reduce(into: [ChatId: RcvCallInvitation]()) { + result, inv in result[inv.contact.id] = inv + } } func activateCall(_ callInvitation: RcvCallInvitation) { - if !callInvitation.user.showNotifications { return } let m = ChatModel.shared + logger.debug("reportNewIncomingCall activeCallUUID \(String(describing: m.activeCall?.callUUID)) invitationUUID \(String(describing: callInvitation.callUUID))") + if !callInvitation.user.showNotifications || m.activeCall?.callUUID == callInvitation.callUUID { return } CallController.shared.reportNewIncomingCall(invitation: callInvitation) { error in if let error = error { DispatchQueue.main.async { - m.callInvitations[callInvitation.contact.id]?.callkitUUID = nil + m.callInvitations[callInvitation.contact.id]?.callUUID = nil } logger.error("reportNewIncomingCall error: \(error.localizedDescription)") } else { diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index fe306b944f..10120db185 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -82,10 +82,18 @@ struct SimpleXApp: App { if appState != .stopped { startChatAndActivate { - if appState.inactive && chatModel.chatRunning == true { - updateChats() - if !chatModel.showCallView && !CallController.shared.hasActiveCalls() { - updateCallInvitations() + if chatModel.chatRunning == true { + if let ntfResponse = chatModel.notificationResponse { + chatModel.notificationResponse = nil + NtfManager.shared.processNotificationResponse(ntfResponse) + } + if appState.inactive { + Task { + await updateChats() + if !chatModel.showCallView && !CallController.shared.hasActiveCalls() { + await updateCallInvitations() + } + } } } } @@ -130,16 +138,17 @@ struct SimpleXApp: App { } } - private func updateChats() { + private func updateChats() async { do { - let chats = try apiGetChats() - chatModel.updateChats(with: chats) + let chats = try await apiGetChatsAsync() + await MainActor.run { chatModel.updateChats(chats) } if let id = chatModel.chatId, - let chat = chatModel.getChat(id) { - Task { await loadChat(chat: chat) } + let chat = chatModel.getChat(id), + !NtfManager.shared.navigatingToChat { + Task { await loadChat(chat: chat, clearItems: false) } } if let ncr = chatModel.ntfContactRequest { - chatModel.ntfContactRequest = nil + await MainActor.run { chatModel.ntfContactRequest = nil } if case let .contactRequest(contactRequest) = chatModel.getChat(ncr.chatId)?.chatInfo { Task { await acceptContactRequest(incognito: ncr.incognito, contactRequest: contactRequest) } } @@ -149,9 +158,9 @@ struct SimpleXApp: App { } } - private func updateCallInvitations() { + private func updateCallInvitations() async { do { - try refreshCallInvitations() + try await refreshCallInvitations() } catch let error { logger.error("apiGetCallInvitations: cannot update call invitations \(responseError(error))") } diff --git a/apps/ios/Shared/Theme/Theme.swift b/apps/ios/Shared/Theme/Theme.swift index d4dcc8097f..de67390026 100644 --- a/apps/ios/Shared/Theme/Theme.swift +++ b/apps/ios/Shared/Theme/Theme.swift @@ -91,8 +91,8 @@ var systemInDarkThemeCurrently: Bool { return UITraitCollection.current.userInterfaceStyle == .dark } -func reactOnDarkThemeChanges() { - if currentThemeDefault.get() == DefaultTheme.SYSTEM_THEME_NAME && CurrentColors.colors.isLight == systemInDarkThemeCurrently { +func reactOnDarkThemeChanges(_ inDarkNow: Bool) { + if currentThemeDefault.get() == DefaultTheme.SYSTEM_THEME_NAME && CurrentColors.colors.isLight == inDarkNow { // Change active colors from light to dark and back based on system theme ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME) } @@ -102,7 +102,7 @@ extension ThemeWallpaper { public func importFromString() -> ThemeWallpaper { if preset == nil, let image { // Need to save image from string and to save its path - if let parsed = UIImage(base64Encoded: image), + if let parsed = imageFromBase64(image), let filename = saveWallpaperFile(image: parsed) { var copy = self copy.image = nil @@ -122,7 +122,7 @@ extension ThemeWallpaper { let preset: String? = if case let WallpaperType.preset(filename, _) = type { filename } else { nil } let scale: Float? = if case let WallpaperType.preset(_, scale) = type { scale } else { if case let WallpaperType.image(_, scale, _) = type { scale } else { 1.0 } } let scaleType: WallpaperScaleType? = if case let WallpaperType.image(_, _, scaleType) = type { scaleType } else { nil } - let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSize(image, maxDataSize: 5_000_000) } else { nil } + let image: String? = if case WallpaperType.image = type, let image = type.uiImage { resizeImageToStrSizeSync(image, maxDataSize: 5_000_000) } else { nil } return ThemeWallpaper ( preset: preset, scale: scale, diff --git a/apps/ios/Shared/Theme/ThemeManager.swift b/apps/ios/Shared/Theme/ThemeManager.swift index 55f9a08878..4166619d04 100644 --- a/apps/ios/Shared/Theme/ThemeManager.swift +++ b/apps/ios/Shared/Theme/ThemeManager.swift @@ -53,7 +53,7 @@ class ThemeManager { return perUserTheme } let defaultTheme = defaultActiveTheme(appSettingsTheme) - return ThemeModeOverride(mode: CurrentColors.base.mode, colors: defaultTheme?.colors ?? ThemeColors(), wallpaper: defaultTheme?.wallpaper) + return ThemeModeOverride(mode: CurrentColors.base.mode, colors: defaultTheme?.colors ?? ThemeColors(), wallpaper: defaultTheme?.wallpaper ?? ThemeWallpaper.from(PresetWallpaper.school.toType(CurrentColors.base), nil, nil)) } static func currentColors(_ themeOverridesForType: WallpaperType?, _ perChatTheme: ThemeModeOverride?, _ perUserTheme: ThemeModeOverrides?, _ appSettingsTheme: [ThemeOverrides]) -> ActiveTheme { @@ -197,7 +197,7 @@ class ThemeManager { var themeIds = currentThemeIdsDefault.get() themeIds[nonSystemThemeName] = prevValue.themeId currentThemeIdsDefault.set(themeIds) - applyTheme(nonSystemThemeName) + applyTheme(currentThemeDefault.get()) } static func copyFromSameThemeOverrides(_ type: WallpaperType?, _ lowerLevelOverride: ThemeModeOverride?, _ pref: Binding) -> Bool { diff --git a/apps/ios/Shared/Views/Call/ActiveCallView.swift b/apps/ios/Shared/Views/Call/ActiveCallView.swift index 97415018bf..2f76f1f046 100644 --- a/apps/ios/Shared/Views/Call/ActiveCallView.swift +++ b/apps/ios/Shared/Views/Call/ActiveCallView.swift @@ -17,8 +17,8 @@ struct ActiveCallView: View { @ObservedObject var call: Call @Environment(\.scenePhase) var scenePhase @State private var client: WebRTCClient? = nil - @State private var activeCall: WebRTCClient.Call? = nil @State private var localRendererAspectRatio: CGFloat? = nil + @State var remoteContentMode: UIView.ContentMode = .scaleAspectFill @Binding var canConnectCall: Bool @State var prevColorScheme: ColorScheme = .dark @State var pipShown = false @@ -27,24 +27,39 @@ struct ActiveCallView: View { var body: some View { ZStack(alignment: .topLeading) { ZStack(alignment: .bottom) { - if let client = client, [call.peerMedia, call.localMedia].contains(.video), activeCall != nil { + if let client = client, call.hasVideo { GeometryReader { g in let width = g.size.width * 0.3 ZStack(alignment: .topTrailing) { - CallViewRemote(client: client, activeCall: $activeCall, activeCallViewIsCollapsed: $m.activeCallViewIsCollapsed, pipShown: $pipShown) - CallViewLocal(client: client, activeCall: $activeCall, localRendererAspectRatio: $localRendererAspectRatio, pipShown: $pipShown) - .cornerRadius(10) - .frame(width: width, height: width / (localRendererAspectRatio ?? 1)) - .padding([.top, .trailing], 17) ZStack(alignment: .center) { // For some reason, when the view in GeometryReader and ZStack is visible, it steals clicks on a back button, so showing something on top like this with background color helps (.clear color doesn't work) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.primary.opacity(0.000001)) + + CallViewRemote(client: client, call: call, activeCallViewIsCollapsed: $m.activeCallViewIsCollapsed, contentMode: $remoteContentMode, pipShown: $pipShown) + .onTapGesture { + remoteContentMode = remoteContentMode == .scaleAspectFill ? .scaleAspectFit : .scaleAspectFill + } + + Group { + let localVideoTrack = client.activeCall?.localVideoTrack ?? client.notConnectedCall?.localCameraAndTrack?.1 + if localVideoTrack != nil { + CallViewLocal(client: client, localRendererAspectRatio: $localRendererAspectRatio, pipShown: $pipShown) + .onDisappear { + localRendererAspectRatio = nil + } + } else { + Rectangle().fill(.black) + } + } + .cornerRadius(10) + .frame(width: width, height: localRendererAspectRatio == nil ? (g.size.width < g.size.height ? width * 1.33 : width / 1.33) : width / (localRendererAspectRatio ?? 1)) + .padding([.top, .trailing], 17) } } } - if let call = m.activeCall, let client = client, (!pipShown || !call.supportsVideo) { + if let call = m.activeCall, let client = client, (!pipShown || !call.hasVideo) { ActiveCallOverlay(call: call, client: client) } } @@ -54,6 +69,9 @@ struct ActiveCallView: View { .onAppear { logger.debug("ActiveCallView: appear client is nil \(client == nil), scenePhase \(String(describing: scenePhase)), canConnectCall \(canConnectCall)") AppDelegate.keepScreenOn(true) + Task { + await askRequiredPermissions() + } createWebRTCClient() dismissAllSheets() hideKeyboard() @@ -84,7 +102,7 @@ struct ActiveCallView: View { private func createWebRTCClient() { if client == nil && canConnectCall { - client = WebRTCClient($activeCall, { msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio) + client = WebRTCClient({ msg in await MainActor.run { processRtcMessage(msg: msg) } }, $localRendererAspectRatio) Task { await m.callCommand.setClient(client) } @@ -99,7 +117,7 @@ struct ActiveCallView: View { logger.debug("ActiveCallView: response \(msg.resp.respType)") switch msg.resp { case let .capabilities(capabilities): - let callType = CallType(media: call.localMedia, capabilities: capabilities) + let callType = CallType(media: call.initialCallType, capabilities: capabilities) Task { do { try await apiSendCallInvitation(call.contact, callType) @@ -110,7 +128,7 @@ struct ActiveCallView: View { call.callState = .invitationSent call.localCapabilities = capabilities } - if call.supportsVideo && !AVAudioSession.sharedInstance().hasExternalAudioDevice() { + if call.hasVideo && !AVAudioSession.sharedInstance().hasExternalAudioDevice() { try? AVAudioSession.sharedInstance().setCategory(.playback, options: [.allowBluetooth, .allowAirPlay, .allowBluetoothA2DP]) } CallSoundsPlayer.shared.startConnectingCallSound() @@ -120,7 +138,7 @@ struct ActiveCallView: View { Task { do { try await apiSendCallOffer(call.contact, offer, iceCandidates, - media: call.localMedia, capabilities: capabilities) + media: call.initialCallType, capabilities: capabilities) } catch { logger.error("apiSendCallOffer \(responseError(error))") } @@ -164,6 +182,9 @@ struct ActiveCallView: View { } if state.connectionState == "closed" { closeCallView(client) + if let callUUID = m.activeCall?.callUUID { + CallController.shared.endCall(callUUID: callUUID) + } m.activeCall = nil m.activeCallViewIsCollapsed = false } @@ -182,10 +203,18 @@ struct ActiveCallView: View { CallSoundsPlayer.shared.vibrate(long: false) wasConnected = true } + case let .peerMedia(source, enabled): + switch source { + case .mic: call.peerMediaSources.mic = enabled + case .camera: call.peerMediaSources.camera = enabled + case .screenAudio: call.peerMediaSources.screenAudio = enabled + case .screenVideo: call.peerMediaSources.screenVideo = enabled + case .unknown: () + } case .ended: closeCallView(client) call.callState = .ended - if let uuid = call.callkitUUID { + if let uuid = call.callUUID { CallController.shared.endCall(callUUID: uuid) } case .ok: @@ -214,16 +243,38 @@ struct ActiveCallView: View { ChatReceiver.shared.messagesChannel = nil return } - if case let .chatItemStatusUpdated(_, msg) = msg, - msg.chatInfo.id == call.contact.id, - case .sndCall = msg.chatItem.content, - case .sndRcvd = msg.chatItem.meta.itemStatus { + if case let .chatItemsStatusesUpdated(_, chatItems) = msg, + chatItems.contains(where: { ci in + ci.chatInfo.id == call.contact.id && + ci.chatItem.content.isSndCall && + ci.chatItem.meta.itemStatus.isSndRcvd + }) { CallSoundsPlayer.shared.startInCallSound() ChatReceiver.shared.messagesChannel = nil } } } + private func askRequiredPermissions() async { + let mic = await WebRTCClient.isAuthorized(for: .audio) + await MainActor.run { + call.localMediaSources.mic = mic + } + let cameraAuthorized = AVCaptureDevice.authorizationStatus(for: .video) == .authorized + var camera = call.initialCallType == .audio || cameraAuthorized + if call.initialCallType == .video && !cameraAuthorized { + camera = await WebRTCClient.isAuthorized(for: .video) + await MainActor.run { + if camera, let client { + client.setCameraEnabled(true) + } + } + } + if !mic || !camera { + WebRTCClient.showUnauthorizedAlert(for: !mic ? .audio : .video) + } + } + private func closeCallView(_ client: WebRTCClient) { if m.activeCall != nil { m.showCallView = false @@ -239,44 +290,16 @@ struct ActiveCallOverlay: View { var body: some View { VStack { - switch call.localMedia { - case .video: + switch call.hasVideo { + case true: videoCallInfoView(call) .foregroundColor(.white) .opacity(0.8) - .padding() - - Spacer() - - HStack { - toggleAudioButton() - Spacer() - if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) { - toggleSpeakerButton() - .frame(width: 40, height: 40) - } else if call.hasMedia { - AudioDevicePicker() - .scaleEffect(2) - .frame(maxWidth: 40, maxHeight: 40) - } else { - Color.clear.frame(width: 40, height: 40) - } - Spacer() - endCallButton() - Spacer() - if call.videoEnabled { - flipCameraButton() - } else { - Color.clear.frame(width: 40, height: 40) - } - Spacer() - toggleVideoButton() - } - .padding(.horizontal, 20) - .padding(.bottom, 16) - .frame(maxWidth: .infinity, alignment: .center) - - case .audio: + .padding(.horizontal) + // Fixed vertical padding required for preserving position of buttons row when changing audio-to-video and back in landscape orientation. + // Otherwise, bigger padding is added by SwiftUI when switching call types + .padding(.vertical, 10) + case false: ZStack(alignment: .topLeading) { Button { chatModel.activeCallViewIsCollapsed = true @@ -291,35 +314,32 @@ struct ActiveCallOverlay: View { } .foregroundColor(.white) .opacity(0.8) - .padding() + .padding(.horizontal) + .padding(.vertical, 10) .frame(maxHeight: .infinity) } - - Spacer() - - ZStack(alignment: .bottom) { - toggleAudioButton() - .frame(maxWidth: .infinity, alignment: .leading) - endCallButton() - // Check if the only input is microphone. And in this case show toggle button, - // If there are more inputs, it probably means something like bluetooth headphones are available - // and in this case show iOS button for choosing different output. - // There is no way to get available outputs, only inputs - if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) { - toggleSpeakerButton() - .frame(maxWidth: .infinity, alignment: .trailing) - } else if call.hasMedia { - AudioDevicePicker() - .scaleEffect(2) - .frame(maxWidth: 50, maxHeight: 40) - .frame(maxWidth: .infinity, alignment: .trailing) - } else { - Color.clear.frame(width: 50, height: 40) - } - } - .padding(.bottom, 60) - .padding(.horizontal, 48) } + + Spacer() + + HStack { + toggleMicButton() + Spacer() + audioDeviceButton() + Spacer() + endCallButton() + Spacer() + if call.localMediaSources.camera { + flipCameraButton() + } else { + Color.clear.frame(width: 60, height: 60) + } + Spacer() + toggleCameraButton() + } + .padding(.horizontal, 20) + .padding(.bottom, 16) + .frame(maxWidth: 440, alignment: .center) } .frame(maxWidth: .infinity) .onAppear { @@ -381,36 +401,54 @@ struct ActiveCallOverlay: View { private func endCallButton() -> some View { let cc = CallController.shared - return callButton("phone.down.fill", width: 60, height: 60) { - if let uuid = call.callkitUUID { + return callButton("phone.down.fill", .red, padding: 10) { + if let uuid = call.callUUID { cc.endCall(callUUID: uuid) } else { cc.endCall(call: call) {} } } - .foregroundColor(.red) } - private func toggleAudioButton() -> some View { - controlButton(call, call.audioEnabled ? "mic.fill" : "mic.slash") { + private func toggleMicButton() -> some View { + controlButton(call, call.localMediaSources.mic ? "mic.fill" : "mic.slash", padding: 14) { Task { - client.setAudioEnabled(!call.audioEnabled) - DispatchQueue.main.async { - call.audioEnabled = !call.audioEnabled - } + if await WebRTCClient.isAuthorized(for: .audio) { + client.setAudioEnabled(!call.localMediaSources.mic) + } else { WebRTCClient.showUnauthorizedAlert(for: .audio) } + } + } + } + + func audioDeviceButton() -> some View { + // Check if the only input is microphone. And in this case show toggle button, + // If there are more inputs, it probably means something like bluetooth headphones are available + // and in this case show iOS button for choosing different output. + // There is no way to get available outputs, only inputs + Group { + if deviceManager.availableInputs.allSatisfy({ $0.portType == .builtInMic }) { + toggleSpeakerButton() + } else { + audioDevicePickerButton() + } + } + .onChange(of: call.localMediaSources.hasVideo) { hasVideo in + let current = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType + let speakerEnabled = current == .builtInSpeaker + let receiverEnabled = current == .builtInReceiver + // react automatically only when receiver were selected, otherwise keep an external device selected + if !speakerEnabled && hasVideo && receiverEnabled { + client.setSpeakerEnabledAndConfigureSession(!speakerEnabled, skipExternalDevice: true) + call.speakerEnabled = !speakerEnabled } } } private func toggleSpeakerButton() -> some View { - controlButton(call, call.speakerEnabled ? "speaker.wave.2.fill" : "speaker.wave.1.fill") { - Task { - let speakerEnabled = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType == .builtInSpeaker - client.setSpeakerEnabledAndConfigureSession(!speakerEnabled) - DispatchQueue.main.async { - call.speakerEnabled = !speakerEnabled - } - } + controlButton(call, !call.peerMediaSources.mic ? "speaker.slash" : call.speakerEnabled ? "speaker.wave.2.fill" : "speaker.wave.1.fill", padding: !call.peerMediaSources.mic ? 16 : call.speakerEnabled ? 15 : 17) { + let speakerEnabled = AVAudioSession.sharedInstance().currentRoute.outputs.first?.portType == .builtInSpeaker + client.setSpeakerEnabledAndConfigureSession(!speakerEnabled) + call.speakerEnabled = !speakerEnabled } .onAppear { deviceManager.call = call @@ -418,53 +456,67 @@ struct ActiveCallOverlay: View { } } - private func toggleVideoButton() -> some View { - controlButton(call, call.videoEnabled ? "video.fill" : "video.slash") { + private func toggleCameraButton() -> some View { + controlButton(call, call.localMediaSources.camera ? "video.fill" : "video.slash", padding: call.localMediaSources.camera ? 16 : 14) { Task { - client.setVideoEnabled(!call.videoEnabled) - DispatchQueue.main.async { - call.videoEnabled = !call.videoEnabled - } + if await WebRTCClient.isAuthorized(for: .video) { + client.setCameraEnabled(!call.localMediaSources.camera) + } else { WebRTCClient.showUnauthorizedAlert(for: .video) } } } + .disabled(call.initialCallType == .audio && client.activeCall?.peerHasOldVersion == true) } @ViewBuilder private func flipCameraButton() -> some View { - controlButton(call, "arrow.triangle.2.circlepath") { + controlButton(call, "arrow.triangle.2.circlepath", padding: 12) { Task { - client.flipCamera() + if await WebRTCClient.isAuthorized(for: .video) { + client.flipCamera() + } } } } - @ViewBuilder private func controlButton(_ call: Call, _ imageName: String, _ perform: @escaping () -> Void) -> some View { - if call.hasMedia { - callButton(imageName, width: 50, height: 38, perform) - .foregroundColor(.white) - .opacity(0.85) - } else { - Color.clear.frame(width: 50, height: 38) - } + @ViewBuilder private func controlButton(_ call: Call, _ imageName: String, padding: CGFloat, _ perform: @escaping () -> Void) -> some View { + callButton(imageName, call.peerMediaSources.hasVideo ? Color.black.opacity(0.2) : Color.white.opacity(0.2), padding: padding, perform) } - private func callButton(_ imageName: String, width: CGFloat, height: CGFloat, _ perform: @escaping () -> Void) -> some View { + @ViewBuilder private func audioDevicePickerButton() -> some View { + AudioDevicePicker() + .opacity(0.8) + .scaleEffect(2) + .padding(10) + .frame(width: 60, height: 60) + .background(call.peerMediaSources.hasVideo ? Color.black.opacity(0.2) : Color.white.opacity(0.2)) + .clipShape(.circle) + } + + private func callButton(_ imageName: String, _ background: Color, padding: CGFloat, _ perform: @escaping () -> Void) -> some View { Button { perform() } label: { Image(systemName: imageName) .resizable() .scaledToFit() - .frame(maxWidth: width, maxHeight: height) + .padding(padding) + .frame(width: 60, height: 60) + .background(background) } + .foregroundColor(whiteColorWithAlpha) + .clipShape(.circle) + } + + private var whiteColorWithAlpha: Color { + get { Color(red: 204 / 255, green: 204 / 255, blue: 204 / 255) } } } struct ActiveCallOverlay_Previews: PreviewProvider { static var previews: some View { Group{ - ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callkitUUID: UUID(), callState: .offerSent, localMedia: .video), client: WebRTCClient(Binding.constant(nil), { _ in }, Binding.constant(nil))) + ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, initialCallType: .video), client: WebRTCClient({ _ in }, Binding.constant(nil))) .background(.black) - ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callkitUUID: UUID(), callState: .offerSent, localMedia: .audio), client: WebRTCClient(Binding.constant(nil), { _ in }, Binding.constant(nil))) + ActiveCallOverlay(call: Call(direction: .incoming, contact: Contact.sampleData, callUUID: UUID().uuidString.lowercased(), callState: .offerSent, initialCallType: .audio), client: WebRTCClient({ _ in }, Binding.constant(nil))) .background(.black) } } diff --git a/apps/ios/Shared/Views/Call/CallController.swift b/apps/ios/Shared/Views/Call/CallController.swift index 64b565e8e6..1f28180e87 100644 --- a/apps/ios/Shared/Views/Call/CallController.swift +++ b/apps/ios/Shared/Views/Call/CallController.swift @@ -51,7 +51,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse func provider(_ provider: CXProvider, perform action: CXStartCallAction) { logger.debug("CallController.provider CXStartCallAction") - if callManager.startOutgoingCall(callUUID: action.callUUID) { + if callManager.startOutgoingCall(callUUID: action.callUUID.uuidString.lowercased()) { action.fulfill() provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: nil) } else { @@ -61,12 +61,30 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { logger.debug("CallController.provider CXAnswerCallAction") - if callManager.answerIncomingCall(callUUID: action.callUUID) { - // WebRTC call should be in connected state to fulfill. - // Otherwise no audio and mic working on lockscreen - fulfillOnConnect = action - } else { - action.fail() + Task { + let chatIsReady = await waitUntilChatStarted(timeoutMs: 30_000, stepMs: 500) + logger.debug("CallController chat started \(chatIsReady) \(ChatModel.shared.chatInitialized) \(ChatModel.shared.chatRunning == true) \(String(describing: AppChatState.shared.value))") + if !chatIsReady { + action.fail() + return + } + if !ChatModel.shared.callInvitations.values.contains(where: { inv in inv.callUUID == action.callUUID.uuidString.lowercased() }) { + try? await justRefreshCallInvitations() + logger.debug("CallController: updated call invitations chat") + } + await MainActor.run { + logger.debug("CallController.provider will answer on call") + + if callManager.answerIncomingCall(callUUID: action.callUUID.uuidString.lowercased()) { + logger.debug("CallController.provider answered on call") + // WebRTC call should be in connected state to fulfill. + // Otherwise no audio and mic working on lockscreen + fulfillOnConnect = action + } else { + logger.debug("CallController.provider will fail the call") + action.fail() + } + } } } @@ -75,7 +93,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse // Should be nil here if connection was in connected state fulfillOnConnect?.fail() fulfillOnConnect = nil - callManager.endCall(callUUID: action.callUUID) { ok in + callManager.endCall(callUUID: action.callUUID.uuidString.lowercased()) { ok in if ok { action.fulfill() } else { @@ -86,7 +104,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse } func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) { - if callManager.enableMedia(media: .audio, enable: !action.isMuted, callUUID: action.callUUID) { + if callManager.enableMedia(source: .mic, enable: !action.isMuted, callUUID: action.callUUID.uuidString.lowercased()) { action.fulfill() } else { action.fail() @@ -103,8 +121,8 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession) RTCAudioSession.sharedInstance().isAudioEnabled = true do { - let supportsVideo = ChatModel.shared.activeCall?.supportsVideo == true - if supportsVideo { + let hasVideo = ChatModel.shared.activeCall?.hasVideo == true + if hasVideo { try audioSession.setCategory(.playAndRecord, mode: .videoChat, options: [.defaultToSpeaker, .mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP]) } else { try audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.mixWithOthers, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP]) @@ -115,7 +133,7 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse try? await Task.sleep(nanoseconds: UInt64(i) * 300_000000) if let preferred = audioSession.preferredInputDevice() { await MainActor.run { try? audioSession.setPreferredInput(preferred) } - } else if supportsVideo { + } else if hasVideo { await MainActor.run { try? audioSession.overrideOutputAudioPort(.speaker) } } } @@ -156,6 +174,19 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse } } + private func waitUntilChatStarted(timeoutMs: UInt64, stepMs: UInt64) async -> Bool { + logger.debug("CallController waiting until chat started") + var t: UInt64 = 0 + repeat { + if ChatModel.shared.chatInitialized, ChatModel.shared.chatRunning == true, case .active = AppChatState.shared.value { + return true + } + _ = try? await Task.sleep(nanoseconds: stepMs * 1000000) + t += stepMs + } while t < timeoutMs + return false + } + @objc(pushRegistry:didUpdatePushCredentials:forType:) func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { logger.debug("CallController: didUpdate push credentials for type \(type.rawValue)") @@ -171,32 +202,19 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse self.reportExpiredCall(payload: payload, completion) return } - if (!ChatModel.shared.chatInitialized) { - logger.debug("CallController: initializing chat") - do { - try initializeChat(start: true, refreshInvitations: false) - } catch let error { - logger.error("CallController: initializing chat error: \(error)") - self.reportExpiredCall(payload: payload, completion) - return - } - } - logger.debug("CallController: initialized chat") - startChatForCall() - logger.debug("CallController: started chat") - self.shouldSuspendChat = true - // There are no invitations in the model, as it was processed by NSE - _ = try? justRefreshCallInvitations() - logger.debug("CallController: updated call invitations chat") - // logger.debug("CallController justRefreshCallInvitations: \(String(describing: m.callInvitations))") // Extract the call information from the push notification payload let m = ChatModel.shared if let contactId = payload.dictionaryPayload["contactId"] as? String, - let invitation = m.callInvitations[contactId] { - let update = self.cxCallUpdate(invitation: invitation) - if let uuid = invitation.callkitUUID { + let displayName = payload.dictionaryPayload["displayName"] as? String, + let callUUID = payload.dictionaryPayload["callUUID"] as? String, + let uuid = UUID(uuidString: callUUID), + let callTsInterval = payload.dictionaryPayload["callTs"] as? TimeInterval, + let mediaStr = payload.dictionaryPayload["media"] as? String, + let media = CallMediaType(rawValue: mediaStr) { + let update = self.cxCallUpdate(contactId, displayName, media) + let callTs = Date(timeIntervalSince1970: callTsInterval) + if callTs.timeIntervalSinceNow >= -180 { logger.debug("CallController: report pushkit call via CallKit") - let update = self.cxCallUpdate(invitation: invitation) self.provider.reportNewIncomingCall(with: uuid, update: update) { error in if error != nil { m.callInvitations.removeValue(forKey: contactId) @@ -205,11 +223,31 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse completion() } } else { + logger.debug("CallController will expire call 1") self.reportExpiredCall(update: update, completion) } } else { + logger.debug("CallController will expire call 2") self.reportExpiredCall(payload: payload, completion) } + + //DispatchQueue.main.asyncAfter(deadline: .now() + 10) { + if (!ChatModel.shared.chatInitialized) { + logger.debug("CallController: initializing chat") + do { + try initializeChat(start: true, refreshInvitations: false) + } catch let error { + logger.error("CallController: initializing chat error: \(error)") + if let call = ChatModel.shared.activeCall { + self.endCall(call: call, completed: completion) + } + return + } + } + logger.debug("CallController: initialized chat") + startChatForCall() + logger.debug("CallController: started chat") + self.shouldSuspendChat = true } // This function fulfils the requirement to always report a call when PushKit notification is received, @@ -239,8 +277,8 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse } func reportNewIncomingCall(invitation: RcvCallInvitation, completion: @escaping (Error?) -> Void) { - logger.debug("CallController.reportNewIncomingCall, UUID=\(String(describing: invitation.callkitUUID))") - if CallController.useCallKit(), let uuid = invitation.callkitUUID { + logger.debug("CallController.reportNewIncomingCall, UUID=\(String(describing: invitation.callUUID))") + if CallController.useCallKit(), let callUUID = invitation.callUUID, let uuid = UUID(uuidString: callUUID) { if invitation.callTs.timeIntervalSinceNow >= -180 { let update = cxCallUpdate(invitation: invitation) provider.reportNewIncomingCall(with: uuid, update: update, completion: completion) @@ -261,6 +299,14 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse return update } + private func cxCallUpdate(_ contactId: String, _ displayName: String, _ media: CallMediaType) -> CXCallUpdate { + let update = CXCallUpdate() + update.remoteHandle = CXHandle(type: .generic, value: contactId) + update.hasVideo = media == .video + update.localizedCallerName = displayName + return update + } + func reportIncomingCall(call: Call, connectedAt dateConnected: Date?) { logger.debug("CallController: reporting incoming call connected") if CallController.useCallKit() { @@ -272,14 +318,14 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse func reportOutgoingCall(call: Call, connectedAt dateConnected: Date?) { logger.debug("CallController: reporting outgoing call connected") - if CallController.useCallKit(), let uuid = call.callkitUUID { + if CallController.useCallKit(), let callUUID = call.callUUID, let uuid = UUID(uuidString: callUUID) { provider.reportOutgoingCall(with: uuid, connectedAt: dateConnected) } } func reportCallRemoteEnded(invitation: RcvCallInvitation) { logger.debug("CallController: reporting remote ended") - if CallController.useCallKit(), let uuid = invitation.callkitUUID { + if CallController.useCallKit(), let callUUID = invitation.callUUID, let uuid = UUID(uuidString: callUUID) { provider.reportCall(with: uuid, endedAt: nil, reason: .remoteEnded) } else if invitation.contact.id == activeCallInvitation?.contact.id { activeCallInvitation = nil @@ -288,14 +334,17 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse func reportCallRemoteEnded(call: Call) { logger.debug("CallController: reporting remote ended") - if CallController.useCallKit(), let uuid = call.callkitUUID { + if CallController.useCallKit(), let callUUID = call.callUUID, let uuid = UUID(uuidString: callUUID) { provider.reportCall(with: uuid, endedAt: nil, reason: .remoteEnded) } } func startCall(_ contact: Contact, _ media: CallMediaType) { logger.debug("CallController.startCall") - let uuid = callManager.newOutgoingCall(contact, media) + let callUUID = callManager.newOutgoingCall(contact, media) + guard let uuid = UUID(uuidString: callUUID) else { + return + } if CallController.useCallKit() { let handle = CXHandle(type: .generic, value: contact.id) let action = CXStartCallAction(call: uuid, handle: handle) @@ -307,19 +356,17 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse update.localizedCallerName = contact.displayName self.provider.reportCall(with: uuid, updated: update) } - } else if callManager.startOutgoingCall(callUUID: uuid) { - if callManager.startOutgoingCall(callUUID: uuid) { - logger.debug("CallController.startCall: call started") - } else { - logger.error("CallController.startCall: no active call") - } + } else if callManager.startOutgoingCall(callUUID: callUUID) { + logger.debug("CallController.startCall: call started") + } else { + logger.error("CallController.startCall: no active call") } } func answerCall(invitation: RcvCallInvitation) { logger.debug("CallController: answering a call") - if CallController.useCallKit(), let callUUID = invitation.callkitUUID { - requestTransaction(with: CXAnswerCallAction(call: callUUID)) + if CallController.useCallKit(), let callUUID = invitation.callUUID, let uuid = UUID(uuidString: callUUID) { + requestTransaction(with: CXAnswerCallAction(call: uuid)) } else { callManager.answerIncomingCall(invitation: invitation) } @@ -328,10 +375,13 @@ class CallController: NSObject, CXProviderDelegate, PKPushRegistryDelegate, Obse } } - func endCall(callUUID: UUID) { - logger.debug("CallController: ending the call with UUID \(callUUID.uuidString)") + func endCall(callUUID: String) { + let uuid = UUID(uuidString: callUUID) + logger.debug("CallController: ending the call with UUID \(callUUID)") if CallController.useCallKit() { - requestTransaction(with: CXEndCallAction(call: callUUID)) + if let uuid { + requestTransaction(with: CXEndCallAction(call: uuid)) + } } else { callManager.endCall(callUUID: callUUID) { ok in if ok { diff --git a/apps/ios/Shared/Views/Call/CallManager.swift b/apps/ios/Shared/Views/Call/CallManager.swift index a6d5ea17c4..a3e1df2301 100644 --- a/apps/ios/Shared/Views/Call/CallManager.swift +++ b/apps/ios/Shared/Views/Call/CallManager.swift @@ -10,25 +10,25 @@ import Foundation import SimpleXChat class CallManager { - func newOutgoingCall(_ contact: Contact, _ media: CallMediaType) -> UUID { - let uuid = UUID() - let call = Call(direction: .outgoing, contact: contact, callkitUUID: uuid, callState: .waitCapabilities, localMedia: media) + func newOutgoingCall(_ contact: Contact, _ media: CallMediaType) -> String { + let uuid = UUID().uuidString.lowercased() + let call = Call(direction: .outgoing, contact: contact, callUUID: uuid, callState: .waitCapabilities, initialCallType: media) call.speakerEnabled = media == .video ChatModel.shared.activeCall = call return uuid } - func startOutgoingCall(callUUID: UUID) -> Bool { + func startOutgoingCall(callUUID: String) -> Bool { let m = ChatModel.shared - if let call = m.activeCall, call.callkitUUID == callUUID { + if let call = m.activeCall, call.callUUID == callUUID { m.showCallView = true - Task { await m.callCommand.processCommand(.capabilities(media: call.localMedia)) } + Task { await m.callCommand.processCommand(.capabilities(media: call.initialCallType)) } return true } return false } - func answerIncomingCall(callUUID: UUID) -> Bool { + func answerIncomingCall(callUUID: String) -> Bool { if let invitation = getCallInvitation(callUUID) { answerIncomingCall(invitation: invitation) return true @@ -42,9 +42,9 @@ class CallManager { let call = Call( direction: .incoming, contact: invitation.contact, - callkitUUID: invitation.callkitUUID, + callUUID: invitation.callUUID, callState: .invitationAccepted, - localMedia: invitation.callType.media, + initialCallType: invitation.callType.media, sharedKey: invitation.sharedKey ) call.speakerEnabled = invitation.callType.media == .video @@ -68,17 +68,17 @@ class CallManager { } } - func enableMedia(media: CallMediaType, enable: Bool, callUUID: UUID) -> Bool { - if let call = ChatModel.shared.activeCall, call.callkitUUID == callUUID { + func enableMedia(source: CallMediaSource, enable: Bool, callUUID: String) -> Bool { + if let call = ChatModel.shared.activeCall, call.callUUID == callUUID { let m = ChatModel.shared - Task { await m.callCommand.processCommand(.media(media: media, enable: enable)) } + Task { await m.callCommand.processCommand(.media(source: source, enable: enable)) } return true } return false } - func endCall(callUUID: UUID, completed: @escaping (Bool) -> Void) { - if let call = ChatModel.shared.activeCall, call.callkitUUID == callUUID { + func endCall(callUUID: String, completed: @escaping (Bool) -> Void) { + if let call = ChatModel.shared.activeCall, call.callUUID == callUUID { endCall(call: call) { completed(true) } } else if let invitation = getCallInvitation(callUUID) { endCall(invitation: invitation) { completed(true) } @@ -126,8 +126,8 @@ class CallManager { } } - private func getCallInvitation(_ callUUID: UUID) -> RcvCallInvitation? { - if let (_, invitation) = ChatModel.shared.callInvitations.first(where: { (_, inv) in inv.callkitUUID == callUUID }) { + private func getCallInvitation(_ callUUID: String) -> RcvCallInvitation? { + if let (_, invitation) = ChatModel.shared.callInvitations.first(where: { (_, inv) in inv.callUUID == callUUID }) { return invitation } return nil diff --git a/apps/ios/Shared/Views/Call/CallViewRenderers.swift b/apps/ios/Shared/Views/Call/CallViewRenderers.swift index a3201d9351..e779093a24 100644 --- a/apps/ios/Shared/Views/Call/CallViewRenderers.swift +++ b/apps/ios/Shared/Views/Call/CallViewRenderers.swift @@ -10,40 +10,49 @@ import AVKit struct CallViewRemote: UIViewRepresentable { var client: WebRTCClient - var activeCall: Binding + @ObservedObject var call: Call @State var enablePip: (Bool) -> Void = {_ in } @Binding var activeCallViewIsCollapsed: Bool + @Binding var contentMode: UIView.ContentMode @Binding var pipShown: Bool - init(client: WebRTCClient, activeCall: Binding, activeCallViewIsCollapsed: Binding, pipShown: Binding) { - self.client = client - self.activeCall = activeCall - self._activeCallViewIsCollapsed = activeCallViewIsCollapsed - self._pipShown = pipShown - } - func makeUIView(context: Context) -> UIView { let view = UIView() - if let call = activeCall.wrappedValue { - let remoteRenderer = RTCMTLVideoView(frame: view.frame) - remoteRenderer.videoContentMode = .scaleAspectFill - client.addRemoteRenderer(call, remoteRenderer) - addSubviewAndResize(remoteRenderer, into: view) + let remoteCameraRenderer = RTCMTLVideoView(frame: view.frame) + remoteCameraRenderer.videoContentMode = contentMode + remoteCameraRenderer.tag = 0 - if AVPictureInPictureController.isPictureInPictureSupported() { - makeViewWithRTCRenderer(call, remoteRenderer, view, context) - } + let screenVideo = call.peerMediaSources.screenVideo + let remoteScreenRenderer = RTCMTLVideoView(frame: view.frame) + remoteScreenRenderer.videoContentMode = contentMode + remoteScreenRenderer.tag = 1 + remoteScreenRenderer.alpha = screenVideo ? 1 : 0 + + context.coordinator.cameraRenderer = remoteCameraRenderer + context.coordinator.screenRenderer = remoteScreenRenderer + client.addRemoteCameraRenderer(remoteCameraRenderer) + client.addRemoteScreenRenderer(remoteScreenRenderer) + if screenVideo { + addSubviewAndResize(remoteScreenRenderer, remoteCameraRenderer, into: view) + } else { + addSubviewAndResize(remoteCameraRenderer, remoteScreenRenderer, into: view) + } + + if AVPictureInPictureController.isPictureInPictureSupported() { + makeViewWithRTCRenderer(remoteCameraRenderer, remoteScreenRenderer, view, context) } return view } - func makeViewWithRTCRenderer(_ call: WebRTCClient.Call, _ remoteRenderer: RTCMTLVideoView, _ view: UIView, _ context: Context) { - let pipRemoteRenderer = RTCMTLVideoView(frame: view.frame) - pipRemoteRenderer.videoContentMode = .scaleAspectFill - + func makeViewWithRTCRenderer(_ remoteCameraRenderer: RTCMTLVideoView, _ remoteScreenRenderer: RTCMTLVideoView, _ view: UIView, _ context: Context) { + let pipRemoteCameraRenderer = RTCMTLVideoView(frame: view.frame) + pipRemoteCameraRenderer.videoContentMode = .scaleAspectFill + + let pipRemoteScreenRenderer = RTCMTLVideoView(frame: view.frame) + pipRemoteScreenRenderer.videoContentMode = .scaleAspectFill + let pipVideoCallViewController = AVPictureInPictureVideoCallViewController() pipVideoCallViewController.preferredContentSize = CGSize(width: 1080, height: 1920) - addSubviewAndResize(pipRemoteRenderer, into: pipVideoCallViewController.view) let pipContentSource = AVPictureInPictureController.ContentSource( activeVideoCallSourceView: view, contentViewController: pipVideoCallViewController @@ -55,7 +64,9 @@ struct CallViewRemote: UIViewRepresentable { context.coordinator.pipController = pipController context.coordinator.willShowHide = { show in if show { - client.addRemoteRenderer(call, pipRemoteRenderer) + client.addRemoteCameraRenderer(pipRemoteCameraRenderer) + client.addRemoteScreenRenderer(pipRemoteScreenRenderer) + context.coordinator.relayout() DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { activeCallViewIsCollapsed = true } @@ -67,13 +78,29 @@ struct CallViewRemote: UIViewRepresentable { } context.coordinator.didShowHide = { show in if show { - remoteRenderer.isHidden = true + remoteCameraRenderer.isHidden = true + remoteScreenRenderer.isHidden = true } else { - client.removeRemoteRenderer(call, pipRemoteRenderer) - remoteRenderer.isHidden = false + client.removeRemoteCameraRenderer(pipRemoteCameraRenderer) + client.removeRemoteScreenRenderer(pipRemoteScreenRenderer) + remoteCameraRenderer.isHidden = false + remoteScreenRenderer.isHidden = false } pipShown = show } + context.coordinator.relayout = { + let camera = call.peerMediaSources.camera + let screenVideo = call.peerMediaSources.screenVideo + pipRemoteCameraRenderer.alpha = camera ? 1 : 0 + pipRemoteScreenRenderer.alpha = screenVideo ? 1 : 0 + if screenVideo { + addSubviewAndResize(pipRemoteScreenRenderer, pipRemoteCameraRenderer, pip: true, into: pipVideoCallViewController.view) + } else { + addSubviewAndResize(pipRemoteCameraRenderer, pipRemoteScreenRenderer, pip: true, into: pipVideoCallViewController.view) + } + (pipVideoCallViewController.view.subviews[0] as! RTCMTLVideoView).videoContentMode = contentMode + (pipVideoCallViewController.view.subviews[1] as! RTCMTLVideoView).videoContentMode = .scaleAspectFill + } DispatchQueue.main.async { enablePip = { enable in if enable != pipShown /* pipController.isPictureInPictureActive */ { @@ -88,24 +115,50 @@ struct CallViewRemote: UIViewRepresentable { } func makeCoordinator() -> Coordinator { - Coordinator() + Coordinator(client) } func updateUIView(_ view: UIView, context: Context) { logger.debug("CallView.updateUIView remote") + let camera = view.subviews.first(where: { $0.tag == 0 })! + let screen = view.subviews.first(where: { $0.tag == 1 })! + let screenVideo = call.peerMediaSources.screenVideo + if screenVideo && screen.alpha == 0 { + screen.alpha = 1 + addSubviewAndResize(screen, camera, into: view) + } else if !screenVideo && screen.alpha == 1 { + screen.alpha = 0 + addSubviewAndResize(camera, screen, into: view) + } + (view.subviews[0] as! RTCMTLVideoView).videoContentMode = contentMode + (view.subviews[1] as! RTCMTLVideoView).videoContentMode = .scaleAspectFill + + camera.alpha = call.peerMediaSources.camera ? 1 : 0 + screen.alpha = call.peerMediaSources.screenVideo ? 1 : 0 + DispatchQueue.main.async { if activeCallViewIsCollapsed != pipShown { enablePip(activeCallViewIsCollapsed) + } else if pipShown { + context.coordinator.relayout() } } } // MARK: - Coordinator class Coordinator: NSObject, AVPictureInPictureControllerDelegate { + var cameraRenderer: RTCMTLVideoView? + var screenRenderer: RTCMTLVideoView? + var client: WebRTCClient var pipController: AVPictureInPictureController? = nil var willShowHide: (Bool) -> Void = { _ in } var didShowHide: (Bool) -> Void = { _ in } - + var relayout: () -> Void = {} + + required init(_ client: WebRTCClient) { + self.client = client + } + func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { willShowHide(true) } @@ -127,11 +180,20 @@ struct CallViewRemote: UIViewRepresentable { } deinit { + // TODO: deinit is not called when changing call type from audio to video and back, + // which causes many renderers can be created and added to stream (if enabling/disabling + // video while not yet connected in outgoing call) pipController?.stopPictureInPicture() pipController?.canStartPictureInPictureAutomaticallyFromInline = false pipController?.contentSource = nil pipController?.delegate = nil pipController = nil + if let cameraRenderer { + client.removeRemoteCameraRenderer(cameraRenderer) + } + if let screenRenderer { + client.removeRemoteScreenRenderer(screenRenderer) + } } } @@ -148,51 +210,109 @@ struct CallViewRemote: UIViewRepresentable { struct CallViewLocal: UIViewRepresentable { var client: WebRTCClient - var activeCall: Binding var localRendererAspectRatio: Binding @State var pipStateChanged: (Bool) -> Void = {_ in } @Binding var pipShown: Bool - init(client: WebRTCClient, activeCall: Binding, localRendererAspectRatio: Binding, pipShown: Binding) { + init(client: WebRTCClient, localRendererAspectRatio: Binding, pipShown: Binding) { self.client = client - self.activeCall = activeCall self.localRendererAspectRatio = localRendererAspectRatio self._pipShown = pipShown } func makeUIView(context: Context) -> UIView { let view = UIView() - if let call = activeCall.wrappedValue { - let localRenderer = RTCEAGLVideoView(frame: .zero) - client.addLocalRenderer(call, localRenderer) - client.startCaptureLocalVideo(call) - addSubviewAndResize(localRenderer, into: view) - DispatchQueue.main.async { - pipStateChanged = { shown in - localRenderer.isHidden = shown - } + let localRenderer = RTCEAGLVideoView(frame: .zero) + context.coordinator.renderer = localRenderer + client.addLocalRenderer(localRenderer) + addSubviewAndResize(localRenderer, nil, into: view) + DispatchQueue.main.async { + pipStateChanged = { shown in + localRenderer.isHidden = shown } } return view } + func makeCoordinator() -> Coordinator { + Coordinator(client) + } + func updateUIView(_ view: UIView, context: Context) { logger.debug("CallView.updateUIView local") pipStateChanged(pipShown) } + + // MARK: - Coordinator + class Coordinator: NSObject, AVPictureInPictureControllerDelegate { + var renderer: RTCEAGLVideoView? + var client: WebRTCClient + + required init(_ client: WebRTCClient) { + self.client = client + } + + deinit { + if let renderer { + client.removeLocalRenderer(renderer) + } + } + } } -private func addSubviewAndResize(_ view: UIView, into containerView: UIView) { - containerView.addSubview(view) - view.translatesAutoresizingMaskIntoConstraints = false - containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", - options: [], - metrics: nil, - views: ["view": view])) +private func addSubviewAndResize(_ fullscreen: UIView, _ end: UIView?, pip: Bool = false, into containerView: UIView) { + if containerView.subviews.firstIndex(of: fullscreen) == 0 && ((end == nil && containerView.subviews.count == 1) || (end != nil && containerView.subviews.firstIndex(of: end!) == 1)) { + // Nothing to do, elements on their places + return + } + containerView.removeConstraints(containerView.constraints) + containerView.subviews.forEach { sub in sub.removeFromSuperview()} - containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", + containerView.addSubview(fullscreen) + fullscreen.translatesAutoresizingMaskIntoConstraints = false + fullscreen.layer.cornerRadius = 0 + fullscreen.layer.masksToBounds = false + + if let end { + containerView.addSubview(end) + end.translatesAutoresizingMaskIntoConstraints = false + end.layer.cornerRadius = pip ? 8 : 10 + end.layer.masksToBounds = true + } + + let constraintFullscreenV = NSLayoutConstraint.constraints( + withVisualFormat: "V:|[fullscreen]|", options: [], metrics: nil, - views: ["view": view])) + views: ["fullscreen": fullscreen] + ) + let constraintFullscreenH = NSLayoutConstraint.constraints( + withVisualFormat: "H:|[fullscreen]|", + options: [], + metrics: nil, + views: ["fullscreen": fullscreen] + ) + + containerView.addConstraints(constraintFullscreenV) + containerView.addConstraints(constraintFullscreenH) + + if let end { + let constraintEndWidth = NSLayoutConstraint( + item: end, attribute: .width, relatedBy: .equal, toItem: containerView, attribute: .width, multiplier: pip ? 0.5 : 0.3, constant: 0 + ) + let constraintEndHeight = NSLayoutConstraint( + item: end, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .width, multiplier: pip ? 0.5 * 1.33 : 0.3 * 1.33, constant: 0 + ) + let constraintEndX = NSLayoutConstraint( + item: end, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: pip ? 0.5 : 0.7, constant: pip ? -8 : -17 + ) + let constraintEndY = NSLayoutConstraint( + item: end, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1, constant: pip ? -8 : -92 + ) + containerView.addConstraint(constraintEndWidth) + containerView.addConstraint(constraintEndHeight) + containerView.addConstraint(constraintEndX) + containerView.addConstraint(constraintEndY) + } containerView.layoutIfNeeded() } diff --git a/apps/ios/Shared/Views/Call/IncomingCallView.swift b/apps/ios/Shared/Views/Call/IncomingCallView.swift index 4960281d72..5479a9fada 100644 --- a/apps/ios/Shared/Views/Call/IncomingCallView.swift +++ b/apps/ios/Shared/Views/Call/IncomingCallView.swift @@ -38,6 +38,7 @@ struct IncomingCallView: View { } HStack { ProfilePreview(profileOf: invitation.contact, color: .white) + .padding(.vertical, 6) Spacer() callButton("Reject", "phone.down.fill", .red) { diff --git a/apps/ios/Shared/Views/Call/WebRTC.swift b/apps/ios/Shared/Views/Call/WebRTC.swift index 333dc082d5..ef9135761c 100644 --- a/apps/ios/Shared/Views/Call/WebRTC.swift +++ b/apps/ios/Shared/Views/Call/WebRTC.swift @@ -18,49 +18,49 @@ class Call: ObservableObject, Equatable { var direction: CallDirection var contact: Contact - var callkitUUID: UUID? - var localMedia: CallMediaType + var callUUID: String? + var initialCallType: CallMediaType + @Published var localMediaSources: CallMediaSources @Published var callState: CallState @Published var localCapabilities: CallCapabilities? - @Published var peerMedia: CallMediaType? + @Published var peerMediaSources: CallMediaSources = CallMediaSources() @Published var sharedKey: String? - @Published var audioEnabled = true @Published var speakerEnabled = false - @Published var videoEnabled: Bool @Published var connectionInfo: ConnectionInfo? @Published var connectedAt: Date? = nil init( direction: CallDirection, contact: Contact, - callkitUUID: UUID?, + callUUID: String?, callState: CallState, - localMedia: CallMediaType, + initialCallType: CallMediaType, sharedKey: String? = nil ) { self.direction = direction self.contact = contact - self.callkitUUID = callkitUUID + self.callUUID = callUUID self.callState = callState - self.localMedia = localMedia + self.initialCallType = initialCallType self.sharedKey = sharedKey - self.videoEnabled = localMedia == .video + self.localMediaSources = CallMediaSources( + mic: AVCaptureDevice.authorizationStatus(for: .audio) == .authorized, + camera: initialCallType == .video && AVCaptureDevice.authorizationStatus(for: .video) == .authorized) } var encrypted: Bool { get { localEncrypted && sharedKey != nil } } - var localEncrypted: Bool { get { localCapabilities?.encryption ?? false } } + private var localEncrypted: Bool { get { localCapabilities?.encryption ?? false } } var encryptionStatus: LocalizedStringKey { get { switch callState { case .waitCapabilities: return "" case .invitationSent: return localEncrypted ? "e2e encrypted" : "no e2e encryption" case .invitationAccepted: return sharedKey == nil ? "contact has no e2e encryption" : "contact has e2e encryption" - default: return !localEncrypted ? "no e2e encryption" : sharedKey == nil ? "contact has no e2e encryption" : "e2e encrypted" + default: return !localEncrypted ? "no e2e encryption" : sharedKey == nil ? "contact has no e2e encryption" : "e2e encrypted" } } } - var hasMedia: Bool { get { callState == .offerSent || callState == .negotiated || callState == .connected } } - var supportsVideo: Bool { get { peerMedia == .video || localMedia == .video } } + var hasVideo: Bool { get { localMediaSources.hasVideo || peerMediaSources.hasVideo } } } enum CallDirection { @@ -105,18 +105,28 @@ struct WVAPIMessage: Equatable, Decodable, Encodable { var command: WCallCommand? } +struct CallMediaSources: Equatable, Codable { + var mic: Bool = false + var camera: Bool = false + var screenAudio: Bool = false + var screenVideo: Bool = false + + var hasVideo: Bool { get { camera || screenVideo } } +} + enum WCallCommand: Equatable, Encodable, Decodable { case capabilities(media: CallMediaType) case start(media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil) case offer(offer: String, iceCandidates: String, media: CallMediaType, aesKey: String? = nil, iceServers: [RTCIceServer]? = nil, relay: Bool? = nil) case answer(answer: String, iceCandidates: String) case ice(iceCandidates: String) - case media(media: CallMediaType, enable: Bool) + case media(source: CallMediaSource, enable: Bool) case end enum CodingKeys: String, CodingKey { case type case media + case source case aesKey case offer case answer @@ -167,9 +177,9 @@ enum WCallCommand: Equatable, Encodable, Decodable { case let .ice(iceCandidates): try container.encode("ice", forKey: .type) try container.encode(iceCandidates, forKey: .iceCandidates) - case let .media(media, enable): + case let .media(source, enable): try container.encode("media", forKey: .type) - try container.encode(media, forKey: .media) + try container.encode(source, forKey: .media) try container.encode(enable, forKey: .enable) case .end: try container.encode("end", forKey: .type) @@ -205,9 +215,9 @@ enum WCallCommand: Equatable, Encodable, Decodable { let iceCandidates = try container.decode(String.self, forKey: CodingKeys.iceCandidates) self = .ice(iceCandidates: iceCandidates) case "media": - let media = try container.decode(CallMediaType.self, forKey: CodingKeys.media) + let source = try container.decode(CallMediaSource.self, forKey: CodingKeys.source) let enable = try container.decode(Bool.self, forKey: CodingKeys.enable) - self = .media(media: media, enable: enable) + self = .media(source: source, enable: enable) case "end": self = .end default: @@ -224,6 +234,7 @@ enum WCallResponse: Equatable, Decodable { case ice(iceCandidates: String) case connection(state: ConnectionState) case connected(connectionInfo: ConnectionInfo) + case peerMedia(source: CallMediaSource, enabled: Bool) case ended case ok case error(message: String) @@ -238,6 +249,8 @@ enum WCallResponse: Equatable, Decodable { case state case connectionInfo case message + case source + case enabled } var respType: String { @@ -249,6 +262,7 @@ enum WCallResponse: Equatable, Decodable { case .ice: return "ice" case .connection: return "connection" case .connected: return "connected" + case .peerMedia: return "peerMedia" case .ended: return "ended" case .ok: return "ok" case .error: return "error" @@ -283,6 +297,10 @@ enum WCallResponse: Equatable, Decodable { case "connected": let connectionInfo = try container.decode(ConnectionInfo.self, forKey: CodingKeys.connectionInfo) self = .connected(connectionInfo: connectionInfo) + case "peerMedia": + let source = try container.decode(CallMediaSource.self, forKey: CodingKeys.source) + let enabled = try container.decode(Bool.self, forKey: CodingKeys.enabled) + self = .peerMedia(source: source, enabled: enabled) case "ended": self = .ended case "ok": @@ -324,6 +342,10 @@ extension WCallResponse: Encodable { case let .connected(connectionInfo): try container.encode("connected", forKey: .type) try container.encode(connectionInfo, forKey: .connectionInfo) + case let .peerMedia(source, enabled): + try container.encode("peerMedia", forKey: .type) + try container.encode(source, forKey: .source) + try container.encode(enabled, forKey: .enabled) case .ended: try container.encode("ended", forKey: .type) case .ok: @@ -376,7 +398,7 @@ actor WebRTCCommandProcessor { func shouldRunCommand(_ client: WebRTCClient, _ c: WCallCommand) -> Bool { switch c { case .capabilities, .start, .offer, .end: true - default: client.activeCall.wrappedValue != nil + default: client.activeCall != nil } } } diff --git a/apps/ios/Shared/Views/Call/WebRTCClient.swift b/apps/ios/Shared/Views/Call/WebRTCClient.swift index 0b4917c103..db7910836e 100644 --- a/apps/ios/Shared/Views/Call/WebRTCClient.swift +++ b/apps/ios/Shared/Views/Call/WebRTCClient.swift @@ -23,15 +23,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg struct Call { var connection: RTCPeerConnection var iceCandidates: IceCandidates - var localMedia: CallMediaType var localCamera: RTCVideoCapturer? - var localVideoSource: RTCVideoSource? - var localStream: RTCVideoTrack? - var remoteStream: RTCVideoTrack? - var device: AVCaptureDevice.Position = .front + var localAudioTrack: RTCAudioTrack? + var localVideoTrack: RTCVideoTrack? + var remoteAudioTrack: RTCAudioTrack? + var remoteVideoTrack: RTCVideoTrack? + var remoteScreenAudioTrack: RTCAudioTrack? + var remoteScreenVideoTrack: RTCVideoTrack? + var device: AVCaptureDevice.Position var aesKey: String? var frameEncryptor: RTCFrameEncryptor? var frameDecryptor: RTCFrameDecryptor? + var peerHasOldVersion: Bool + } + + struct NotConnectedCall { + var audioTrack: RTCAudioTrack? + var localCameraAndTrack: (RTCVideoCapturer, RTCVideoTrack)? + var device: AVCaptureDevice.Position = .front } actor IceCandidates { @@ -51,17 +60,20 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg private let rtcAudioSession = RTCAudioSession.sharedInstance() private let audioQueue = DispatchQueue(label: "chat.simplex.app.audio") private var sendCallResponse: (WVAPIMessage) async -> Void - var activeCall: Binding + var activeCall: Call? + var notConnectedCall: NotConnectedCall? private var localRendererAspectRatio: Binding + var cameraRenderers: [RTCVideoRenderer] = [] + var screenRenderers: [RTCVideoRenderer] = [] + @available(*, unavailable) override init() { fatalError("Unimplemented") } - required init(_ activeCall: Binding, _ sendCallResponse: @escaping (WVAPIMessage) async -> Void, _ localRendererAspectRatio: Binding) { + required init(_ sendCallResponse: @escaping (WVAPIMessage) async -> Void, _ localRendererAspectRatio: Binding) { self.sendCallResponse = sendCallResponse - self.activeCall = activeCall self.localRendererAspectRatio = localRendererAspectRatio rtcAudioSession.useManualAudio = CallController.useCallKit() rtcAudioSession.isAudioEnabled = !CallController.useCallKit() @@ -78,39 +90,45 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg func initializeCall(_ iceServers: [WebRTC.RTCIceServer]?, _ mediaType: CallMediaType, _ aesKey: String?, _ relay: Bool?) -> Call { let connection = createPeerConnection(iceServers ?? getWebRTCIceServers() ?? defaultIceServers, relay) connection.delegate = self - createAudioSender(connection) - var localStream: RTCVideoTrack? = nil - var remoteStream: RTCVideoTrack? = nil + let device = notConnectedCall?.device ?? .front var localCamera: RTCVideoCapturer? = nil - var localVideoSource: RTCVideoSource? = nil - if mediaType == .video { - (localStream, remoteStream, localCamera, localVideoSource) = createVideoSender(connection) + var localAudioTrack: RTCAudioTrack? = nil + var localVideoTrack: RTCVideoTrack? = nil + if let localCameraAndTrack = notConnectedCall?.localCameraAndTrack { + (localCamera, localVideoTrack) = localCameraAndTrack + } else if notConnectedCall == nil && mediaType == .video { + (localCamera, localVideoTrack) = createVideoTrackAndStartCapture(device) } + if let audioTrack = notConnectedCall?.audioTrack { + localAudioTrack = audioTrack + } else if notConnectedCall == nil { + localAudioTrack = createAudioTrack() + } + notConnectedCall?.localCameraAndTrack = nil + notConnectedCall?.audioTrack = nil + var frameEncryptor: RTCFrameEncryptor? = nil var frameDecryptor: RTCFrameDecryptor? = nil if aesKey != nil { let encryptor = RTCFrameEncryptor.init(sizeChange: Int32(WebRTCClient.ivTagBytes)) encryptor.delegate = self frameEncryptor = encryptor - connection.senders.forEach { $0.setRtcFrameEncryptor(encryptor) } let decryptor = RTCFrameDecryptor.init(sizeChange: -Int32(WebRTCClient.ivTagBytes)) decryptor.delegate = self frameDecryptor = decryptor - // Has no video receiver in outgoing call if applied here, see [peerConnection(_ connection: RTCPeerConnection, didChange newState] - // connection.receivers.forEach { $0.setRtcFrameDecryptor(decryptor) } } return Call( connection: connection, iceCandidates: IceCandidates(), - localMedia: mediaType, localCamera: localCamera, - localVideoSource: localVideoSource, - localStream: localStream, - remoteStream: remoteStream, + localAudioTrack: localAudioTrack, + localVideoTrack: localVideoTrack, + device: device, aesKey: aesKey, frameEncryptor: frameEncryptor, - frameDecryptor: frameDecryptor + frameDecryptor: frameDecryptor, + peerHasOldVersion: false ) } @@ -151,18 +169,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg func sendCallCommand(command: WCallCommand) async { var resp: WCallResponse? = nil - let pc = activeCall.wrappedValue?.connection + let pc = activeCall?.connection switch command { - case .capabilities: + case let .capabilities(media): // outgoing + let localCameraAndTrack: (RTCVideoCapturer, RTCVideoTrack)? = media == .video + ? createVideoTrackAndStartCapture(.front) + : nil + notConnectedCall = NotConnectedCall(audioTrack: createAudioTrack(), localCameraAndTrack: localCameraAndTrack, device: .front) resp = .capabilities(capabilities: CallCapabilities(encryption: WebRTCClient.enableEncryption)) - case let .start(media: media, aesKey, iceServers, relay): + case let .start(media: media, aesKey, iceServers, relay): // incoming logger.debug("starting incoming call - create webrtc session") - if activeCall.wrappedValue != nil { endCall() } + if activeCall != nil { endCall() } let encryption = WebRTCClient.enableEncryption let call = initializeCall(iceServers?.toWebRTCIceServers(), media, encryption ? aesKey : nil, relay) - activeCall.wrappedValue = call + activeCall = call + setupLocalTracks(true, call) let (offer, error) = await call.connection.offer() if let offer = offer { + setupEncryptionForLocalTracks(call) resp = .offer( offer: compressToBase64(input: encodeJSON(CustomRTCSessionDescription(type: offer.type.toSdpType(), sdp: offer.sdp))), iceCandidates: compressToBase64(input: encodeJSON(await self.getInitialIceCandidates())), @@ -172,18 +196,24 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg } else { resp = .error(message: "offer error: \(error?.localizedDescription ?? "unknown error")") } - case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay): - if activeCall.wrappedValue != nil { + case let .offer(offer, iceCandidates, media, aesKey, iceServers, relay): // outgoing + if activeCall != nil { resp = .error(message: "accept: call already started") } else if !WebRTCClient.enableEncryption && aesKey != nil { resp = .error(message: "accept: encryption is not supported") } else if let offer: CustomRTCSessionDescription = decodeJSON(decompressFromBase64(input: offer)), let remoteIceCandidates: [RTCIceCandidate] = decodeJSON(decompressFromBase64(input: iceCandidates)) { let call = initializeCall(iceServers?.toWebRTCIceServers(), media, WebRTCClient.enableEncryption ? aesKey : nil, relay) - activeCall.wrappedValue = call + activeCall = call let pc = call.connection if let type = offer.type, let sdp = offer.sdp { if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil { + setupLocalTracks(false, call) + setupEncryptionForLocalTracks(call) + pc.transceivers.forEach { transceiver in + transceiver.setDirection(.sendRecv, error: nil) + } + await adaptToOldVersion(pc.transceivers.count <= 2) let (answer, error) = await pc.answer() if let answer = answer { self.addIceCandidates(pc, remoteIceCandidates) @@ -200,7 +230,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg } } } - case let .answer(answer, iceCandidates): + case let .answer(answer, iceCandidates): // incoming if pc == nil { resp = .error(message: "answer: call not started") } else if pc?.localDescription == nil { @@ -212,6 +242,9 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg let type = answer.type, let sdp = answer.sdp, let pc = pc { if (try? await pc.setRemoteDescription(RTCSessionDescription(type: type.toWebRTCSdpType(), sdp: sdp))) != nil { + var currentDirection: RTCRtpTransceiverDirection = .sendOnly + pc.transceivers[2].currentDirection(¤tDirection) + await adaptToOldVersion(currentDirection == .sendOnly) addIceCandidates(pc, remoteIceCandidates) resp = .ok } else { @@ -226,13 +259,11 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg } else { resp = .error(message: "ice: call not started") } - case let .media(media, enable): - if activeCall.wrappedValue == nil { + case let .media(source, enable): + if activeCall == nil { resp = .error(message: "media: call not started") - } else if activeCall.wrappedValue?.localMedia == .audio && media == .video { - resp = .error(message: "media: no video") } else { - enableMedia(media, enable) + await enableMedia(source, enable) resp = .ok } case .end: @@ -247,7 +278,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg func getInitialIceCandidates() async -> [RTCIceCandidate] { await untilIceComplete(timeoutMs: 750, stepMs: 150) {} - let candidates = await activeCall.wrappedValue?.iceCandidates.getAndClear() ?? [] + let candidates = await activeCall?.iceCandidates.getAndClear() ?? [] logger.debug("WebRTCClient: sending initial ice candidates: \(candidates.count)") return candidates } @@ -255,7 +286,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg func waitForMoreIceCandidates() { Task { await untilIceComplete(timeoutMs: 12000, stepMs: 1500) { - let candidates = await self.activeCall.wrappedValue?.iceCandidates.getAndClear() ?? [] + let candidates = await self.activeCall?.iceCandidates.getAndClear() ?? [] if candidates.count > 0 { logger.debug("WebRTCClient: sending more ice candidates: \(candidates.count)") await self.sendIceCandidates(candidates) @@ -272,25 +303,202 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg ) } - func enableMedia(_ media: CallMediaType, _ enable: Bool) { - logger.debug("WebRTCClient: enabling media \(media.rawValue) \(enable)") - media == .video ? setVideoEnabled(enable) : setAudioEnabled(enable) + func setupMuteUnmuteListener(_ transceiver: RTCRtpTransceiver, _ track: RTCMediaStreamTrack) { + // logger.log("Setting up mute/unmute listener in the call without encryption for mid = \(transceiver.mid)") + Task { + var lastBytesReceived: Int64 = 0 + // muted initially + var mutedSeconds = 4 + while let call = self.activeCall, transceiver.receiver.track?.readyState == .live { + let stats: RTCStatisticsReport = await call.connection.statistics(for: transceiver.receiver) + let stat = stats.statistics.values.first(where: { stat in stat.type == "inbound-rtp"}) + if let stat { + //logger.debug("Stat \(stat.debugDescription)") + let bytes = stat.values["bytesReceived"] as! Int64 + if bytes <= lastBytesReceived { + mutedSeconds += 1 + if mutedSeconds == 3 { + await MainActor.run { + self.onMediaMuteUnmute(transceiver.mid, true) + } + } + } else { + if mutedSeconds >= 3 { + await MainActor.run { + self.onMediaMuteUnmute(transceiver.mid, false) + } + } + lastBytesReceived = bytes + mutedSeconds = 0 + } + } + try? await Task.sleep(nanoseconds: 1000_000000) + } + } } - func addLocalRenderer(_ activeCall: Call, _ renderer: RTCEAGLVideoView) { - activeCall.localStream?.add(renderer) + @MainActor + func onMediaMuteUnmute(_ transceiverMid: String?, _ mute: Bool) { + guard let activeCall = ChatModel.shared.activeCall else { return } + let source = mediaSourceFromTransceiverMid(transceiverMid) + logger.log("Mute/unmute \(source.rawValue) track = \(mute) with mid = \(transceiverMid ?? "nil")") + if source == .mic && activeCall.peerMediaSources.mic == mute { + activeCall.peerMediaSources.mic = !mute + } else if (source == .camera && activeCall.peerMediaSources.camera == mute) { + activeCall.peerMediaSources.camera = !mute + } else if (source == .screenAudio && activeCall.peerMediaSources.screenAudio == mute) { + activeCall.peerMediaSources.screenAudio = !mute + } else if (source == .screenVideo && activeCall.peerMediaSources.screenVideo == mute) { + activeCall.peerMediaSources.screenVideo = !mute + } + } + + @MainActor + func enableMedia(_ source: CallMediaSource, _ enable: Bool) { + logger.debug("WebRTCClient: enabling media \(source.rawValue) \(enable)") + source == .camera ? setCameraEnabled(enable) : setAudioEnabled(enable) + } + + @MainActor + func adaptToOldVersion(_ peerHasOldVersion: Bool) { + activeCall?.peerHasOldVersion = peerHasOldVersion + if peerHasOldVersion { + logger.debug("The peer has an old version. Remote audio track is nil = \(self.activeCall?.remoteAudioTrack == nil), video = \(self.activeCall?.remoteVideoTrack == nil)") + onMediaMuteUnmute("0", false) + if activeCall?.remoteVideoTrack != nil { + onMediaMuteUnmute("1", false) + } + if ChatModel.shared.activeCall?.localMediaSources.camera == true && ChatModel.shared.activeCall?.peerMediaSources.camera == false { + logger.debug("Stopping video track for the old version") + activeCall?.connection.senders[1].track = nil + ChatModel.shared.activeCall?.localMediaSources.camera = false + (activeCall?.localCamera as? RTCCameraVideoCapturer)?.stopCapture() + activeCall?.localCamera = nil + activeCall?.localVideoTrack = nil + } + } + } + + func addLocalRenderer(_ renderer: RTCEAGLVideoView) { + if let activeCall { + if let track = activeCall.localVideoTrack { + track.add(renderer) + } + } else if let notConnectedCall { + if let track = notConnectedCall.localCameraAndTrack?.1 { + track.add(renderer) + } + } // To get width and height of a frame, see videoView(videoView:, didChangeVideoSize) renderer.delegate = self } + func removeLocalRenderer(_ renderer: RTCEAGLVideoView) { + if let activeCall { + if let track = activeCall.localVideoTrack { + track.remove(renderer) + } + } else if let notConnectedCall { + if let track = notConnectedCall.localCameraAndTrack?.1 { + track.remove(renderer) + } + } + renderer.delegate = nil + } + func videoView(_ videoView: RTCVideoRenderer, didChangeVideoSize size: CGSize) { guard size.height > 0 else { return } localRendererAspectRatio.wrappedValue = size.width / size.height } + func setupLocalTracks(_ incomingCall: Bool, _ call: Call) { + let pc = call.connection + let transceivers = call.connection.transceivers + let audioTrack = call.localAudioTrack + let videoTrack = call.localVideoTrack + + if incomingCall { + let micCameraInit = RTCRtpTransceiverInit() + // streamIds required for old versions which adds tracks from stream, not from track property + micCameraInit.streamIds = ["micCamera"] + + let screenAudioVideoInit = RTCRtpTransceiverInit() + screenAudioVideoInit.streamIds = ["screenAudioVideo"] + + // incoming call, no transceivers yet. But they should be added in order: mic, camera, screen audio, screen video + // mid = 0, mic + if let audioTrack { + pc.addTransceiver(with: audioTrack, init: micCameraInit) + } else { + pc.addTransceiver(of: .audio, init: micCameraInit) + } + // mid = 1, camera + if let videoTrack { + pc.addTransceiver(with: videoTrack, init: micCameraInit) + } else { + pc.addTransceiver(of: .video, init: micCameraInit) + } + // mid = 2, screenAudio + pc.addTransceiver(of: .audio, init: screenAudioVideoInit) + // mid = 3, screenVideo + pc.addTransceiver(of: .video, init: screenAudioVideoInit) + } else { + // new version + if transceivers.count > 2 { + // Outgoing call. All transceivers are ready. Don't addTrack() because it will create new transceivers, replace existing (nil) tracks + transceivers + .first(where: { elem in mediaSourceFromTransceiverMid(elem.mid) == .mic })? + .sender.track = audioTrack + transceivers + .first(where: { elem in mediaSourceFromTransceiverMid(elem.mid) == .camera })? + .sender.track = videoTrack + } else { + // old version, only two transceivers + if let audioTrack { + pc.add(audioTrack, streamIds: ["micCamera"]) + } else { + // it's important to have any track in order to be able to turn it on again (currently it's off) + let sender = pc.add(createAudioTrack(), streamIds: ["micCamera"]) + sender?.track = nil + } + if let videoTrack { + pc.add(videoTrack, streamIds: ["micCamera"]) + } else { + // it's important to have any track in order to be able to turn it on again (currently it's off) + let localVideoSource = WebRTCClient.factory.videoSource() + let localVideoTrack = WebRTCClient.factory.videoTrack(with: localVideoSource, trackId: "video0") + let sender = pc.add(localVideoTrack, streamIds: ["micCamera"]) + sender?.track = nil + } + } + } + } + + func mediaSourceFromTransceiverMid(_ mid: String?) -> CallMediaSource { + switch mid { + case "0": + return .mic + case "1": + return .camera + case "2": + return .screenAudio + case "3": + return .screenVideo + default: + return .unknown + } + } + + // Should be called after local description set + func setupEncryptionForLocalTracks(_ call: Call) { + if let encryptor = call.frameEncryptor { + call.connection.senders.forEach { $0.setRtcFrameEncryptor(encryptor) } + } + } + func frameDecryptor(_ decryptor: RTCFrameDecryptor, mediaType: RTCRtpMediaType, withFrame encrypted: Data) -> Data? { guard encrypted.count > 0 else { return nil } - if var key: [CChar] = activeCall.wrappedValue?.aesKey?.cString(using: .utf8), + if var key: [CChar] = activeCall?.aesKey?.cString(using: .utf8), let pointer: UnsafeMutableRawPointer = malloc(encrypted.count) { memcpy(pointer, (encrypted as NSData).bytes, encrypted.count) let isKeyFrame = encrypted[0] & 1 == 0 @@ -304,7 +512,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg func frameEncryptor(_ encryptor: RTCFrameEncryptor, mediaType: RTCRtpMediaType, withFrame unencrypted: Data) -> Data? { guard unencrypted.count > 0 else { return nil } - if var key: [CChar] = activeCall.wrappedValue?.aesKey?.cString(using: .utf8), + if var key: [CChar] = activeCall?.aesKey?.cString(using: .utf8), let pointer: UnsafeMutableRawPointer = malloc(unencrypted.count + WebRTCClient.ivTagBytes) { memcpy(pointer, (unencrypted as NSData).bytes, unencrypted.count) let isKeyFrame = unencrypted[0] & 1 == 0 @@ -327,18 +535,42 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg } } - func addRemoteRenderer(_ activeCall: Call, _ renderer: RTCVideoRenderer) { - activeCall.remoteStream?.add(renderer) + func addRemoteCameraRenderer(_ renderer: RTCVideoRenderer) { + if activeCall?.remoteVideoTrack != nil { + activeCall?.remoteVideoTrack?.add(renderer) + } else { + cameraRenderers.append(renderer) + } } - func removeRemoteRenderer(_ activeCall: Call, _ renderer: RTCVideoRenderer) { - activeCall.remoteStream?.remove(renderer) + func removeRemoteCameraRenderer(_ renderer: RTCVideoRenderer) { + if activeCall?.remoteVideoTrack != nil { + activeCall?.remoteVideoTrack?.remove(renderer) + } else { + cameraRenderers.removeAll(where: { $0.isEqual(renderer) }) + } } - func startCaptureLocalVideo(_ activeCall: Call) { + func addRemoteScreenRenderer(_ renderer: RTCVideoRenderer) { + if activeCall?.remoteScreenVideoTrack != nil { + activeCall?.remoteScreenVideoTrack?.add(renderer) + } else { + screenRenderers.append(renderer) + } + } + + func removeRemoteScreenRenderer(_ renderer: RTCVideoRenderer) { + if activeCall?.remoteScreenVideoTrack != nil { + activeCall?.remoteScreenVideoTrack?.remove(renderer) + } else { + screenRenderers.removeAll(where: { $0.isEqual(renderer) }) + } + } + + func startCaptureLocalVideo(_ device: AVCaptureDevice.Position?, _ capturer: RTCVideoCapturer?) { #if targetEnvironment(simulator) guard - let capturer = activeCall.localCamera as? RTCFileVideoCapturer + let capturer = (activeCall?.localCamera ?? notConnectedCall?.localCameraAndTrack?.0) as? RTCFileVideoCapturer else { logger.error("Unable to work with a file capturer") return @@ -348,10 +580,10 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg capturer.startCapturing(fromFileNamed: "sounds/video.mp4") #else guard - let capturer = activeCall.localCamera as? RTCCameraVideoCapturer, - let camera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == activeCall.device }) + let capturer = capturer as? RTCCameraVideoCapturer, + let camera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == device }) else { - logger.error("Unable to find a camera") + logger.error("Unable to find a camera or local track") return } @@ -377,19 +609,6 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg #endif } - private func createAudioSender(_ connection: RTCPeerConnection) { - let streamId = "stream" - let audioTrack = createAudioTrack() - connection.add(audioTrack, streamIds: [streamId]) - } - - private func createVideoSender(_ connection: RTCPeerConnection) -> (RTCVideoTrack?, RTCVideoTrack?, RTCVideoCapturer?, RTCVideoSource?) { - let streamId = "stream" - let (localVideoTrack, localCamera, localVideoSource) = createVideoTrack() - connection.add(localVideoTrack, streamIds: [streamId]) - return (localVideoTrack, connection.transceivers.first { $0.mediaType == .video }?.receiver.track as? RTCVideoTrack, localCamera, localVideoSource) - } - private func createAudioTrack() -> RTCAudioTrack { let audioConstrains = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil) let audioSource = WebRTCClient.factory.audioSource(with: audioConstrains) @@ -397,7 +616,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg return audioTrack } - private func createVideoTrack() -> (RTCVideoTrack, RTCVideoCapturer, RTCVideoSource) { + private func createVideoTrackAndStartCapture(_ device: AVCaptureDevice.Position) -> (RTCVideoCapturer, RTCVideoTrack) { let localVideoSource = WebRTCClient.factory.videoSource() #if targetEnvironment(simulator) @@ -407,19 +626,30 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg #endif let localVideoTrack = WebRTCClient.factory.videoTrack(with: localVideoSource, trackId: "video0") - return (localVideoTrack, localCamera, localVideoSource) + startCaptureLocalVideo(device, localCamera) + return (localCamera, localVideoTrack) } func endCall() { - guard let call = activeCall.wrappedValue else { return } + if #available(iOS 16.0, *) { + _endCall() + } else { + // Fixes `connection.close()` getting locked up in iOS15 + DispatchQueue.global(qos: .utility).async { self._endCall() } + } + } + + private func _endCall() { + (notConnectedCall?.localCameraAndTrack?.0 as? RTCCameraVideoCapturer)?.stopCapture() + guard let call = activeCall else { return } logger.debug("WebRTCClient: ending the call") - activeCall.wrappedValue = nil - (call.localCamera as? RTCCameraVideoCapturer)?.stopCapture() call.connection.close() call.connection.delegate = nil call.frameEncryptor?.delegate = nil call.frameDecryptor?.delegate = nil + (call.localCamera as? RTCCameraVideoCapturer)?.stopCapture() audioSessionToDefaults() + activeCall = nil } func untilIceComplete(timeoutMs: UInt64, stepMs: UInt64, action: @escaping () async -> Void) async { @@ -428,7 +658,7 @@ final class WebRTCClient: NSObject, RTCVideoViewDelegate, RTCFrameEncryptorDeleg _ = try? await Task.sleep(nanoseconds: stepMs * 1000000) t += stepMs await action() - } while t < timeoutMs && activeCall.wrappedValue?.connection.iceGatheringState != .complete + } while t < timeoutMs && activeCall?.connection.iceGatheringState != .complete } } @@ -489,11 +719,40 @@ extension WebRTCClient: RTCPeerConnectionDelegate { logger.debug("Connection should negotiate") } + func peerConnection(_ peerConnection: RTCPeerConnection, didStartReceivingOn transceiver: RTCRtpTransceiver) { + if let track = transceiver.receiver.track { + DispatchQueue.main.async { + // Doesn't work for outgoing video call (audio in video call works ok still, same as incoming call) +// if let decryptor = self.activeCall?.frameDecryptor { +// transceiver.receiver.setRtcFrameDecryptor(decryptor) +// } + let source = self.mediaSourceFromTransceiverMid(transceiver.mid) + switch source { + case .mic: self.activeCall?.remoteAudioTrack = track as? RTCAudioTrack + case .camera: + self.activeCall?.remoteVideoTrack = track as? RTCVideoTrack + self.cameraRenderers.forEach({ renderer in + self.activeCall?.remoteVideoTrack?.add(renderer) + }) + self.cameraRenderers.removeAll() + case .screenAudio: self.activeCall?.remoteScreenAudioTrack = track as? RTCAudioTrack + case .screenVideo: + self.activeCall?.remoteScreenVideoTrack = track as? RTCVideoTrack + self.screenRenderers.forEach({ renderer in + self.activeCall?.remoteScreenVideoTrack?.add(renderer) + }) + self.screenRenderers.removeAll() + case .unknown: () + } + } + self.setupMuteUnmuteListener(transceiver, track) + } + } + func peerConnection(_ connection: RTCPeerConnection, didChange newState: RTCIceConnectionState) { debugPrint("Connection new connection state: \(newState.toString() ?? "" + newState.rawValue.description) \(connection.receivers)") - guard let call = activeCall.wrappedValue, - let connectionStateString = newState.toString(), + guard let connectionStateString = newState.toString(), let iceConnectionStateString = connection.iceConnectionState.toString(), let iceGatheringStateString = connection.iceGatheringState.toString(), let signalingStateString = connection.signalingState.toString() @@ -514,18 +773,14 @@ extension WebRTCClient: RTCPeerConnectionDelegate { switch newState { case .checking: - if let frameDecryptor = activeCall.wrappedValue?.frameDecryptor { + if let frameDecryptor = activeCall?.frameDecryptor { connection.receivers.forEach { $0.setRtcFrameDecryptor(frameDecryptor) } } - let enableSpeaker: Bool - switch call.localMedia { - case .video: enableSpeaker = true - default: enableSpeaker = false - } + let enableSpeaker: Bool = ChatModel.shared.activeCall?.localMediaSources.hasVideo == true setSpeakerEnabledAndConfigureSession(enableSpeaker) case .connected: sendConnectedEvent(connection) case .disconnected, .failed: endCall() - default: do {} + default: () } } } @@ -537,7 +792,7 @@ extension WebRTCClient: RTCPeerConnectionDelegate { func peerConnection(_ connection: RTCPeerConnection, didGenerate candidate: WebRTC.RTCIceCandidate) { // logger.debug("Connection generated candidate \(candidate.debugDescription)") Task { - await self.activeCall.wrappedValue?.iceCandidates.append(candidate.toCandidate(nil, nil)) + await self.activeCall?.iceCandidates.append(candidate.toCandidate(nil, nil)) } } @@ -592,11 +847,42 @@ extension WebRTCClient: RTCPeerConnectionDelegate { } extension WebRTCClient { - func setAudioEnabled(_ enabled: Bool) { - setTrackEnabled(RTCAudioTrack.self, enabled) + static func isAuthorized(for type: AVMediaType) async -> Bool { + let status = AVCaptureDevice.authorizationStatus(for: type) + var isAuthorized = status == .authorized + if status == .notDetermined { + isAuthorized = await AVCaptureDevice.requestAccess(for: type) + } + return isAuthorized } - func setSpeakerEnabledAndConfigureSession( _ enabled: Bool) { + static func showUnauthorizedAlert(for type: AVMediaType) { + if type == .audio { + AlertManager.shared.showAlert(Alert( + title: Text("No permission to record speech"), + message: Text("To record speech please grant permission to use Microphone."), + primaryButton: .default(Text("Open Settings")) { + DispatchQueue.main.async { + UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil) + } + }, + secondaryButton: .cancel() + )) + } else if type == .video { + AlertManager.shared.showAlert(Alert( + title: Text("No permission to record video"), + message: Text("To record video please grant permission to use Camera."), + primaryButton: .default(Text("Open Settings")) { + DispatchQueue.main.async { + UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil) + } + }, + secondaryButton: .cancel() + )) + } + } + + func setSpeakerEnabledAndConfigureSession( _ enabled: Bool, skipExternalDevice: Bool = false) { logger.debug("WebRTCClient: configuring session with speaker enabled \(enabled)") audioQueue.async { [weak self] in guard let self = self else { return } @@ -609,7 +895,7 @@ extension WebRTCClient { if enabled { try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.defaultToSpeaker, .allowBluetooth, .allowAirPlay, .allowBluetoothA2DP]) try self.rtcAudioSession.setMode(AVAudioSession.Mode.videoChat.rawValue) - if hasExternalAudioDevice, let preferred = self.rtcAudioSession.session.preferredInputDevice() { + if hasExternalAudioDevice && !skipExternalDevice, let preferred = self.rtcAudioSession.session.preferredInputDevice() { try self.rtcAudioSession.setPreferredInput(preferred) } else { try self.rtcAudioSession.overrideOutputAudioPort(.speaker) @@ -619,7 +905,7 @@ extension WebRTCClient { try self.rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue) try self.rtcAudioSession.overrideOutputAudioPort(.none) } - if hasExternalAudioDevice { + if hasExternalAudioDevice && !skipExternalDevice { logger.debug("WebRTCClient: configuring session with external device available, skip configuring speaker") } try self.rtcAudioSession.setActive(true) @@ -650,25 +936,59 @@ extension WebRTCClient { } } - func setVideoEnabled(_ enabled: Bool) { - setTrackEnabled(RTCVideoTrack.self, enabled) + @MainActor + func setAudioEnabled(_ enabled: Bool) { + if activeCall != nil { + activeCall?.localAudioTrack = enabled ? createAudioTrack() : nil + activeCall?.connection.transceivers.first(where: { t in mediaSourceFromTransceiverMid(t.mid) == .mic })?.sender.track = activeCall?.localAudioTrack + } else if notConnectedCall != nil { + notConnectedCall?.audioTrack = enabled ? createAudioTrack() : nil + } + ChatModel.shared.activeCall?.localMediaSources.mic = enabled + } + + @MainActor + func setCameraEnabled(_ enabled: Bool) { + if let call = activeCall { + if enabled { + if call.localVideoTrack == nil { + let device = activeCall?.device ?? notConnectedCall?.device ?? .front + let (camera, track) = createVideoTrackAndStartCapture(device) + activeCall?.localCamera = camera + activeCall?.localVideoTrack = track + } + } else { + (call.localCamera as? RTCCameraVideoCapturer)?.stopCapture() + activeCall?.localCamera = nil + activeCall?.localVideoTrack = nil + } + call.connection.transceivers + .first(where: { t in mediaSourceFromTransceiverMid(t.mid) == .camera })? + .sender.track = activeCall?.localVideoTrack + ChatModel.shared.activeCall?.localMediaSources.camera = activeCall?.localVideoTrack != nil + } else if let call = notConnectedCall { + if enabled { + let device = activeCall?.device ?? notConnectedCall?.device ?? .front + notConnectedCall?.localCameraAndTrack = createVideoTrackAndStartCapture(device) + } else { + (call.localCameraAndTrack?.0 as? RTCCameraVideoCapturer)?.stopCapture() + notConnectedCall?.localCameraAndTrack = nil + } + ChatModel.shared.activeCall?.localMediaSources.camera = notConnectedCall?.localCameraAndTrack != nil + } } func flipCamera() { - switch activeCall.wrappedValue?.device { - case .front: activeCall.wrappedValue?.device = .back - case .back: activeCall.wrappedValue?.device = .front - default: () + let device = activeCall?.device ?? notConnectedCall?.device + if activeCall != nil { + activeCall?.device = device == .front ? .back : .front + } else { + notConnectedCall?.device = device == .front ? .back : .front } - if let call = activeCall.wrappedValue { - startCaptureLocalVideo(call) - } - } - - private func setTrackEnabled(_ type: T.Type, _ enabled: Bool) { - activeCall.wrappedValue?.connection.transceivers - .compactMap { $0.sender.track as? T } - .forEach { $0.isEnabled = enabled } + startCaptureLocalVideo( + activeCall?.device ?? notConnectedCall?.device, + (activeCall?.localCamera ?? notConnectedCall?.localCameraAndTrack?.0) as? RTCCameraVideoCapturer + ) } } diff --git a/apps/ios/Shared/Views/Chat/ChatInfoToolbar.swift b/apps/ios/Shared/Views/Chat/ChatInfoToolbar.swift index 8c9112a858..62a41c504a 100644 --- a/apps/ios/Shared/Views/Chat/ChatInfoToolbar.swift +++ b/apps/ios/Shared/Views/Chat/ChatInfoToolbar.swift @@ -45,7 +45,7 @@ struct ChatInfoToolbar: View { } private var contactVerifiedShield: Text { - (Text(Image(systemName: "checkmark.shield")) + Text(" ")) + (Text(Image(systemName: "checkmark.shield")) + textSpace) .font(.caption) .foregroundColor(theme.colors.secondary) .baselineOffset(1) diff --git a/apps/ios/Shared/Views/Chat/ChatInfoView.swift b/apps/ios/Shared/Views/Chat/ChatInfoView.swift index ff46b9619c..9b6b9b73e8 100644 --- a/apps/ios/Shared/Views/Chat/ChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatInfoView.swift @@ -96,6 +96,8 @@ struct ChatInfoView: View { @ObservedObject var chat: Chat @State var contact: Contact @State var localAlias: String + @State var featuresAllowed: ContactFeaturesAllowed + @State var currentFeaturesAllowed: ContactFeaturesAllowed var onSearch: () -> Void @State private var connectionStats: ConnectionStats? = nil @State private var customUserProfile: Profile? = nil @@ -154,8 +156,8 @@ struct ChatInfoView: View { HStack(alignment: .center, spacing: 8) { let buttonWidth = g.size.width / 4 searchButton(width: buttonWidth) - AudioCallButton(chat: chat, contact: contact, width: buttonWidth) { alert = .someAlert(alert: $0) } - VideoButton(chat: chat, contact: contact, width: buttonWidth) { alert = .someAlert(alert: $0) } + AudioCallButton(chat: chat, contact: contact, connectionStats: $connectionStats, width: buttonWidth) { alert = .someAlert(alert: $0) } + VideoButton(chat: chat, contact: contact, connectionStats: $connectionStats, width: buttonWidth) { alert = .someAlert(alert: $0) } muteButton(width: buttonWidth) } } @@ -312,7 +314,15 @@ struct ChatInfoView: View { case .networkStatusAlert: return networkStatusAlert() case .switchAddressAlert: return switchAddressAlert(switchContactAddress) case .abortSwitchAddressAlert: return abortSwitchAddressAlert(abortSwitchContactAddress) - case .syncConnectionForceAlert: return syncConnectionForceAlert({ syncContactConnection(force: true) }) + case .syncConnectionForceAlert: + return syncConnectionForceAlert({ + Task { + if let stats = await syncContactConnection(contact, force: true, showAlert: { alert = .someAlert(alert: $0) }) { + connectionStats = stats + dismiss() + } + } + }) case let .queueInfo(info): return queueInfoAlert(info) case let .someAlert(a): return a.alert case let .error(title, error): return mkAlert(title: title, message: error) @@ -327,6 +337,16 @@ struct ChatInfoView: View { $0.content } } + .onDisappear { + if currentFeaturesAllowed != featuresAllowed { + showAlert( + title: NSLocalizedString("Save preferences?", comment: "alert title"), + buttonTitle: NSLocalizedString("Save and notify contact", comment: "alert button"), + buttonAction: { savePreferences() }, + cancelButton: true + ) + } + } } private func contactInfoHeader() -> some View { @@ -339,7 +359,7 @@ struct ChatInfoView: View { Text(Image(systemName: "checkmark.shield")) .foregroundColor(theme.colors.secondary) .font(.title2) - + Text(" ") + + textSpace + Text(contact.profile.displayName) .font(.largeTitle) ) @@ -447,8 +467,9 @@ struct ChatInfoView: View { NavigationLink { ContactPreferencesView( contact: $contact, - featuresAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences), - currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences) + featuresAllowed: $featuresAllowed, + currentFeaturesAllowed: $currentFeaturesAllowed, + savePreferences: savePreferences ) .navigationBarTitle("Contact preferences") .modifier(ThemedBackground(grouped: true)) @@ -480,7 +501,12 @@ struct ChatInfoView: View { private func synchronizeConnectionButton() -> some View { Button { - syncContactConnection(force: false) + Task { + if let stats = await syncContactConnection(contact, force: false, showAlert: { alert = .someAlert(alert: $0) }) { + connectionStats = stats + dismiss() + } + } } label: { Label("Fix connection", systemImage: "exclamationmark.arrow.triangle.2.circlepath") .foregroundColor(.orange) @@ -599,29 +625,50 @@ struct ChatInfoView: View { } } - private func syncContactConnection(force: Bool) { + private func savePreferences() { Task { do { - let stats = try apiSyncContactRatchet(contact.apiId, force) - connectionStats = stats - await MainActor.run { - chatModel.updateContactConnectionStats(contact, stats) - dismiss() - } - } catch let error { - logger.error("syncContactConnection apiSyncContactRatchet error: \(responseError(error))") - let a = getErrorAlert(error, "Error synchronizing connection") - await MainActor.run { - alert = .error(title: a.title, error: a.message) + let prefs = contactFeaturesAllowedToPrefs(featuresAllowed) + if let toContact = try await apiSetContactPrefs(contactId: contact.contactId, preferences: prefs) { + await MainActor.run { + contact = toContact + chatModel.updateContact(toContact) + currentFeaturesAllowed = featuresAllowed + } } + } catch { + logger.error("ContactPreferencesView apiSetContactPrefs error: \(responseError(error))") } } } } +func syncContactConnection(_ contact: Contact, force: Bool, showAlert: (SomeAlert) -> Void) async -> ConnectionStats? { + do { + let stats = try apiSyncContactRatchet(contact.apiId, force) + await MainActor.run { + ChatModel.shared.updateContactConnectionStats(contact, stats) + } + return stats + } catch let error { + logger.error("syncContactConnection apiSyncContactRatchet error: \(responseError(error))") + let a = getErrorAlert(error, "Error synchronizing connection") + await MainActor.run { + showAlert( + SomeAlert( + alert: mkAlert(title: a.title, message: a.message), + id: "syncContactConnection error" + ) + ) + } + return nil + } +} + struct AudioCallButton: View { var chat: Chat var contact: Contact + @Binding var connectionStats: ConnectionStats? var width: CGFloat var showAlert: (SomeAlert) -> Void @@ -629,6 +676,7 @@ struct AudioCallButton: View { CallButton( chat: chat, contact: contact, + connectionStats: $connectionStats, image: "phone.fill", title: "call", mediaType: .audio, @@ -641,6 +689,7 @@ struct AudioCallButton: View { struct VideoButton: View { var chat: Chat var contact: Contact + @Binding var connectionStats: ConnectionStats? var width: CGFloat var showAlert: (SomeAlert) -> Void @@ -648,6 +697,7 @@ struct VideoButton: View { CallButton( chat: chat, contact: contact, + connectionStats: $connectionStats, image: "video.fill", title: "video", mediaType: .video, @@ -660,6 +710,7 @@ struct VideoButton: View { private struct CallButton: View { var chat: Chat var contact: Contact + @Binding var connectionStats: ConnectionStats? var image: String var title: LocalizedStringKey var mediaType: CallMediaType @@ -671,7 +722,42 @@ private struct CallButton: View { InfoViewButton(image: image, title: title, disabledLook: !canCall, width: width) { if canCall { - CallController.shared.startCall(contact, mediaType) + if let connStats = connectionStats { + if connStats.ratchetSyncState == .ok { + if CallController.useCallKit() { + CallController.shared.startCall(contact, mediaType) + } else { + // When CallKit is not used, colorscheme will be changed and it will be visible if not hiding sheets first + dismissAllSheets(animated: true) { + CallController.shared.startCall(contact, mediaType) + } + } + } else if connStats.ratchetSyncAllowed { + showAlert(SomeAlert( + alert: Alert( + title: Text("Fix connection?"), + message: Text("Connection requires encryption renegotiation."), + primaryButton: .default(Text("Fix")) { + Task { + if let stats = await syncContactConnection(contact, force: false, showAlert: showAlert) { + connectionStats = stats + } + } + }, + secondaryButton: .cancel() + ), + id: "can't call contact, fix connection" + )) + } else { + showAlert(SomeAlert( + alert: mkAlert( + title: "Can't call contact", + message: "Encryption renegotiation in progress." + ), + id: "can't call contact, encryption renegotiation in progress" + )) + } + } } else if contact.nextSendGrpInv { showAlert(SomeAlert( alert: mkAlert( @@ -935,7 +1021,7 @@ func syncConnectionForceAlert(_ syncConnectionForce: @escaping () -> Void) -> Al ) } -func queueInfoText(_ info: (RcvMsgInfo?, QueueInfo)) -> String { +func queueInfoText(_ info: (RcvMsgInfo?, ServerQueueInfo)) -> String { let (rcvMsgInfo, qInfo) = info var msgInfo: String if let rcvMsgInfo { msgInfo = encodeJSON(rcvMsgInfo) } else { msgInfo = "none" } @@ -1166,6 +1252,8 @@ struct ChatInfoView_Previews: PreviewProvider { chat: Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []), contact: Contact.sampleData, localAlias: "", + featuresAllowed: contactUserPrefsToFeaturesAllowed(Contact.sampleData.mergedPreferences), + currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(Contact.sampleData.mergedPreferences), onSearch: {} ) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIChatFeatureView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIChatFeatureView.swift index 27d8d9c2de..02be8af73b 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIChatFeatureView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIChatFeatureView.swift @@ -11,11 +11,11 @@ import SimpleXChat struct CIChatFeatureView: View { @EnvironmentObject var m: ChatModel + @Environment(\.revealed) var revealed: Bool @ObservedObject var im = ItemsModel.shared @ObservedObject var chat: Chat @EnvironmentObject var theme: AppTheme var chatItem: ChatItem - @Binding var revealed: Bool var feature: Feature var icon: String? = nil var iconColor: Color @@ -106,6 +106,9 @@ struct CIChatFeatureView: View { struct CIChatFeatureView_Previews: PreviewProvider { static var previews: some View { let enabled = FeatureEnabled(forUser: false, forContact: false) - CIChatFeatureView(chat: Chat.sampleData, chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), revealed: Binding.constant(true), feature: ChatFeature.fullDelete, iconColor: enabled.iconColor(.secondary)) + CIChatFeatureView( + chat: Chat.sampleData, + chatItem: ChatItem.getChatFeatureSample(.fullDelete, enabled), feature: ChatFeature.fullDelete, iconColor: enabled.iconColor(.secondary) + ).environment(\.revealed, true) } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIFeaturePreferenceView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIFeaturePreferenceView.swift index 752f599c8d..2c9c261536 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIFeaturePreferenceView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIFeaturePreferenceView.swift @@ -47,7 +47,7 @@ struct CIFeaturePreferenceView: View { + Text(acceptText) .fontWeight(.medium) .foregroundColor(theme.colors.primary) - + Text(" ") + + Text(verbatim: " ") } r = r + chatItem.timestampText .fontWeight(.light) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift index fcb330c321..f5ab7f3a4b 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIFileView.swift @@ -285,17 +285,18 @@ struct CIFileView_Previews: PreviewProvider { file: nil ) Group { - ChatItemView(chat: Chat.sampleData, chatItem: sentFile, revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile, revealed: Binding.constant(false)) + ChatItemView(chat: Chat.sampleData, chatItem: sentFile) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample()) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileName: "some_long_file_name_here", fileStatus: .rcvInvitation)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvAccepted)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10))) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileStatus: .rcvCancelled)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(fileSize: 1_000_000_000, fileStatus: .rcvInvitation)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Hello there", fileStatus: .rcvInvitation)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getFileMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", fileStatus: .rcvInvitation)) + ChatItemView(chat: Chat.sampleData, chatItem: fileChatItemWtFile) } + .environment(\.revealed, false) .previewLayout(.fixed(width: 360, height: 360)) } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIGroupInvitationView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIGroupInvitationView.swift index ef0fec5dfe..107208a033 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIGroupInvitationView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIGroupInvitationView.swift @@ -12,6 +12,7 @@ import SimpleXChat struct CIGroupInvitationView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme + @Environment(\.showTimestamp) var showTimestamp: Bool @ObservedObject var chat: Chat var chatItem: ChatItem var groupInvitation: CIGroupInvitation @@ -44,16 +45,16 @@ struct CIGroupInvitationView: View { Text(chatIncognito ? "Tap to join incognito" : "Tap to join") .foregroundColor(inProgress ? theme.colors.secondary : chatIncognito ? .indigo : theme.colors.primary) .font(.callout) - + Text(" ") - + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy) + + Text(verbatim: " ") + + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) ) .overlay(DetermineWidth()) } } else { ( groupInvitationText() - + Text(" ") - + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy) + + Text(verbatim: " ") + + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showStatus: false, showEdited: false, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) ) .overlay(DetermineWidth()) } @@ -69,7 +70,7 @@ struct CIGroupInvitationView: View { } .padding(.horizontal, 12) .padding(.vertical, 6) - .background(chatItemFrameColor(chatItem, theme)) + .background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) } .textSelection(.disabled) .onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 } .onChange(of: inProgress) { inProgress in diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift index 3966d7e258..b06c6df48c 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIImageView.swift @@ -165,9 +165,9 @@ struct CIImageView: View { private func fileIcon(_ icon: String, _ size: CGFloat, _ padding: CGFloat) -> some View { Image(systemName: icon) .resizable() + .invertedForegroundStyle() .aspectRatio(contentMode: .fit) .frame(width: size, height: size) - .foregroundColor(.white) .padding(padding) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CILinkView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CILinkView.swift index 3c864ab172..692e6bb8a6 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CILinkView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CILinkView.swift @@ -16,7 +16,7 @@ struct CILinkView: View { var body: some View { VStack(alignment: .center, spacing: 6) { - if let uiImage = UIImage(base64Encoded: linkPreview.image) { + if let uiImage = imageFromBase64(linkPreview.image) { Image(uiImage: uiImage) .resizable() .scaledToFit() diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIMemberCreatedContactView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIMemberCreatedContactView.swift index 463695ddb7..d24c737907 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIMemberCreatedContactView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIMemberCreatedContactView.swift @@ -23,7 +23,7 @@ struct CIMemberCreatedContactView: View { .onTapGesture { dismissAllSheets(animated: true) DispatchQueue.main.async { - m.chatId = "@\(contactId)" + ItemsModel.shared.loadOpenChat("@\(contactId)") } } } else { @@ -45,7 +45,7 @@ struct CIMemberCreatedContactView: View { + Text(openText) .fontWeight(.medium) .foregroundColor(theme.colors.primary) - + Text(" ") + + Text(verbatim: " ") } r = r + chatItem.timestampText .fontWeight(.light) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift index 66b810cf2f..e58ad0f74e 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIMetaView.swift @@ -12,11 +12,13 @@ import SimpleXChat struct CIMetaView: View { @ObservedObject var chat: Chat @EnvironmentObject var theme: AppTheme + @Environment(\.showTimestamp) var showTimestamp: Bool var chatItem: ChatItem var metaColor: Color var paleMetaColor = Color(UIColor.tertiaryLabel) var showStatus = true var showEdited = true + var invertedMaterial = false @AppStorage(DEFAULT_SHOW_SENT_VIA_RPOXY) private var showSentViaProxy = false @@ -24,93 +26,143 @@ struct CIMetaView: View { if chatItem.isDeletedContent { chatItem.timestampText.font(.caption).foregroundColor(metaColor) } else { - let meta = chatItem.meta - let ttl = chat.chatInfo.timedMessagesTTL - let encrypted = chatItem.encryptedFile - switch meta.itemStatus { - case let .sndSent(sndProgress): - switch sndProgress { - case .complete: ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .sent, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) - case .partial: ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .sent, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) + ZStack { + ciMetaText( + chatItem.meta, + chatTTL: chat.chatInfo.timedMessagesTTL, + encrypted: chatItem.encryptedFile, + color: metaColor, + paleColor: paleMetaColor, + colorMode: invertedMaterial + ? .invertedMaterial + : .normal, + showStatus: showStatus, + showEdited: showEdited, + showViaProxy: showSentViaProxy, + showTimesamp: showTimestamp + ).invertedForegroundStyle(enabled: invertedMaterial) + if invertedMaterial { + ciMetaText( + chatItem.meta, + chatTTL: chat.chatInfo.timedMessagesTTL, + encrypted: chatItem.encryptedFile, + colorMode: .normal, + onlyOverrides: true, + showStatus: showStatus, + showEdited: showEdited, + showViaProxy: showSentViaProxy, + showTimesamp: showTimestamp + ) } - case let .sndRcvd(_, sndProgress): - switch sndProgress { - case .complete: - ZStack { - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .rcvd1, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, sent: .rcvd2, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) - } - case .partial: - ZStack { - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .rcvd1, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: paleMetaColor, sent: .rcvd2, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) - } - } - default: - ciMetaText(meta, chatTTL: ttl, encrypted: encrypted, color: metaColor, showStatus: showStatus, showEdited: showEdited, showViaProxy: showSentViaProxy) } } } } -enum SentCheckmark { - case sent - case rcvd1 - case rcvd2 +enum MetaColorMode { + // Renders provided colours + case normal + // Fully transparent meta - used for reserving space + case transparent + // Renders white on dark backgrounds and black on light ones + case invertedMaterial + + func resolve(_ c: Color?) -> Color? { + switch self { + case .normal: c + case .transparent: .clear + case .invertedMaterial: nil + } + } + + func statusSpacer(_ sent: Bool) -> Text { + switch self { + case .normal, .transparent: + Text( + sent + ? Image("checkmark.wide") + : Image(systemName: "circlebadge.fill") + ).foregroundColor(.clear) + case .invertedMaterial: textSpace.kerning(13) + } + } } func ciMetaText( _ meta: CIMeta, chatTTL: Int?, encrypted: Bool?, - color: Color = .clear, + color: Color = .clear, // we use this function to reserve space without rendering meta + paleColor: Color? = nil, primaryColor: Color = .accentColor, - transparent: Bool = false, - sent: SentCheckmark? = nil, + colorMode: MetaColorMode = .normal, + onlyOverrides: Bool = false, // only render colors that differ from base showStatus: Bool = true, showEdited: Bool = true, - showViaProxy: Bool + showViaProxy: Bool, + showTimesamp: Bool ) -> Text { var r = Text("") + var space: Text? = nil + let appendSpace = { + if let sp = space { + r = r + sp + space = nil + } + } + let resolved = colorMode.resolve(color) if showEdited, meta.itemEdited { - r = r + statusIconText("pencil", color) + r = r + statusIconText("pencil", resolved) } if meta.disappearing { - r = r + statusIconText("timer", color).font(.caption2) + r = r + statusIconText("timer", resolved).font(.caption2) let ttl = meta.itemTimed?.ttl if ttl != chatTTL { - r = r + Text(shortTimeText(ttl)).foregroundColor(color) + r = r + colored(Text(shortTimeText(ttl)), resolved) } - r = r + Text(" ") + space = textSpace } if showViaProxy, meta.sentViaProxy == true { - r = r + statusIconText("arrow.forward", color.opacity(0.67)).font(.caption2) + appendSpace() + r = r + statusIconText("arrow.forward", resolved?.opacity(0.67)).font(.caption2) } if showStatus { - if let (icon, statusColor) = meta.statusIcon(color, primaryColor) { - let t = Text(Image(systemName: icon)).font(.caption2) - let gap = Text(" ").kerning(-1.25) - let t1 = t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) - switch sent { - case nil: r = r + t1 - case .sent: r = r + t1 + gap - case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + gap - case .rcvd2: r = r + gap + t1 + appendSpace() + if let (image, statusColor) = meta.itemStatus.statusIcon(color, paleColor ?? color, primaryColor) { + let metaColor = if onlyOverrides && statusColor == color { + Color.clear + } else { + colorMode.resolve(statusColor) } - r = r + Text(" ") + r = r + colored(Text(image), metaColor) } else if !meta.disappearing { - r = r + statusIconText("circlebadge.fill", .clear) + Text(" ") + r = r + colorMode.statusSpacer(meta.itemStatus.sent) } + space = textSpace } if let enc = encrypted { - r = r + statusIconText(enc ? "lock" : "lock.open", color) + Text(" ") + appendSpace() + r = r + statusIconText(enc ? "lock" : "lock.open", resolved) + space = textSpace + } + if showTimesamp { + appendSpace() + r = r + colored(meta.timestampText, resolved) } - r = r + meta.timestampText.foregroundColor(color) return r.font(.caption) } -private func statusIconText(_ icon: String, _ color: Color) -> Text { - Text(Image(systemName: icon)).foregroundColor(color) +private func statusIconText(_ icon: String, _ color: Color?) -> Text { + colored(Text(Image(systemName: icon)), color) +} + +// Applying `foregroundColor(nil)` breaks `.invertedForegroundStyle` modifier +private func colored(_ t: Text, _ color: Color?) -> Text { + if let color { + t.foregroundColor(color) + } else { + t + } } struct CIMetaView_Previews: PreviewProvider { diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIRcvDecryptionError.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIRcvDecryptionError.swift index 1f2e16448d..4603a026cd 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIRcvDecryptionError.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIRcvDecryptionError.swift @@ -15,6 +15,7 @@ struct CIRcvDecryptionError: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme @ObservedObject var chat: Chat + @Environment(\.showTimestamp) var showTimestamp: Bool var msgDecryptError: MsgDecryptError var msgCount: UInt32 var chatItem: ChatItem @@ -47,7 +48,7 @@ struct CIRcvDecryptionError: View { if case let .group(groupInfo) = chat.chatInfo, case let .groupRcv(groupMember) = chatItem.chatDir { do { - let (member, stats) = try apiGroupMemberInfo(groupInfo.apiId, groupMember.groupMemberId) + let (member, stats) = try apiGroupMemberInfoSync(groupInfo.apiId, groupMember.groupMemberId) if let s = stats { m.updateGroupMemberConnectionStats(groupInfo, member, s) } @@ -68,37 +69,40 @@ struct CIRcvDecryptionError: View { } @ViewBuilder private func viewBody() -> some View { - if case let .direct(contact) = chat.chatInfo, - let contactStats = contact.activeConn?.connectionStats { - if contactStats.ratchetSyncAllowed { - decryptionErrorItemFixButton(syncSupported: true) { - alert = .syncAllowedAlert { syncContactConnection(contact) } + Group { + if case let .direct(contact) = chat.chatInfo, + let contactStats = contact.activeConn?.connectionStats { + if contactStats.ratchetSyncAllowed { + decryptionErrorItemFixButton(syncSupported: true) { + alert = .syncAllowedAlert { syncContactConnection(contact) } + } + } else if !contactStats.ratchetSyncSupported { + decryptionErrorItemFixButton(syncSupported: false) { + alert = .syncNotSupportedContactAlert + } + } else { + basicDecryptionErrorItem() } - } else if !contactStats.ratchetSyncSupported { - decryptionErrorItemFixButton(syncSupported: false) { - alert = .syncNotSupportedContactAlert + } else if case let .group(groupInfo) = chat.chatInfo, + case let .groupRcv(groupMember) = chatItem.chatDir, + let mem = m.getGroupMember(groupMember.groupMemberId), + let memberStats = mem.wrapped.activeConn?.connectionStats { + if memberStats.ratchetSyncAllowed { + decryptionErrorItemFixButton(syncSupported: true) { + alert = .syncAllowedAlert { syncMemberConnection(groupInfo, groupMember) } + } + } else if !memberStats.ratchetSyncSupported { + decryptionErrorItemFixButton(syncSupported: false) { + alert = .syncNotSupportedMemberAlert + } + } else { + basicDecryptionErrorItem() } } else { basicDecryptionErrorItem() } - } else if case let .group(groupInfo) = chat.chatInfo, - case let .groupRcv(groupMember) = chatItem.chatDir, - let mem = m.getGroupMember(groupMember.groupMemberId), - let memberStats = mem.wrapped.activeConn?.connectionStats { - if memberStats.ratchetSyncAllowed { - decryptionErrorItemFixButton(syncSupported: true) { - alert = .syncAllowedAlert { syncMemberConnection(groupInfo, groupMember) } - } - } else if !memberStats.ratchetSyncSupported { - decryptionErrorItemFixButton(syncSupported: false) { - alert = .syncNotSupportedMemberAlert - } - } else { - basicDecryptionErrorItem() - } - } else { - basicDecryptionErrorItem() } + .background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) } } private func basicDecryptionErrorItem() -> some View { @@ -117,12 +121,12 @@ struct CIRcvDecryptionError: View { Text(Image(systemName: "exclamationmark.arrow.triangle.2.circlepath")) .foregroundColor(syncSupported ? theme.colors.primary : theme.colors.secondary) .font(.callout) - + Text(" ") + + textSpace + Text("Fix connection") .foregroundColor(syncSupported ? theme.colors.primary : theme.colors.secondary) .font(.callout) - + Text(" ") - + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy) + + Text(verbatim: " ") + + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) ) } .padding(.horizontal, 12) @@ -131,7 +135,6 @@ struct CIRcvDecryptionError: View { } .onTapGesture(perform: { onClick() }) .padding(.vertical, 6) - .background(Color(uiColor: .tertiarySystemGroupedBackground)) .textSelection(.disabled) } @@ -141,8 +144,8 @@ struct CIRcvDecryptionError: View { Text(chatItem.content.text) .foregroundColor(.red) .italic() - + Text(" ") - + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy) + + Text(verbatim: " ") + + ciMetaText(chatItem.meta, chatTTL: nil, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) } .padding(.horizontal, 12) CIMetaView(chat: chat, chatItem: chatItem, metaColor: theme.colors.secondary) @@ -150,7 +153,6 @@ struct CIRcvDecryptionError: View { } .onTapGesture(perform: { onClick() }) .padding(.vertical, 6) - .background(Color(uiColor: .tertiarySystemGroupedBackground)) .textSelection(.disabled) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift index 4670fc685f..851b90bc3d 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVideoView.swift @@ -292,30 +292,22 @@ struct CIVideoView: View { .clipShape(Circle()) } - private func durationProgress() -> some View { - HStack { - Text("\(durationText(videoPlaying ? progress : duration))") - .foregroundColor(.white) - .font(.caption) - .padding(.vertical, 3) - .padding(.horizontal, 6) - .background(Color.black.opacity(0.35)) - .cornerRadius(10) - .padding([.top, .leading], 6) - - if let file = chatItem.file, !videoPlaying { - Text("\(ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary))") - .foregroundColor(.white) - .font(.caption) - .padding(.vertical, 3) - .padding(.horizontal, 6) - .background(Color.black.opacity(0.35)) - .cornerRadius(10) - .padding(.top, 6) - } + private var fileSizeString: String { + if let file = chatItem.file, !videoPlaying { + " " + ByteCountFormatter.string(fromByteCount: file.fileSize, countStyle: .binary) + } else { + "" } } + private func durationProgress() -> some View { + Text((durationText(videoPlaying ? progress : duration)) + fileSizeString) + .invertedForegroundStyle() + .font(.caption) + .padding(.vertical, 6) + .padding(.horizontal, 12) + } + private func imageView(_ img: UIImage) -> some View { let w = img.size.width <= img.size.height ? maxWidth * 0.75 : maxWidth return ZStack(alignment: .topTrailing) { @@ -411,9 +403,9 @@ struct CIVideoView: View { private func fileIcon(_ icon: String, _ size: CGFloat, _ padding: CGFloat) -> some View { Image(systemName: icon) .resizable() + .invertedForegroundStyle() .aspectRatio(contentMode: .fit) .frame(width: size, height: size) - .foregroundColor(.white) .padding(smallView ? 0 : padding) } @@ -428,10 +420,8 @@ struct CIVideoView: View { private func progressCircle(_ progress: Int64, _ total: Int64) -> some View { Circle() .trim(from: 0, to: Double(progress) / Double(total)) - .stroke( - Color(uiColor: .white), - style: StrokeStyle(lineWidth: 2) - ) + .stroke(style: StrokeStyle(lineWidth: 2)) + .invertedForegroundStyle() .rotationEffect(.degrees(-90)) .frame(width: 16, height: 16) .padding([.trailing, .top], smallView ? 0 : 11) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift index 45a20f03bd..acecaaae4f 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/CIVoiceView.swift @@ -510,10 +510,10 @@ struct CIVoiceView_Previews: PreviewProvider { duration: 30, allowMenu: Binding.constant(true) ) - ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, revealed: Binding.constant(false), allowMenu: .constant(true)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), revealed: Binding.constant(false), allowMenu: .constant(true)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false), allowMenu: .constant(true)) - ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, revealed: Binding.constant(false), allowMenu: .constant(true)) + ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, allowMenu: .constant(true)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(), allowMenu: .constant(true)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), allowMenu: .constant(true)) + ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWtFile, allowMenu: .constant(true)) } .previewLayout(.fixed(width: 360, height: 360)) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FramedCIVoiceView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FramedCIVoiceView.swift index 64a7f29a25..47a2cbb6cb 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FramedCIVoiceView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FramedCIVoiceView.swift @@ -92,12 +92,13 @@ struct FramedCIVoiceView_Previews: PreviewProvider { file: CIFile.getSample(fileStatus: .sndComplete) ) Group { - ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage, revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10)), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote, revealed: Binding.constant(false)) + ChatItemView(chat: Chat.sampleData, chatItem: sentVoiceMessage) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Hello there", fileStatus: .rcvTransfer(rcvProgress: 7, rcvTotal: 10))) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getVoiceMsgContentSample(text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")) + ChatItemView(chat: Chat.sampleData, chatItem: voiceMessageWithQuote) } + .environment(\.revealed, false) .previewLayout(.fixed(width: 360, height: 360)) } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift index 258e2e34dc..9b71e6c4a4 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift @@ -12,11 +12,10 @@ import SimpleXChat struct FramedItemView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme - @EnvironmentObject var scrollModel: ReverseListScrollModel + @EnvironmentObject var scrollModel: ReverseListScrollModel @ObservedObject var chat: Chat var chatItem: ChatItem var preview: UIImage? - @Binding var revealed: Bool var maxWidth: CGFloat = .infinity @State var msgWidth: CGFloat = 0 var imgWidth: CGFloat? = nil @@ -59,20 +58,25 @@ struct FramedItemView: View { framedItemHeader(icon: "arrowshape.turn.up.forward", caption: Text(itemForwarded.text(chat.chatInfo.chatType)).italic(), pad: true) } - ChatItemContentView(chat: chat, chatItem: chatItem, revealed: $revealed, msgContentView: framedMsgContentView) + ChatItemContentView(chat: chat, chatItem: chatItem, msgContentView: framedMsgContentView) .padding(chatItem.content.msgContent != nil ? 0 : 4) .overlay(DetermineWidth()) } - if chatItem.content.msgContent != nil { - CIMetaView(chat: chat, chatItem: chatItem, metaColor: useWhiteMetaColor ? Color.white : theme.colors.secondary) - .padding(.horizontal, 12) - .padding(.bottom, 6) - .overlay(DetermineWidth()) - .accessibilityLabel("") + if let content = chatItem.content.msgContent { + CIMetaView( + chat: chat, + chatItem: chatItem, + metaColor: theme.colors.secondary, + invertedMaterial: useWhiteMetaColor + ) + .padding(.horizontal, 12) + .padding(.bottom, 6) + .overlay(DetermineWidth()) + .accessibilityLabel("") } - } - .background(chatItemFrameColorMaybeImageOrVideo(chatItem, theme)) + } + .background { chatItemFrameColorMaybeImageOrVideo(chatItem, theme).modifier(ChatTailPadding()) } .onPreferenceChange(DetermineWidth.Key.self) { msgWidth = $0 } if let (title, text) = chatItem.meta.itemStatus.statusInfo { @@ -185,7 +189,7 @@ struct FramedItemView: View { let v = ZStack(alignment: .topTrailing) { switch (qi.content) { case let .image(_, image): - if let uiImage = UIImage(base64Encoded: image) { + if let uiImage = imageFromBase64(image) { ciQuotedMsgView(qi) .padding(.trailing, 70).frame(minWidth: msgWidth, alignment: .leading) Image(uiImage: uiImage) @@ -197,7 +201,7 @@ struct FramedItemView: View { ciQuotedMsgView(qi) } case let .video(_, image, _): - if let uiImage = UIImage(base64Encoded: image) { + if let uiImage = imageFromBase64(image) { ciQuotedMsgView(qi) .padding(.trailing, 70).frame(minWidth: msgWidth, alignment: .leading) Image(uiImage: uiImage) @@ -294,7 +298,6 @@ struct FramedItemView: View { .padding(.horizontal, 12) .overlay(DetermineWidth()) .frame(minWidth: 0, alignment: .leading) - .textSelection(.enabled) if let mediaWidth = maxMediaWidth(), mediaWidth < maxWidth { v.frame(maxWidth: mediaWidth, alignment: .leading) @@ -367,14 +370,14 @@ func chatItemFrameContextColor(_ ci: ChatItem, _ theme: AppTheme) -> Color { struct FramedItemView_Previews: PreviewProvider { static var previews: some View { Group{ - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -"), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line "), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat"), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat"), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -"), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line "), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat"), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat"), allowMenu: Binding.constant(true)) } .previewLayout(.fixed(width: 360, height: 200)) } @@ -383,17 +386,18 @@ struct FramedItemView_Previews: PreviewProvider { struct FramedItemView_Edited_Previews: PreviewProvider { static var previews: some View { Group { - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat", .rcvRead, itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi there hello hello hello ther hello hello", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello there this is a long text", quotedItem: CIQuote.getSample(1, .now, "hi there", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemEdited: true), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi there hello hello hello ther hello hello", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemEdited: true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello there this is a long text", quotedItem: CIQuote.getSample(1, .now, "hi there", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemEdited: true), allowMenu: Binding.constant(true)) } + .environment(\.revealed, false) .previewLayout(.fixed(width: 360, height: 200)) } } @@ -401,17 +405,18 @@ struct FramedItemView_Edited_Previews: PreviewProvider { struct FramedItemView_Deleted_Previews: PreviewProvider { static var previews: some View { Group { - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi there hello hello hello ther hello hello", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) - FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello there this is a long text", quotedItem: CIQuote.getSample(1, .now, "hi there", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "chaT@simplex.chat", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi there hello hello hello ther hello hello", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) + FramedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello there this is a long text", quotedItem: CIQuote.getSample(1, .now, "hi there", chatDir: .directSnd, image: "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAuKADAAQAAAABAAAAYAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAYAC4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAgEBAgMCAgIDBAMDAwMEBgQEBAQEBgcGBgYGBgYHBwcHBwcHBwgICAgICAkJCQkJCwsLCwsLCwsLC//bAEMBAgICAwMDBQMDBQsIBggLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLC//dAAQADP/aAAwDAQACEQMRAD8A/v4ooooAKKKKACiiigAooooAKK+CP2vP+ChXwZ/ZPibw7dMfEHi2VAYdGs3G9N33TO/IiU9hgu3ZSOa/NzXNL/4KJ/td6JJ49+NXiq2+Cvw7kG/ZNKbDMLcjKblmfI/57SRqewrwMdxBRo1HQoRdWqt1HaP+KT0j838j7XKOCMXiqEcbjKkcPh5bSne8/wDr3BXlN+is+5+43jb45/Bf4bs0fj/xZpGjSL1jvL2KF/8AvlmDfpXjH/DfH7GQuPsv/CydD35x/wAfIx+fT9a/AO58D/8ABJj4UzvF4v8AFfif4l6mp/evpkfkWzP3w2Isg+omb61X/wCF0/8ABJr/AI9f+FQeJPL6ed9vbzPrj7ZivnavFuIT+KhHyc5Sf3wjY+7w/hlgZQv7PF1P70aUKa+SqTUvwP6afBXx2+CnxIZYvAHi3R9ZkfpHZ3sUz/8AfKsW/SvVq/lItvBf/BJX4rTLF4V8UeJ/hpqTH91JqUfn2yv2y2JcD3MqfUV9OaFon/BRH9krQ4vH3wI8XW3xq+HkY3+XDKb/ABCvJxHuaZMDr5Ergd1ruwvFNVrmq0VOK3lSkp29Y6SS+R5GY+HGGi1DD4qVKo9oYmm6XN5RqK9Nvsro/obor4A/ZC/4KH/Bv9qxV8MLnw54vjU+bo9443SFPvG3k4EoHdcB17rjmvv+vqcHjaGKpKth5qUX1X9aPyZ+b5rlOMy3ESwmOpOFRdH+aezT6NXTCiiiuo84KKKKACiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/Q/v4ooooAKKKKACiiigAr8tf+ChP7cWs/BEWfwD+A8R1P4k+JQkUCQr5rWUc52o+zndNIf9Up4H324wD9x/tDfGjw/wDs9fBnX/i/4jAeHRrZpI4c4M87YWKIe7yFV9gc9q/n6+B3iOb4GfCLxL/wU1+Oypq3jzxndT2nhK2uBwZptyvcBeoQBSq4xthjwPvivluIs0lSthKM+WUk5Sl/JBbtebekfM/R+BOHaeIcszxVL2kISUKdP/n7WlrGL/uxXvT8u6uizc6b8I/+CbmmRePPi9HD8Q/j7rifbktLmTz7bSGm582ZzktITyX++5+5tX5z5L8LPgv+0X/wVH12+8ZfEbxneW/2SRxB9o02eTSosdY4XRlgjYZGV++e5Jr8xvF3i7xN4+8UX/jXxney6jquqTNcXVzMcvJI5ySfQdgBwBgDgV+sP/BPX9jj9oL9oXw9H4tuvG2s+DfAVlM8VsthcyJLdSBsyCBNwREDZ3SEHLcBTgkfmuX4j+0MXHB06LdBXagna/8AenK6u+7el9Ej9+zvA/2Jls81r4uMcY7J1px5lHf93ShaVo9FFJNq8pMyPil/wRs/aj8D6dLq3gq70vxdHECxgtZGtrogf3UmAQn2EmT2r8rPEPh3xB4R1u58M+KrGfTdRsnMdxa3MbRTROOzKwBBr+674VfCnTfhNoI0DTtX1jWFAGZtYvpL2U4934X/AICAK8V/aW/Yf/Z9/areHUvibpkkerWsRhg1KxkMFyqHkBiMrIAeQJFYDJxjJr6bNPD+nOkqmAfLP+WTuvk7XX4/I/PeHvG6tSxDo5zH2lLpUhHll6uN7NelmvPY/iir2T4KftA/GD9njxMvir4Q65caTPkGWFTutrgD+GaE/I4+oyOxB5r2n9tb9jTxj+x18RYvD+pTtqmgaqrS6VqezZ5qpjfHIBwsseRuA4IIYdcD4yr80q0sRgcQ4SvCpB+jT8mvzP6Bw2JwOcYGNany1aFRdVdNdmn22aauno9T9tLO0+D/APwUr02Txd8NI4Ph38ftGT7b5NtIYLXWGh58yJwQVkBGd/8ArEP3i6fMP0R/4J7ftw6/8YZ7z9nb9oGJtN+JPhoPFIJ18p75IPlclegnj/5aKOGHzrxnH8rPhXxT4j8D+JbHxj4QvZdO1TTJkuLW5hba8UqHIIP8x0I4PFfsZ8bPEdx+0N8FvDv/AAUl+CgXSfiJ4EuYLXxZBbDALw4CXO0clMEZznMLlSf3Zr7PJM+nzyxUF+9ir1IrRVILeVtlOO+lrr5n5RxfwbRdKGXVXfDzfLRm9ZUKr+GDlq3RqP3UnfllZfy2/ptorw/9m/43aF+0X8FNA+L+gARpq1uGnhByYLlCUmiP+44IHqMHvXuFfsNGtCrTjVpu8ZJNPyZ/LWKwtXDVp4evG04Nxa7NOzX3hRRRWhzhRRRQBBdf8e0n+6f5Vx1djdf8e0n+6f5Vx1AH/9H+/iiiigAooooAKKKKAPw9/wCCvXiPWviH4q+F/wCyN4XlKT+K9TS6uQvoXFvAT7AvI3/AQe1fnF/wVO+IOnXfxx034AeDj5Xhv4ZaXb6TawKfkE7Ro0rY6bgvlofdT61+h3xNj/4Tv/gtd4Q0W/8Anh8P6THLGp6Ax21xOD/324Nfg3+0T4kufGH7QHjjxRdtukvte1GXJ9PPcKPwAAr8a4pxUpLEz6zq8n/btOK0+cpX9Uf1d4c5bCDy+lbSlh3W/wC38RNq/qoQcV5M8fjiaeRYEOGchR9TxX9svw9+GHijSvgB4I+Gnwr1ceGbGztYY728gijluhbohLLAJVeJZJJCN0jo+0Zwu4gj+JgO8REsf3l+YfUV/bf8DNVm+Mv7KtkNF1CTTZ9Z0d4Ir2D/AFls9zF8sidPmj3hhz1Fel4YyhGtiHpzWjur6e9f9Dw/H9VXQwFvgvUv62hb8Oa3zPoDwfp6aPoiaONXuNaa1Zo3ubp43nLDqrmJEXI/3QfWukmjMsTRBihYEbl6jPcZ7ivxk/4JMf8ABOv9ob9hBvFdr8ZvGOma9Yak22wttLiYGV2kMkl1dzSIkkkzcKisX8tSwDYNfs/X7Bj6NOlXlCjUU4/zJWv8j+ZsNUnOmpThyvtufj/+1Z8Hf2bPi58PviF8Avh/4wl1j4iaBZjXG0m71qfU7i3u4FMqt5VxLL5LzR70Kx7AVfJXAXH8sysGUMOh5r+vzwl+wD+y78KP2wPEX7bGn6xqFv4g8QmWa70+fUFGlrdTRmGS4EGATIY2dRvdlXe+0DPH83Nh+x58bPFev3kljpSaVYPcymGS+kEX7oudp2DL/dx/DX4Z4xZxkmCxGHxdTGRTlG0ueUU7q3S93a7S69Oh/SngTnNSjgcZhMc1CnCSlC70966dr/4U7Lq79T5Kr9MP+CWfxHsNH+P138EPF2JvDfxL0640a9gc/I0vls0Rx6kb4x/v1x3iz9hmHwV4KuPFHiLxlaWkltGzt5sBSAsBkIHL7iT0GFJJ7V8qfAnxLc+D/jd4N8V2bFJdP1vT5wR/szoT+YyK/NeD+Lcvx+Ijisuq88ackpPlklruveSvdX2ufsmavC5zlWKw9CV7xaTs1aSV4tXS1Ukmrdj9/P8Agkfrus/DD4ifFP8AY/8AEkrPJ4Z1F7y1DeiSG3mI9m2wv/wI1+5Ffhd4Ki/4Qf8A4Lb+INM0/wCSHxDpDySqOhL2cMx/8fizX7o1/RnC7ccLPDP/AJdTnBeid1+DP5M8RkqmZUselZ4ijSqv1lG0vvcWwooor6Q+BCiiigCC6/49pP8AdP8AKuOrsbr/AI9pP90/yrjqAP/S/v4ooooAKKKKACiiigD8LfiNIfBP/BbLwpq9/wDJDr2kJHGTwCZLS4gH/j0eK/Bj9oPw7c+Evj3428M3ilZLHXtRiIPoJ3x+Ywa/fL/grnoWsfDPx98K/wBrzw5EzyeGNSS0uSvokguYQfZtsy/8CFfnB/wVP+HNho/7QFp8bvCeJvDnxK0231mznQfI0vlqsoz6kbJD/v1+M8U4WUViYW1hV5/+3akVr/4FG3qz+r/DnMYTeX1b6VcP7L/t/Dzenq4Tcl5I/M2v6yP+CR3j4eLP2XbLRZZN0uku9sRnp5bMB/45sr+Tev3u/wCCJXj7yNW8T/DyZ+C6XUak9pUw36xD865uAcV7LNFTf24tfd736Hd405d9Y4cddLWlOMvk7wf/AKUvuP6Kq/P/APaa+InjJfF8vge3lez06KONgIyVM+8ZJYjkgHIx045r9AK/Gr/gsB8UPHXwg8N+AvFfgV4oWmv7u3uTJEsiyL5SsiNkZxkMeCDmvU8bsgzPN+Fa+FyrEujUUot6tKcdnBtapO6fny2ejZ/OnAOFWJzqjheVOU+ZK+yaTlfr2t8z85td/b18H6D4n1DQLrw5fSLY3Elv5okRWcxsVJKMAVyR0yTivEPHf7f3jjVFe18BaXb6PGeBPcH7RN9QMBAfqGrFP7UPwj8c3f2/4y/DuzvbxgA93ZNtd8dyGwT+Lmuvh/aP/ZT8IxC58EfD0y3Y5UzwxKAf99mlP5Cv49wvCeBwUoc3D9Sday3qRlTb73c7Wf8Aej8j+rKWVUKLV8vlKf8AiTj/AOlW+9Hw74w8ceNvHl8NX8bajc6jK2SjTsSo/wBxeFUf7orovgf4dufF3xp8H+F7NS0uoa3p8Cgf7c6A/pW98avjx4q+NmoW0mswW9jY2G/7LaWy4WPfjJLHlicD0HoBX13/AMEtPhrZeI/2jH+L3inEPh34cWE+t31w/wBxJFRliBPqPmkH/XOv3fhXCVa/1ahUoRoybV4RacYq/dKK0jq7Ky1s3uezm+PeByeviqkFBxhK0U767RirJattLTqz9H/CMg8af8Futd1DT/ni8P6OySsOxSyiiP8A49Niv3Qr8NP+CS+j6t8V/iv8V/2wdfiZD4i1B7K0LDtLJ9olUf7imFfwr9y6/oLhe88LUxPSrUnNejdl+CP5G8RWqeY0cAnd4ejSpP8AxRjd/c5NBRRRX0h8CFFFFAEF1/x7Sf7p/lXHV2N1/wAe0n+6f5Vx1AH/0/7+KKKKACiiigAooooA8M/aT+B+iftGfBLxB8INcIjGrWxFvORnyLmMh4ZB/uSAE46jI71+AfwU8N3H7SXwL8Qf8E5fjFt0r4kfD65nuvCstycbmhz5ltuPVcE4x1idWHEdf031+UX/AAUL/Yj8T/FG/sv2mP2c5H074keGtkoFufLe+jg5Taennx9Ezw6/Ie2PleI8slUtjKUOZpOM4/zwe6X96L1j5/cfpPAXEMKF8rxNX2cZSU6VR7Uq0dE3/cmvcn5dldn8r/iXw3r/AIN8Q3vhPxXZy6fqemzPb3VtMNskUsZwysPY/n1HFfe3/BL3x/8A8IP+1bptvK+2HVbeSBvdoyso/RWH419SX8fwg/4Kc6QmleIpLfwB8f8ASI/ssiXCGC11kwfLtZSNwkGMbceZH0w6Dj88tM+HvxW/ZK/aO8OQ/FvR7nQ7uw1OElpV/czQs+x2ilGUkUqTypPvivy3DYWWX46hjaT56HOrSXa+ql/LK26fy0P6LzDMYZ3lGMynEx9ni/ZyvTfV2bjKD+3BtJqS9HZn9gnxB/aM+Cvwp8XWXgj4ja/Bo+o6hB9ogW5DrG0ZYoCZNvlr8wI+Zh0r48/4KkfDey+NP7GOqeIPDUsV7L4elh1u0khYOskcOVl2MCQcwu5GDyRXwx/wVBnbVPH3gjxGeVvPDwUt2LxzOW/9Cr87tO8PfFXVdPisbDS9avNImbzLNILa4mtXfo5j2KULZwDjmvqs+4srKvi8rqYfnjays2nqlq9JX3v0P4FwfiDisjzqNanQU3RnGUbNq9rOz0ej207nxZovhrV9enMNhHwpwztwq/U+vt1qrrWlT6JqUumXBDNHj5l6EEZr7U+IHhHxF8JvEUHhL4j2Umiald2sV/Hb3Q8t2hnztbB75BDKfmVgQQCK8e0f4N/E349/FRvBvwh0a41y+YRq/kD91ECPvSyHCRqPVmFfl8aNZ1vYcj59rWd79rbn9T+HPjFnnEPE1WhmmEWEwKw8qkVJNbSppTdSSimmpO1ko2a3aueH+H/D+ueLNds/DHhi0lv9R1CZLe2toV3SSyyHCqoHUk1+yfxl8N3X7Ln7P+h/8E9/hOF1X4nfEm4gufFDWp3FBMR5dqGHRTgLzx5au5wJKtaZZ/B7/gmFpBhsJLbx78fdVi+zwQWyma00UzjbgAfMZDnGMCSToAiElvv/AP4J7fsS+LPh5q15+1H+0q76h8R/Em+ZUuSHksI5/vFj0E8g4YDiNPkH8VfeZJkVTnlhYfxpK02tqUHur7c8trdFfzt9dxdxjQ9lDMKi/wBlpvmpRejxFVfDK26o03713bmla2yv90/sw/ArRv2bvgboHwh0crK2mQZup1GPPu5Tvmk9fmcnGei4HavfKKK/YaFGFGnGlTVoxSSXkj+WMXi6uKr1MTXlec25N923dsKKKK1OcKKKKAILr/j2k/3T/KuOrsbr/j2k/wB0/wAq46gD/9T+/iiiigAooooAKKKKACiiigD87P2wf+Ccnwm/ahmbxvosh8K+NY8NHq1onyzOn3ftEYK7yMcSKVkX1IAFfnT4m8f/ALdv7L+gyfDn9rjwFb/GLwFD8q3ssf2srGOjfaAjspA6GeMMOzV/RTRXz+N4eo1akq+Hm6VR7uNrS/xRekvzPuMo45xOGoQweOpRxFCPwqd1KH/XuorSh8m0uiPwz0L/AIKEf8E3vi6miH4saHd6Xc6B5gs4tWs3vYIPNILAGFpA65UcSLxjgCvtS1/4KT/sLWVlHFZePrCGCJAqRJa3K7VHQBRFxj0xXv8A48/Zc/Zx+J0z3Xj3wPoupzyHLTS2cfnE+8iqH/WvGP8Ah23+w953n/8ACu9PznOPMn2/98+bj9K5oYTOqMpSpyoyb3k4yjJ2015Xqac/BNSbrPD4mlKW6hKlJf8AgUkpP5n5zfta/tof8Ex/jPq+k+IPHelan491HQlljtI7KGWyikWUqSkryNCzJlcgc4JPHNcZ4V+Iv7c37TGgJ8N/2Ovh7bfB7wHN8pvoo/shMZ4LfaSiMxx1MERf/ar9sPAn7LH7N3wxmS68B+BtF02eM5WaOzjMwI9JGBf9a98AAGBWSyDF16kquKrqPN8Xso8rfrN3lY9SXG+WYPDww2W4SdRQ+B4io5xjre6pRtTvfW+up+cv7H//AATg+FX7MdynjzxHMfFnjeTLvqt2vyQO/wB77OjFtpOeZGLSH1AOK/Rqiivo8FgaGEpKjh4KMV/V33fmz4LNs5xuZ4h4rHVXOb6vouyWyS6JJIKKKK6zzAooooAKKKKAILr/AI9pP90/yrjq7G6/49pP90/yrjqAP//Z"), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true)) } + .environment(\.revealed, false) .previewLayout(.fixed(width: 360, height: 200)) } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FullScreenMediaView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FullScreenMediaView.swift index a80c5412b6..044ee2a26d 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FullScreenMediaView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FullScreenMediaView.swift @@ -13,7 +13,7 @@ import AVKit struct FullScreenMediaView: View { @EnvironmentObject var m: ChatModel - @EnvironmentObject var scrollModel: ReverseListScrollModel + @EnvironmentObject var scrollModel: ReverseListScrollModel @State var chatItem: ChatItem @State var image: UIImage? @State var player: AVPlayer? = nil diff --git a/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift index 822dda4d06..afeb88b05d 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift @@ -69,7 +69,7 @@ struct CIMsgError: View { } .padding(.leading, 12) .padding(.vertical, 6) - .background(Color(uiColor: .tertiarySystemGroupedBackground)) + .background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) } .textSelection(.disabled) .onTapGesture(perform: onTap) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift index 25e06b9ea4..c2b4021edc 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift @@ -12,17 +12,17 @@ import SimpleXChat struct MarkedDeletedItemView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme + @Environment(\.revealed) var revealed: Bool @ObservedObject var chat: Chat var chatItem: ChatItem - @Binding var revealed: Bool var body: some View { - (Text(mergedMarkedDeletedText).italic() + Text(" ") + chatItem.timestampText) + (Text(mergedMarkedDeletedText).italic() + textSpace + chatItem.timestampText) .font(.caption) .foregroundColor(theme.colors.secondary) .padding(.horizontal, 12) .padding(.vertical, 6) - .background(chatItemFrameColor(chatItem, theme)) + .background { chatItemFrameColor(chatItem, theme).modifier(ChatTailPadding()) } .textSelection(.disabled) } @@ -79,7 +79,10 @@ struct MarkedDeletedItemView: View { struct MarkedDeletedItemView_Previews: PreviewProvider { static var previews: some View { Group { - MarkedDeletedItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(true)) + MarkedDeletedItemView( + chat: Chat.sampleData, + chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)) + ).environment(\.revealed, true) } .previewLayout(.fixed(width: 360, height: 200)) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift index 999f99b294..914f7c8a2f 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/MsgContentView.swift @@ -11,7 +11,7 @@ import SimpleXChat let uiLinkColor = UIColor(red: 0, green: 0.533, blue: 1, alpha: 1) -private let noTyping = Text(" ") +private let noTyping = Text(verbatim: " ") private let typingIndicators: [Text] = [ (typing(.black) + typing() + typing()), @@ -26,6 +26,7 @@ private func typing(_ w: Font.Weight = .light) -> Text { struct MsgContentView: View { @ObservedObject var chat: Chat + @Environment(\.showTimestamp) var showTimestamp: Bool @EnvironmentObject var theme: AppTheme var text: String var formattedText: [FormattedText]? = nil @@ -84,7 +85,7 @@ struct MsgContentView: View { } private func reserveSpaceForMeta(_ mt: CIMeta) -> Text { - (rightToLeft ? Text("\n") : Text(" ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, transparent: true, showViaProxy: showSentViaProxy) + (rightToLeft ? Text("\n") : Text(verbatim: " ")) + ciMetaText(mt, chatTTL: chat.chatInfo.timedMessagesTTL, encrypted: nil, colorMode: .transparent, showViaProxy: showSentViaProxy, showTimesamp: showTimestamp) } } @@ -103,7 +104,7 @@ func messageText(_ text: String, _ formattedText: [FormattedText]?, _ sender: St } if let i = icon { - res = Text(Image(systemName: i)).foregroundColor(secondaryColor) + Text(" ") + res + res = Text(Image(systemName: i)).foregroundColor(secondaryColor) + textSpace + res } if let s = sender { diff --git a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift index 32993d1a76..587957cd5d 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift @@ -14,12 +14,11 @@ struct ChatItemForwardingView: View { @EnvironmentObject var theme: AppTheme @Environment(\.dismiss) var dismiss - var ci: ChatItem + var chatItems: [ChatItem] var fromChatInfo: ChatInfo @Binding var composeState: ComposeState @State private var searchText: String = "" - @FocusState private var searchFocused @State private var alert: SomeAlert? private let chatsToForwardTo = filterChatsToForwardTo(chats: ChatModel.shared.chats) @@ -46,8 +45,6 @@ struct ChatItemForwardingView: View { VStack(alignment: .leading) { if !chatsToForwardTo.isEmpty { List { - searchFieldView(text: $searchText, focussed: $searchFocused, theme.colors.onBackground, theme.colors.secondary) - .padding(.leading, 2) let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase let chats = s == "" ? chatsToForwardTo : chatsToForwardTo.filter { foundChat($0, s) } ForEach(chats) { chat in @@ -55,6 +52,7 @@ struct ChatItemForwardingView: View { .disabled(chatModel.deletedChats.contains(chat.chatInfo.id)) } } + .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always)) .modifier(ThemedBackground(grouped: true)) } else { ZStack { @@ -73,11 +71,14 @@ struct ChatItemForwardingView: View { } @ViewBuilder private func forwardListChatView(_ chat: Chat) -> some View { - let prohibited = chat.prohibitedByPref( - hasSimplexLink: hasSimplexLink(ci.content.msgContent?.text), - isMediaOrFileAttachment: ci.content.msgContent?.isMediaOrFileAttachment ?? false, - isVoice: ci.content.msgContent?.isVoice ?? false - ) + let prohibited = chatItems.map { ci in + chat.prohibitedByPref( + hasSimplexLink: hasSimplexLink(ci.content.msgContent?.text), + isMediaOrFileAttachment: ci.content.msgContent?.isMediaOrFileAttachment ?? false, + isVoice: ci.content.msgContent?.isVoice ?? false + ) + }.contains(true) + Button { if prohibited { alert = SomeAlert( @@ -93,10 +94,10 @@ struct ChatItemForwardingView: View { composeState = ComposeState( message: composeState.message, preview: composeState.linkPreview != nil ? composeState.preview : .noPreview, - contextItem: .forwardingItem(chatItem: ci, fromChatInfo: fromChatInfo) + contextItem: .forwardingItems(chatItems: chatItems, fromChatInfo: fromChatInfo) ) } else { - composeState = ComposeState.init(forwardingItem: ci, fromChatInfo: fromChatInfo) + composeState = ComposeState.init(forwardingItems: chatItems, fromChatInfo: fromChatInfo) ItemsModel.shared.loadOpenChat(chat.id) } } @@ -123,7 +124,7 @@ struct ChatItemForwardingView: View { #Preview { ChatItemForwardingView( - ci: ChatItem.getSample(1, .directSnd, .now, "hello"), + chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")], fromChatInfo: .direct(contact: Contact.sampleData), composeState: Binding.constant(ComposeState(message: "hello")) ).environmentObject(CurrentColors.toAppTheme()) diff --git a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift index f6a856dad1..62ea607d27 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift @@ -450,20 +450,8 @@ struct ChatItemInfoView: View { .foregroundColor(theme.colors.secondary).opacity(0.67) } let v = Group { - let (icon, statusColor) = status.statusIcon(theme.colors.secondary, theme.colors.primary) - switch status { - case .rcvd: - ZStack(alignment: .trailing) { - Image(systemName: icon) - .foregroundColor(statusColor.opacity(0.67)) - .padding(.trailing, 6) - Image(systemName: icon) - .foregroundColor(statusColor.opacity(0.67)) - } - default: - Image(systemName: icon) - .foregroundColor(statusColor) - } + let (image, statusColor) = status.statusIcon(theme.colors.secondary, theme.colors.primary) + image.foregroundColor(statusColor) } if let (title, text) = status.statusInfo { diff --git a/apps/ios/Shared/Views/Chat/ChatItemView.swift b/apps/ios/Shared/Views/Chat/ChatItemView.swift index 870fe30108..ebbc55a932 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemView.swift @@ -9,12 +9,33 @@ import SwiftUI import SimpleXChat +extension EnvironmentValues { + struct ShowTimestamp: EnvironmentKey { + static let defaultValue: Bool = true + } + + struct Revealed: EnvironmentKey { + static let defaultValue: Bool = true + } + + var showTimestamp: Bool { + get { self[ShowTimestamp.self] } + set { self[ShowTimestamp.self] = newValue } + } + + var revealed: Bool { + get { self[Revealed.self] } + set { self[Revealed.self] = newValue } + } +} + struct ChatItemView: View { @ObservedObject var chat: Chat @EnvironmentObject var theme: AppTheme + @Environment(\.showTimestamp) var showTimestamp: Bool + @Environment(\.revealed) var revealed: Bool var chatItem: ChatItem var maxWidth: CGFloat = .infinity - @Binding var revealed: Bool @Binding var allowMenu: Bool init( @@ -22,27 +43,25 @@ struct ChatItemView: View { chatItem: ChatItem, showMember: Bool = false, maxWidth: CGFloat = .infinity, - revealed: Binding, allowMenu: Binding = .constant(false) ) { self.chat = chat self.chatItem = chatItem self.maxWidth = maxWidth - _revealed = revealed _allowMenu = allowMenu } var body: some View { let ci = chatItem if chatItem.meta.itemDeleted != nil && (!revealed || chatItem.isDeletedContent) { - MarkedDeletedItemView(chat: chat, chatItem: chatItem, revealed: $revealed) + MarkedDeletedItemView(chat: chat, chatItem: chatItem) } else if ci.quotedItem == nil && ci.meta.itemForwarded == nil && ci.meta.itemDeleted == nil && !ci.meta.isLive { if let mc = ci.content.msgContent, mc.isText && isShortEmoji(ci.content.text) { EmojiItemView(chat: chat, chatItem: ci) } else if ci.content.text.isEmpty, case let .voice(_, duration) = ci.content.msgContent { CIVoiceView(chat: chat, chatItem: ci, recordingFile: ci.file, duration: duration, allowMenu: $allowMenu) } else if ci.content.msgContent == nil { - ChatItemContentView(chat: chat, chatItem: chatItem, revealed: $revealed, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case + ChatItemContentView(chat: chat, chatItem: chatItem, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case } else { framedItemView() } @@ -60,7 +79,7 @@ struct ChatItemView: View { default: nil } } - .flatMap { UIImage(base64Encoded: $0) } + .flatMap { imageFromBase64($0) } let adjustedMaxWidth = { if let preview, preview.size.width <= preview.size.height { maxWidth * 0.75 @@ -72,7 +91,6 @@ struct ChatItemView: View { chat: chat, chatItem: chatItem, preview: preview, - revealed: $revealed, maxWidth: maxWidth, imgWidth: adjustedMaxWidth, videoWidth: adjustedMaxWidth, @@ -84,9 +102,9 @@ struct ChatItemView: View { struct ChatItemContentView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme + @Environment(\.revealed) var revealed: Bool @ObservedObject var chat: Chat var chatItem: ChatItem - @Binding var revealed: Bool var msgContentView: () -> Content @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false @@ -118,7 +136,7 @@ struct ChatItemContentView: View { case let .rcvChatPreference(feature, allowed, param): CIFeaturePreferenceView(chat: chat, chatItem: chatItem, feature: feature, allowed: allowed, param: param) case let .sndChatPreference(feature, _, _): - CIChatFeatureView(chat: chat, chatItem: chatItem, revealed: $revealed, feature: feature, icon: feature.icon, iconColor: theme.colors.secondary) + CIChatFeatureView(chat: chat, chatItem: chatItem, feature: feature, icon: feature.icon, iconColor: theme.colors.secondary) case let .rcvGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary)) case let .sndGroupFeature(feature, preference, _, role): chatFeatureView(feature, preference.enabled(role, for: chat.chatInfo.groupInfo?.membership).iconColor(theme.colors.secondary)) case let .rcvChatFeatureRejected(feature): chatFeatureView(feature, .red) @@ -152,7 +170,7 @@ struct ChatItemContentView: View { private func eventItemViewText(_ secondaryColor: Color) -> Text { if !revealed, let t = mergedGroupEventText { - return chatEventText(t + Text(" ") + chatItem.timestampText, secondaryColor) + return chatEventText(t + textSpace + chatItem.timestampText, secondaryColor) } else if let member = chatItem.memberDisplayName { return Text(member + " ") .font(.caption) @@ -165,7 +183,7 @@ struct ChatItemContentView: View { } private func chatFeatureView(_ feature: Feature, _ iconColor: Color) -> some View { - CIChatFeatureView(chat: chat, chatItem: chatItem, revealed: $revealed, feature: feature, iconColor: iconColor) + CIChatFeatureView(chat: chat, chatItem: chatItem, feature: feature, iconColor: iconColor) } private var mergedGroupEventText: Text? { @@ -185,7 +203,7 @@ struct ChatItemContentView: View { } else if ns.count == 0 { Text("\(count) group events") } else if count > ns.count { - Text(members) + Text(" ") + Text("and \(count - ns.count) other events") + Text(members) + textSpace + Text("and \(count - ns.count) other events") } else { Text(members) } @@ -216,7 +234,7 @@ func chatEventText(_ text: Text, _ secondaryColor: Color) -> Text { } func chatEventText(_ eventText: LocalizedStringKey, _ ts: Text, _ secondaryColor: Color) -> Text { - chatEventText(Text(eventText) + Text(" ") + ts, secondaryColor) + chatEventText(Text(eventText) + textSpace + ts, secondaryColor) } func chatEventText(_ ci: ChatItem, _ secondaryColor: Color) -> Text { @@ -226,16 +244,17 @@ func chatEventText(_ ci: ChatItem, _ secondaryColor: Color) -> Text { struct ChatItemView_Previews: PreviewProvider { static var previews: some View { Group{ - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample(), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(false)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true)) - ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true)) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂")) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getDeletedContentSample()) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now))) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true) + ChatItemView(chat: Chat.sampleData, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true)).environment(\.revealed, true) } + .environment(\.revealed, false) .previewLayout(.fixed(width: 360, height: 70)) .environmentObject(Chat.sampleData) } @@ -253,8 +272,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider { content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: 1, toMsgId: 2)), quotedItem: nil, file: nil - ), - revealed: Binding.constant(true) + ) ) ChatItemView( chat: Chat.sampleData, @@ -264,8 +282,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider { content: .rcvDecryptionError(msgDecryptError: .ratchetHeader, msgCount: 2), quotedItem: nil, file: nil - ), - revealed: Binding.constant(true) + ) ) ChatItemView( chat: Chat.sampleData, @@ -275,8 +292,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider { content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: .pending), memberRole: .admin), quotedItem: nil, file: nil - ), - revealed: Binding.constant(true) + ) ) ChatItemView( chat: Chat.sampleData, @@ -286,8 +302,7 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider { content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)), quotedItem: nil, file: nil - ), - revealed: Binding.constant(true) + ) ) ChatItemView( chat: Chat.sampleData, @@ -297,10 +312,10 @@ struct ChatItemView_NonMsgContentDeleted_Previews: PreviewProvider { content: ciFeatureContent, quotedItem: nil, file: nil - ), - revealed: Binding.constant(true) + ) ) } + .environment(\.revealed, true) .previewLayout(.fixed(width: 360, height: 70)) .environmentObject(Chat.sampleData) } diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 7bd13a3fa7..0c5a458930 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -22,8 +22,7 @@ struct ChatView: View { @Environment(\.presentationMode) var presentationMode @Environment(\.scenePhase) var scenePhase @State @ObservedObject var chat: Chat - @StateObject private var scrollModel = ReverseListScrollModel() - @StateObject private var floatingButtonModel = FloatingButtonModel() + @StateObject private var scrollModel = ReverseListScrollModel() @State private var showChatInfoSheet: Bool = false @State private var showAddMembersSheet: Bool = false @State private var composeState = ComposeState() @@ -43,6 +42,7 @@ struct ChatView: View { @State private var showGroupLinkSheet: Bool = false @State private var groupLink: String? @State private var groupLinkMemberRole: GroupMemberRole = .member + @State private var forwardedChatItems: [ChatItem] = [] @State private var selectedChatItems: Set? = nil @State private var showDeleteSelectedMessages: Bool = false @State private var allowToDeleteSelectedMessagesForAll: Bool = false @@ -53,7 +53,6 @@ struct ChatView: View { if #available(iOS 16.0, *) { viewBody .scrollDismissesKeyboard(.immediately) - .keyboardPadding() .toolbarBackground(.hidden, for: .navigationBar) } else { viewBody @@ -77,7 +76,7 @@ struct ChatView: View { VStack(spacing: 0) { ZStack(alignment: .bottomTrailing) { chatItemsList() - floatingButtons(counts: floatingButtonModel.unreadChatItemCounts) + FloatingButtons(theme: theme, scrollModel: scrollModel, chat: chat) } connectingText() if selectedChatItems == nil { @@ -100,7 +99,8 @@ struct ChatView: View { if case let .group(groupInfo) = chat.chatInfo { showModerateSelectedMessagesAlert(groupInfo) } - } + }, + forwardItems: forwardSelectedMessages ) } } @@ -133,10 +133,39 @@ struct ChatView: View { .appSheet(item: $selectedMember) { member in Group { if case let .group(groupInfo) = chat.chatInfo { - GroupMemberInfoView(groupInfo: groupInfo, groupMember: member, navigation: true) + GroupMemberInfoView( + groupInfo: groupInfo, + chat: chat, + groupMember: member, + navigation: true + ) } } } + // it should be presented on top level in order to prevent a bug in SwiftUI on iOS 16 related to .focused() modifier in AddGroupMembersView's search field + .appSheet(isPresented: $showAddMembersSheet) { + Group { + if case let .group(groupInfo) = cInfo { + AddGroupMembersView(chat: chat, groupInfo: groupInfo) + } + } + } + .sheet(isPresented: Binding( + get: { !forwardedChatItems.isEmpty }, + set: { isPresented in + if !isPresented { + forwardedChatItems = [] + selectedChatItems = nil + } + } + )) { + if #available(iOS 16.0, *) { + ChatItemForwardingView(chatItems: forwardedChatItems, fromChatInfo: chat.chatInfo, composeState: $composeState) + .presentationDetents([.fraction(0.8)]) + } else { + ChatItemForwardingView(chatItems: forwardedChatItems, fromChatInfo: chat.chatInfo, composeState: $composeState) + } + } .onAppear { selectedChatItems = nil initChatView() @@ -202,6 +231,8 @@ struct ChatView: View { chat: chat, contact: contact, localAlias: chat.chatInfo.localAlias, + featuresAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences), + currentFeaturesAllowed: contactUserPrefsToFeaturesAllowed(contact.mergedPreferences), onSearch: { focusSearch() } ) } @@ -288,9 +319,6 @@ struct ChatView: View { } } else { addMembersButton() - .appSheet(isPresented: $showAddMembersSheet) { - AddGroupMembersView(chat: chat, groupInfo: groupInfo) - } } } Menu { @@ -341,6 +369,7 @@ struct ChatView: View { await markChatUnread(chat, unreadChat: false) } } + ChatView.FloatingButtonModel.shared.totalUnread = chat.chatStats.unreadCount } private func searchToolbar() -> some View { @@ -412,14 +441,9 @@ struct ChatView: View { composeState: $composeState, selectedMember: $selectedMember, revealedChatItem: $revealedChatItem, - selectedChatItems: $selectedChatItems + selectedChatItems: $selectedChatItems, + forwardedChatItems: $forwardedChatItems ) - .onAppear { - floatingButtonModel.appeared(viewId: ci.viewId) - } - .onDisappear { - floatingButtonModel.disappeared(viewId: ci.viewId) - } .id(ci.id) // Required to trigger `onAppear` on iOS15 } loadPage: { loadChatItems(cInfo) @@ -430,13 +454,10 @@ struct ChatView: View { .onChange(of: searchText) { _ in Task { await loadChat(chat: chat, search: searchText) } } - .onChange(of: im.reversedChatItems) { _ in - floatingButtonModel.chatItemsChanged() - } .onChange(of: im.itemAdded) { added in if added { im.itemAdded = false - if floatingButtonModel.unreadChatItemCounts.isReallyNearBottom { + if FloatingButtonModel.shared.isReallyNearBottom { scrollModel.scrollToBottom() } } @@ -459,103 +480,169 @@ struct ChatView: View { } class FloatingButtonModel: ObservableObject { - private enum Event { - case appeared(String) - case disappeared(String) - case chatItemsChanged - } + static let shared = FloatingButtonModel() + @Published var unreadBelow: Int = 0 + @Published var isNearBottom: Bool = true + @Published var date: Date? + @Published var isDateVisible: Bool = false + var totalUnread: Int = 0 + var isReallyNearBottom: Bool = true + var hideDateWorkItem: DispatchWorkItem? - @Published var unreadChatItemCounts: UnreadChatItemCounts - - private let events = PassthroughSubject() - private var bag = Set() - - init() { - unreadChatItemCounts = UnreadChatItemCounts( - isNearBottom: true, - isReallyNearBottom: true, - unreadBelow: 0 - ) - events - .receive(on: DispatchQueue.global(qos: .background)) - .scan(Set()) { itemsInView, event in - var updated = itemsInView - switch event { - case let .appeared(viewId): updated.insert(viewId) - case let .disappeared(viewId): updated.remove(viewId) - case .chatItemsChanged: () - } - return updated + func updateOnListChange(_ listState: ListState) { + let im = ItemsModel.shared + let unreadBelow = + if let id = listState.bottomItemId, + let index = im.reversedChatItems.firstIndex(where: { $0.id == id }) + { + im.reversedChatItems[.. 0 && listState.scrollOffset < 500 + } + + // set floating button indication mode + let nearBottom = listState.scrollOffset < 800 + if nearBottom != self.isNearBottom { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { [weak self] in + self?.isNearBottom = nearBottom + } + } + + // hide Date indicator after 1 second of no scrolling + hideDateWorkItem?.cancel() + let workItem = DispatchWorkItem { [weak self] in + guard let it = self else { return } + it.setDate(visibility: false) + it.hideDateWorkItem = nil + } + DispatchQueue.main.async { [weak self] in + self?.hideDateWorkItem = workItem + DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: workItem) + } } - func appeared(viewId: String) { - events.send(.appeared(viewId)) + func resetDate() { + date = nil + isDateVisible = false } - func disappeared(viewId: String) { - events.send(.disappeared(viewId)) + private func setDate(visibility isVisible: Bool) { + if isVisible { + if !isNearBottom, + !isDateVisible, + let date, !Calendar.current.isDateInToday(date) { + withAnimation { self.isDateVisible = true } + } + } else if isDateVisible { + withAnimation { self.isDateVisible = false } + } } - func chatItemsChanged() { - events.send(.chatItemsChanged) - } } - private func floatingButtons(counts: UnreadChatItemCounts) -> some View { - VStack { - let unreadAbove = chat.chatStats.unreadCount - counts.unreadBelow - if unreadAbove > 0 { - circleButton { - unreadCountText(unreadAbove) - .font(.callout) - .foregroundColor(theme.colors.primary) + private struct FloatingButtons: View { + let theme: AppTheme + let scrollModel: ReverseListScrollModel + let chat: Chat + @ObservedObject var model = FloatingButtonModel.shared + + var body: some View { + ZStack(alignment: .top) { + if let date = model.date { + DateSeparator(date: date) + .padding(.vertical, 4).padding(.horizontal, 8) + .background(.thinMaterial) + .clipShape(Capsule()) + .opacity(model.isDateVisible ? 1 : 0) } - .onTapGesture { - scrollModel.scrollToNextPage() - } - .contextMenu { - Button { - Task { - await markChatRead(chat) + VStack { + let unreadAbove = model.totalUnread - model.unreadBelow + if unreadAbove > 0 { + circleButton { + unreadCountText(unreadAbove) + .font(.callout) + .foregroundColor(theme.colors.primary) } - } label: { - Label("Mark read", systemImage: "checkmark") + .onTapGesture { + scrollModel.scrollToNextPage() + } + .contextMenu { + Button { + Task { + await markChatRead(chat) + } + } label: { + Label("Mark read", systemImage: "checkmark") + } + } + } + Spacer() + if model.unreadBelow > 0 { + circleButton { + unreadCountText(model.unreadBelow) + .font(.callout) + .foregroundColor(theme.colors.primary) + } + .onTapGesture { + scrollModel.scrollToBottom() + } + } else if !model.isNearBottom { + circleButton { + Image(systemName: "chevron.down") + .foregroundColor(theme.colors.primary) + } + .onTapGesture { scrollModel.scrollToBottom() } } } + .padding() + .frame(maxWidth: .infinity, alignment: .trailing) } - Spacer() - if counts.unreadBelow > 0 { - circleButton { - unreadCountText(counts.unreadBelow) - .font(.callout) - .foregroundColor(theme.colors.primary) - } - .onTapGesture { - scrollModel.scrollToBottom() - } - } else if !counts.isNearBottom { - circleButton { - Image(systemName: "chevron.down") - .foregroundColor(theme.colors.primary) - } - .onTapGesture { scrollModel.scrollToBottom() } + .onDisappear(perform: model.resetDate) + } + + private func circleButton(_ content: @escaping () -> Content) -> some View { + ZStack { + Circle() + .foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground)) + .frame(width: 44, height: 44) + content() } } - .padding() } - private func circleButton(_ content: @escaping () -> Content) -> some View { - ZStack { - Circle() - .foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground)) - .frame(width: 44, height: 44) - content() + private struct DateSeparator: View { + let date: Date + + var body: some View { + Text(String.localizedStringWithFormat( + NSLocalizedString("%@, %@", comment: "format for date separator in chat"), + date.formatted(.dateTime.weekday(.abbreviated)), + date.formatted( + Calendar.current.isDate(date, equalTo: .now, toGranularity: .year) + ? .dateTime.day().month(.abbreviated) + : .dateTime.day().month(.abbreviated).year() + ) + )) + .font(.callout) + .fontWeight(.medium) + .foregroundStyle(.secondary) } } @@ -569,8 +656,8 @@ struct ChatView: View { private func endCallButton(_ call: Call) -> some View { Button { - if let uuid = call.callkitUUID { - CallController.shared.endCall(callUUID: uuid) + if CallController.useCallKit(), let callUUID = call.callUUID { + CallController.shared.endCall(callUUID: callUUID) } else { CallController.shared.endCall(call: call) {} } @@ -649,6 +736,116 @@ struct ChatView: View { } } + private func forwardSelectedMessages() { + Task { + do { + if let selectedChatItems { + let (validItems, confirmation) = try await apiPlanForwardChatItems( + type: chat.chatInfo.chatType, + id: chat.chatInfo.apiId, + itemIds: Array(selectedChatItems) + ) + if let confirmation { + if validItems.count > 0 { + showAlert( + String.localizedStringWithFormat( + NSLocalizedString("Forward %d message(s)?", comment: "alert title"), + validItems.count + ), + message: forwardConfirmationText(confirmation) + "\n" + + NSLocalizedString("Forward messages without files?", comment: "alert message") + ) { + switch confirmation { + case let .filesNotAccepted(fileIds): + [forwardAction(validItems), downloadAction(fileIds), cancelAlertAction] + default: + [forwardAction(validItems), cancelAlertAction] + } + } + } else { + showAlert( + NSLocalizedString("Nothing to forward!", comment: "alert title"), + message: forwardConfirmationText(confirmation) + ) { + switch confirmation { + case let .filesNotAccepted(fileIds): + [downloadAction(fileIds), cancelAlertAction] + default: + [okAlertAction] + } + } + } + } else { + await openForwardingSheet(validItems) + } + } + } catch { + logger.error("Plan forward chat items failed: \(error.localizedDescription)") + } + } + + func forwardConfirmationText(_ fc: ForwardConfirmation) -> String { + switch fc { + case let .filesNotAccepted(fileIds): + String.localizedStringWithFormat( + NSLocalizedString("%d file(s) were not downloaded.", comment: "forward confirmation reason"), + fileIds.count + ) + case let .filesInProgress(filesCount): + String.localizedStringWithFormat( + NSLocalizedString("%d file(s) are still being downloaded.", comment: "forward confirmation reason"), + filesCount + ) + case let .filesMissing(filesCount): + String.localizedStringWithFormat( + NSLocalizedString("%d file(s) were deleted.", comment: "forward confirmation reason"), + filesCount + ) + case let .filesFailed(filesCount): + String.localizedStringWithFormat( + NSLocalizedString("%d file(s) failed to download.", comment: "forward confirmation reason"), + filesCount + ) + } + } + + func forwardAction(_ items: [Int64]) -> UIAlertAction { + UIAlertAction( + title: NSLocalizedString("Forward messages", comment: "alert action"), + style: .default, + handler: { _ in Task { await openForwardingSheet(items) } } + ) + } + + func downloadAction(_ fileIds: [Int64]) -> UIAlertAction { + UIAlertAction( + title: NSLocalizedString("Download files", comment: "alert action"), + style: .default, + handler: { _ in + Task { + if let user = ChatModel.shared.currentUser { + await receiveFiles(user: user, fileIds: fileIds) + } + } + } + ) + } + + func openForwardingSheet(_ items: [Int64]) async { + let im = ItemsModel.shared + var items = Set(items) + var fci = [ChatItem]() + for reversedChatItem in im.reversedChatItems { + if items.contains(reversedChatItem.id) { + items.remove(reversedChatItem.id) + fci.insert(reversedChatItem, at: 0) + } + if items.isEmpty { break } + } + await MainActor.run { forwardedChatItems = fci } + } + } + private func loadChatItems(_ cInfo: ChatInfo) { Task { if loadingItems || firstPage { return } @@ -697,6 +894,7 @@ struct ChatView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme @Binding @ObservedObject var chat: Chat + @ObservedObject var dummyModel: ChatItemDummyModel = .shared let chatItem: ChatItem let maxWidth: CGFloat @Binding var composeState: ComposeState @@ -709,39 +907,66 @@ struct ChatView: View { @State private var showDeleteMessages = false @State private var showChatItemInfoSheet: Bool = false @State private var chatItemInfo: ChatItemInfo? - @State private var showForwardingSheet: Bool = false + @State private var msgWidth: CGFloat = 0 @Binding var selectedChatItems: Set? + @Binding var forwardedChatItems: [ChatItem] @State private var allowMenu: Bool = true + @State private var markedRead = false var revealed: Bool { chatItem == revealedChatItem } + typealias ItemSeparation = (timestamp: Bool, largeGap: Bool, date: Date?) + + func getItemSeparation(_ chatItem: ChatItem, at i: Int?) -> ItemSeparation { + let im = ItemsModel.shared + if let i, i > 0 && im.reversedChatItems.count >= i { + let nextItem = im.reversedChatItems[i - 1] + let largeGap = !nextItem.chatDir.sameDirection(chatItem.chatDir) || nextItem.meta.itemTs.timeIntervalSince(chatItem.meta.itemTs) > 60 + return ( + timestamp: largeGap || formatTimestampMeta(chatItem.meta.itemTs) != formatTimestampMeta(nextItem.meta.itemTs), + largeGap: largeGap, + date: Calendar.current.isDate(chatItem.meta.itemTs, inSameDayAs: nextItem.meta.itemTs) ? nil : nextItem.meta.itemTs + ) + } else { + return (timestamp: true, largeGap: true, date: nil) + } + } + var body: some View { - let (currIndex, _) = m.getNextChatItem(chatItem) + let currIndex = m.getChatItemIndex(chatItem) let ciCategory = chatItem.mergeCategory let (prevHidden, prevItem) = m.getPrevShownChatItem(currIndex, ciCategory) let range = itemsRange(currIndex, prevHidden) + let timeSeparation = getItemSeparation(chatItem, at: currIndex) let im = ItemsModel.shared Group { if revealed, let range = range { let items = Array(zip(Array(range), im.reversedChatItems[range])) - ForEach(items.reversed(), id: \.1.viewId) { (i, ci) in - let prev = i == prevHidden ? prevItem : im.reversedChatItems[i + 1] - chatItemView(ci, nil, prev) - .overlay { - if let selected = selectedChatItems, ci.canBeDeletedForSelf { - Color.clear - .contentShape(Rectangle()) - .onTapGesture { - let checked = selected.contains(ci.id) - selectUnselectChatItem(select: !checked, ci) + VStack(spacing: 0) { + ForEach(items.reversed(), id: \.1.viewId) { (i: Int, ci: ChatItem) in + let prev = i == prevHidden ? prevItem : im.reversedChatItems[i + 1] + chatItemView(ci, nil, prev, getItemSeparation(ci, at: i)) + .overlay { + if let selected = selectedChatItems, ci.canBeDeletedForSelf { + Color.clear + .contentShape(Rectangle()) + .onTapGesture { + let checked = selected.contains(ci.id) + selectUnselectChatItem(select: !checked, ci) + } } - } + } } } } else { - chatItemView(chatItem, range, prevItem) + VStack(spacing: 0) { + chatItemView(chatItem, range, prevItem, timeSeparation) + if let date = timeSeparation.date { + DateSeparator(date: date).padding(8) + } + } .overlay { if let selected = selectedChatItems, chatItem.canBeDeletedForSelf { Color.clear @@ -755,44 +980,94 @@ struct ChatView: View { } } .onAppear { + if markedRead { + return + } else { + markedRead = true + } if let range { - if let items = unreadItems(range) { + let itemIds = unreadItemIds(range) + if !itemIds.isEmpty { waitToMarkRead { - for ci in items { - await apiMarkChatItemRead(chat.chatInfo, ci) - } + await apiMarkChatItemsRead(chat.chatInfo, itemIds) } } } else if chatItem.isRcvNew { waitToMarkRead { - await apiMarkChatItemRead(chat.chatInfo, chatItem) + await apiMarkChatItemsRead(chat.chatInfo, [chatItem.id]) } } } } - - private func unreadItems(_ range: ClosedRange) -> [ChatItem]? { + + private func unreadItemIds(_ range: ClosedRange) -> [ChatItem.ID] { let im = ItemsModel.shared - let items = range.compactMap { i in + return range.compactMap { i in if i >= 0 && i < im.reversedChatItems.count { let ci = im.reversedChatItems[i] - return if ci.isRcvNew { ci } else { nil } + return if ci.isRcvNew { ci.id } else { nil } } else { return nil } } - return if items.isEmpty { nil } else { items } } private func waitToMarkRead(_ op: @Sendable @escaping () async -> Void) { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { + Task { + _ = try? await Task.sleep(nanoseconds: 600_000000) if m.chatId == chat.chatInfo.id { - Task(operation: op) + await op() } } } + - @ViewBuilder func chatItemView(_ ci: ChatItem, _ range: ClosedRange?, _ prevItem: ChatItem?) -> some View { + @available(iOS 16.0, *) + struct MemberLayout: Layout { + let spacing: Double + let msgWidth: Double + + private func sizes(subviews: Subviews, proposal: ProposedViewSize) -> (CGSize, CGSize) { + assert(subviews.count == 2, "member layout must contain exactly two subviews") + let roleSize = subviews[1].sizeThatFits(proposal) + let memberSize = subviews[0].sizeThatFits( + ProposedViewSize( + width: (proposal.width ?? msgWidth) - roleSize.width, + height: proposal.height + ) + ) + return (memberSize, roleSize) + } + + func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) -> CGSize { + let (memberSize, roleSize) = sizes(subviews: subviews, proposal: proposal) + return CGSize( + width: min( + proposal.width ?? msgWidth, + max(msgWidth, roleSize.width + spacing + memberSize.width) + ), + height: max(memberSize.height, roleSize.height) + ) + } + + func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) { + let (memberSize, roleSize) = sizes(subviews: subviews, proposal: proposal) + subviews[0].place( + at: CGPoint(x: bounds.minX, y: bounds.midY - memberSize.height / 2), + proposal: ProposedViewSize(memberSize) + ) + subviews[1].place( + at: CGPoint( + x: bounds.minX + max(memberSize.width + spacing, msgWidth - roleSize.width), + y: bounds.midY - roleSize.height / 2 + ), + proposal: ProposedViewSize(roleSize) + ) + } + } + + @ViewBuilder func chatItemView(_ ci: ChatItem, _ range: ClosedRange?, _ prevItem: ChatItem?, _ itemSeparation: ItemSeparation) -> some View { + let bottomPadding: Double = itemSeparation.largeGap ? 10 : 2 if case let .groupRcv(member) = ci.chatDir, case let .group(groupInfo) = chat.chatInfo { let (prevMember, memCount): (GroupMember?, Int) = @@ -804,41 +1079,66 @@ struct ChatView: View { if prevItem == nil || showMemberImage(member, prevItem) || prevMember != nil { VStack(alignment: .leading, spacing: 4) { if ci.content.showMemberName { - let t = if memCount == 1 && member.memberRole > .member { - Text(member.memberRole.text + " ").fontWeight(.semibold) + Text(member.displayName) - } else { - Text(memberNames(member, prevMember, memCount)) + Group { + if memCount == 1 && member.memberRole > .member { + Group { + if #available(iOS 16.0, *) { + MemberLayout(spacing: 16, msgWidth: msgWidth) { + Text(member.chatViewName) + .lineLimit(1) + Text(member.memberRole.text) + .fontWeight(.semibold) + .lineLimit(1) + .padding(.trailing, 8) + } + } else { + HStack(spacing: 16) { + Text(member.chatViewName) + .lineLimit(1) + Text(member.memberRole.text) + .fontWeight(.semibold) + .lineLimit(1) + .layoutPriority(1) + } + } + } + .frame( + maxWidth: maxWidth, + alignment: chatItem.chatDir.sent ? .trailing : .leading + ) + } else { + Text(memberNames(member, prevMember, memCount)) + .lineLimit(2) + } } - t .font(.caption) .foregroundStyle(.secondary) - .lineLimit(2) .padding(.leading, memberImageSize + 14 + (selectedChatItems != nil && ci.canBeDeletedForSelf ? 12 + 24 : 0)) - .padding(.top, 7) + .padding(.top, 3) // this is in addition to message sequence gap } HStack(alignment: .center, spacing: 0) { if selectedChatItems != nil && ci.canBeDeletedForSelf { SelectedChatItem(ciId: ci.id, selectedChatItems: $selectedChatItems) .padding(.trailing, 12) } - HStack(alignment: .top, spacing: 8) { + HStack(alignment: .top, spacing: 10) { MemberProfileImage(member, size: memberImageSize, backgroundColor: theme.colors.background) .onTapGesture { - if let member = m.getGroupMember(member.groupMemberId) { - selectedMember = member + if let mem = m.getGroupMember(member.groupMemberId) { + selectedMember = mem } else { - Task { - await m.loadGroupMembers(groupInfo) { - selectedMember = m.getGroupMember(member.groupMemberId) - } - } + let mem = GMember.init(member) + m.groupMembers.append(mem) + m.groupMembersIndexes[member.groupMemberId] = m.groupMembers.count - 1 + selectedMember = mem } } - chatItemWithMenu(ci, range, maxWidth) + chatItemWithMenu(ci, range, maxWidth, itemSeparation) + .onPreferenceChange(DetermineWidth.Key.self) { msgWidth = $0 } } } } - .padding(.bottom, 5) + .padding(.bottom, bottomPadding) .padding(.trailing) .padding(.leading, 12) } else { @@ -847,11 +1147,11 @@ struct ChatView: View { SelectedChatItem(ciId: ci.id, selectedChatItems: $selectedChatItems) .padding(.leading, 12) } - chatItemWithMenu(ci, range, maxWidth) + chatItemWithMenu(ci, range, maxWidth, itemSeparation) .padding(.trailing) - .padding(.leading, memberImageSize + 8 + 12) + .padding(.leading, 10 + memberImageSize + 12) } - .padding(.bottom, 5) + .padding(.bottom, bottomPadding) } } else { HStack(alignment: .center, spacing: 0) { @@ -864,10 +1164,10 @@ struct ChatView: View { .padding(.leading) } } - chatItemWithMenu(ci, range, maxWidth) + chatItemWithMenu(ci, range, maxWidth, itemSeparation) .padding(.horizontal) } - .padding(.bottom, 5) + .padding(.bottom, bottomPadding) } } @@ -882,17 +1182,18 @@ struct ChatView: View { } } - @ViewBuilder func chatItemWithMenu(_ ci: ChatItem, _ range: ClosedRange?, _ maxWidth: CGFloat) -> some View { + @ViewBuilder func chatItemWithMenu(_ ci: ChatItem, _ range: ClosedRange?, _ maxWidth: CGFloat, _ itemSeparation: ItemSeparation) -> some View { let alignment: Alignment = ci.chatDir.sent ? .trailing : .leading VStack(alignment: alignment.horizontal, spacing: 3) { ChatItemView( chat: chat, chatItem: ci, maxWidth: maxWidth, - revealed: .constant(revealed), allowMenu: $allowMenu ) - .modifier(ChatItemClipped(ci)) + .environment(\.revealed, revealed) + .environment(\.showTimestamp, itemSeparation.timestamp) + .modifier(ChatItemClipped(ci, tailVisible: itemSeparation.largeGap && (ci.meta.itemDeleted == nil || revealed))) .contextMenu { menu(ci, range, live: composeState.liveMessage != nil) } .accessibilityLabel("") if ci.content.msgContent != nil && (ci.meta.itemDeleted == nil || revealed) && ci.reactions.count > 0 { @@ -922,14 +1223,6 @@ struct ChatView: View { }) { ChatItemInfoView(ci: ci, chatItemInfo: $chatItemInfo) } - .sheet(isPresented: $showForwardingSheet) { - if #available(iOS 16.0, *) { - ChatItemForwardingView(ci: ci, fromChatInfo: chat.chatInfo, composeState: $composeState) - .presentationDetents([.fraction(0.8)]) - } else { - ChatItemForwardingView(ci: ci, fromChatInfo: chat.chatInfo, composeState: $composeState) - } - } } private func showMemberImage(_ member: GroupMember, _ prevItem: ChatItem?) -> Bool { @@ -957,11 +1250,20 @@ struct ChatView: View { } .padding(.horizontal, 6) .padding(.vertical, 4) - - if chat.chatInfo.featureEnabled(.reactions) && (ci.allowAddReaction || r.userReacted) { + .if(chat.chatInfo.featureEnabled(.reactions) && (ci.allowAddReaction || r.userReacted)) { v in v.onTapGesture { setReaction(ci, add: !r.userReacted, reaction: r.reaction) } + } + if case let .group(groupInfo) = chat.chatInfo { + v.contextMenu { + ReactionContextMenu( + groupInfo: groupInfo, + itemId: ci.id, + reactionCount: r, + selectedMember: $selectedMember + ) + } } else { v } @@ -1070,7 +1372,7 @@ struct ChatView: View { var forwardButton: Button { Button { - showForwardingSheet = true + forwardedChatItems = [chatItem] } label: { Label( NSLocalizedString("Forward", comment: "chat item action"), @@ -1551,6 +1853,109 @@ private func buildTheme() -> AppTheme { } } +struct ReactionContextMenu: View { + @EnvironmentObject var m: ChatModel + let groupInfo: GroupInfo + var itemId: Int64 + var reactionCount: CIReactionCount + @Binding var selectedMember: GMember? + @State private var memberReactions: [MemberReaction] = [] + @AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner + + var body: some View { + groupMemberReactionList() + .task { + logger.debug("ReactionContextMenu task \(radius)") + await loadChatItemReaction() + } + } + + @ViewBuilder private func groupMemberReactionList() -> some View { + if memberReactions.isEmpty { + ForEach(Array(repeating: 0, count: reactionCount.totalReacted), id: \.self) { _ in + Text(verbatim: " ") + } + } else { + ForEach(memberReactions, id: \.groupMember.groupMemberId) { mr in + let mem = mr.groupMember + let userMember = mem.groupMemberId == groupInfo.membership.groupMemberId + Button { + if let member = m.getGroupMember(mem.groupMemberId) { + selectedMember = member + } else { + let member = GMember.init(mem) + m.groupMembers.append(member) + m.groupMembersIndexes[member.groupMemberId] = m.groupMembers.count - 1 + selectedMember = member + } + } label: { + HStack { + Text(mem.displayName) + if let img = cropImage(mem.image) { + Image(uiImage: img) + } else { + Image(systemName: "person.crop.circle") + } + } + } + .disabled(userMember) + } + } + } + + private func cropImage(_ img: String?) -> UIImage? { + return if let originalImage = imageFromBase64(img) { + maskToCustomShape(originalImage, size: 30, radius: radius) + } else { + nil + } + } + + private func loadChatItemReaction() async { + do { + let memberReactions = try await apiGetReactionMembers( + groupId: groupInfo.groupId, + itemId: itemId, + reaction: reactionCount.reaction + ) + await MainActor.run { + self.memberReactions = memberReactions + } + } catch let error { + logger.error("apiGetReactionMembers error: \(responseError(error))") + } + } +} + +func maskToCustomShape(_ image: UIImage, size: CGFloat, radius: CGFloat) -> UIImage { + let path = Path { path in + if radius >= 50 { + path.addEllipse(in: CGRect(x: 0, y: 0, width: size, height: size)) + } else if radius <= 0 { + path.addRect(CGRect(x: 0, y: 0, width: size, height: size)) + } else { + let cornerRadius = size * CGFloat(radius) / 100 + path.addRoundedRect( + in: CGRect(x: 0, y: 0, width: size, height: size), + cornerSize: CGSize(width: cornerRadius, height: cornerRadius), + style: .continuous + ) + } + } + + return UIGraphicsImageRenderer(size: CGSize(width: size, height: size)).image { context in + context.cgContext.addPath(path.cgPath) + context.cgContext.clip() + let scale = size / max(image.size.width, image.size.height) + let imageSize = CGSize(width: image.size.width * scale, height: image.size.height * scale) + let imageOrigin = CGPoint( + x: (size - imageSize.width) / 2, + y: (size - imageSize.height) / 2 + ) + image.draw(in: CGRect(origin: imageOrigin, size: imageSize)) + } +} + struct ToggleNtfsButton: View { @ObservedObject var chat: Chat diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeImageView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeImageView.swift index df3a8caf55..14026d79d1 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeImageView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeImageView.swift @@ -18,7 +18,7 @@ struct ComposeImageView: View { var body: some View { HStack(alignment: .center, spacing: 8) { let imgs: [UIImage] = images.compactMap { image in - UIImage(base64Encoded: image) + imageFromBase64(image) } if imgs.count == 0 { ProgressView() diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeLinkView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeLinkView.swift index 66cb9edcf8..6c44aeea83 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeLinkView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeLinkView.swift @@ -40,7 +40,7 @@ struct ComposeLinkView: View { private func linkPreviewView(_ linkPreview: LinkPreview) -> some View { HStack(alignment: .center, spacing: 8) { - if let uiImage = UIImage(base64Encoded: linkPreview.image) { + if let uiImage = imageFromBase64(linkPreview.image) { Image(uiImage: uiImage) .resizable() .aspectRatio(contentMode: .fit) @@ -55,7 +55,7 @@ struct ComposeLinkView: View { .foregroundColor(theme.colors.secondary) } .padding(.vertical, 5) - .frame(maxWidth: .infinity, minHeight: 60, maxHeight: 60) + .frame(maxWidth: .infinity, minHeight: 60) } } } diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift index e059d72e98..19e2b528f1 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift @@ -23,7 +23,7 @@ enum ComposeContextItem { case noContextItem case quotedItem(chatItem: ChatItem) case editingItem(chatItem: ChatItem) - case forwardingItem(chatItem: ChatItem, fromChatInfo: ChatInfo) + case forwardingItems(chatItems: [ChatItem], fromChatInfo: ChatInfo) } enum VoiceMessageRecordingState { @@ -73,10 +73,10 @@ struct ComposeState { } } - init(forwardingItem: ChatItem, fromChatInfo: ChatInfo) { + init(forwardingItems: [ChatItem], fromChatInfo: ChatInfo) { self.message = "" self.preview = .noPreview - self.contextItem = .forwardingItem(chatItem: forwardingItem, fromChatInfo: fromChatInfo) + self.contextItem = .forwardingItems(chatItems: forwardingItems, fromChatInfo: fromChatInfo) self.voiceMessageRecordingState = .noRecording } @@ -112,7 +112,7 @@ struct ComposeState { var forwarding: Bool { switch contextItem { - case .forwardingItem: return true + case .forwardingItems: return true default: return false } } @@ -167,6 +167,13 @@ struct ComposeState { } } + var manyMediaPreviews: Bool { + switch preview { + case let .mediaPreviews(mediaPreviews): return mediaPreviews.count > 1 + default: return false + } + } + var attachmentDisabled: Bool { if editing || forwarding || liveMessage != nil || inProgress { return true } switch preview { @@ -280,8 +287,8 @@ struct ComposeView: View { // this is a workaround to fire an explicit event in certain cases @State private var stopPlayback: Bool = false - @AppStorage(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true - @AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial + @UserDefault(DEFAULT_PRIVACY_SAVE_LAST_DRAFT) private var saveLastDraft = true + @UserDefault(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial var body: some View { VStack(spacing: 0) { @@ -382,7 +389,11 @@ struct ComposeView: View { } } } - .background(ToolbarMaterial.material(toolbarMaterial)) + .background { + Color.clear + .overlay(ToolbarMaterial.material(toolbarMaterial)) + .ignoresSafeArea(.all, edges: .bottom) + } .onChange(of: composeState.message) { msg in if composeState.linkPreviewAllowed { if msg.count > 0 { @@ -448,7 +459,7 @@ struct ComposeView: View { Task { var media: [(String, UploadContent)] = [] for content in selected { - if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) { + if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) { media.append((img, content)) await MainActor.run { composeState = composeState.copy(preview: .mediaPreviews(mediaPreviews: media)) @@ -540,7 +551,7 @@ struct ComposeView: View { } private func addMediaContent(_ content: UploadContent) async { - if let img = resizeImageToStrSize(content.uiImage, maxDataSize: 14000) { + if let img = await resizeImageToStrSize(content.uiImage, maxDataSize: 14000) { var newMedia: [(String, UploadContent?)] = [] if case var .mediaPreviews(media) = composeState.preview { media.append((img, content)) @@ -683,7 +694,7 @@ struct ComposeView: View { case let .quotedItem(chatItem: quotedItem): ContextItemView( chat: chat, - contextItem: quotedItem, + contextItems: [quotedItem], contextIcon: "arrowshape.turn.up.left", cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) } ) @@ -691,18 +702,17 @@ struct ComposeView: View { case let .editingItem(chatItem: editingItem): ContextItemView( chat: chat, - contextItem: editingItem, + contextItems: [editingItem], contextIcon: "pencil", cancelContextItem: { clearState() } ) Divider() - case let .forwardingItem(chatItem: forwardedItem, _): + case let .forwardingItems(chatItems, _): ContextItemView( chat: chat, - contextItem: forwardedItem, + contextItems: chatItems, contextIcon: "arrowshape.turn.up.forward", - cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) }, - showSender: false + cancelContextItem: { composeState = composeState.copy(contextItem: .noContextItem) } ) Divider() } @@ -726,10 +736,11 @@ struct ComposeView: View { } if chat.chatInfo.contact?.nextSendGrpInv ?? false { await sendMemberContactInvitation() - } else if case let .forwardingItem(ci, fromChatInfo) = composeState.contextItem { - sent = await forwardItem(ci, fromChatInfo, ttl) + } else if case let .forwardingItems(chatItems, fromChatInfo) = composeState.contextItem { + // Composed text is send as a reply to the last forwarded item + sent = await forwardItems(chatItems, fromChatInfo, ttl).last if !composeState.message.isEmpty { - sent = await send(checkLinkPreview(), quoted: sent?.id, live: false, ttl: ttl) + _ = await send(checkLinkPreview(), quoted: sent?.id, live: false, ttl: ttl) } } else if case let .editingItem(ci) = composeState.contextItem { sent = await updateMessage(ci, live: live) @@ -746,26 +757,28 @@ struct ComposeView: View { sent = await send(.text(msgText), quoted: quoted, live: live, ttl: ttl) case .linkPreview: sent = await send(checkLinkPreview(), quoted: quoted, live: live, ttl: ttl) - case let .mediaPreviews(mediaPreviews: media): + case let .mediaPreviews(media): let last = media.count - 1 + var msgs: [ComposedMessage] = [] if last >= 0 { for i in 0.. 0 { + // Sleep to allow `progressByTimeout` update be rendered + try? await Task.sleep(nanoseconds: 100_000000) + } + if let (fileSource, msgContent) = mediaContent(media[i], text: "") { + msgs.append(ComposedMessage(fileSource: fileSource, msgContent: msgContent)) } - _ = try? await Task.sleep(nanoseconds: 100_000000) } - if case (_, .video(_, _, _)) = media[last] { - sent = await sendVideo(media[last], text: msgText, quoted: quoted, live: live, ttl: ttl) - } else { - sent = await sendImage(media[last], text: msgText, quoted: quoted, live: live, ttl: ttl) + if let (fileSource, msgContent) = mediaContent(media[last], text: msgText) { + msgs.append(ComposedMessage(fileSource: fileSource, quotedItemId: quoted, msgContent: msgContent)) } } - if sent == nil { - sent = await send(.text(msgText), quoted: quoted, live: live, ttl: ttl) + if msgs.isEmpty { + msgs = [ComposedMessage(quotedItemId: quoted, msgContent: .text(msgText))] } + sent = await send(msgs, live: live, ttl: ttl).last + case let .voicePreview(recordingFileName, duration): stopPlayback.toggle() let file = voiceCryptoFile(recordingFileName) @@ -787,6 +800,20 @@ struct ComposeView: View { } return sent + func mediaContent(_ media: (String, UploadContent?), text: String) -> (CryptoFile?, MsgContent)? { + let (previewImage, uploadContent) = media + return switch uploadContent { + case let .simpleImage(image): + (saveImage(image), .image(text: text, image: previewImage)) + case let .animatedImage(image): + (saveAnimImage(image), .image(text: text, image: previewImage)) + case let .video(_, url, duration): + (moveTempFileFromURL(url), .video(text: text, image: previewImage, duration: duration)) + case .none: + nil + } + } + func sending() async { await MainActor.run { composeState.inProgress = true } } @@ -850,23 +877,6 @@ struct ComposeView: View { } } - func sendImage(_ imageData: (String, UploadContent?), text: String = "", quoted: Int64? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? { - let (image, data) = imageData - if let data = data, let savedFile = saveAnyImage(data) { - return await send(.image(text: text, image: image), quoted: quoted, file: savedFile, live: live, ttl: ttl) - } - return nil - } - - func sendVideo(_ imageData: (String, UploadContent?), text: String = "", quoted: Int64? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? { - let (image, data) = imageData - if case let .video(_, url, duration) = data, let savedFile = moveTempFileFromURL(url) { - ChatModel.shared.filesToDelete.remove(url) - return await send(.video(text: text, image: image, duration: duration), quoted: quoted, file: savedFile, live: live, ttl: ttl) - } - return nil - } - func voiceCryptoFile(_ fileName: String) -> CryptoFile? { if !privacyEncryptLocalFilesGroupDefault.get() { return CryptoFile.plain(fileName) @@ -883,44 +893,66 @@ struct ComposeView: View { } func send(_ mc: MsgContent, quoted: Int64?, file: CryptoFile? = nil, live: Bool = false, ttl: Int?) async -> ChatItem? { - if let chatItem = chat.chatInfo.chatType == .local - ? await apiCreateChatItem(noteFolderId: chat.chatInfo.apiId, file: file, msg: mc) - : await apiSendMessage( + await send( + [ComposedMessage(fileSource: file, quotedItemId: quoted, msgContent: mc)], + live: live, + ttl: ttl + ).first + } + + func send(_ msgs: [ComposedMessage], live: Bool, ttl: Int?) async -> [ChatItem] { + if let chatItems = chat.chatInfo.chatType == .local + ? await apiCreateChatItems(noteFolderId: chat.chatInfo.apiId, composedMessages: msgs) + : await apiSendMessages( type: chat.chatInfo.chatType, id: chat.chatInfo.apiId, - file: file, - quotedItemId: quoted, - msg: mc, live: live, - ttl: ttl + ttl: ttl, + composedMessages: msgs ) { await MainActor.run { chatModel.removeLiveDummy(animated: false) - chatModel.addChatItem(chat.chatInfo, chatItem) + for chatItem in chatItems { + chatModel.addChatItem(chat.chatInfo, chatItem) + } } - return chatItem + return chatItems } - if let file = file { - removeFile(file.filePath) + for msg in msgs { + if let file = msg.fileSource { + removeFile(file.filePath) + } } - return nil + return [] } - func forwardItem(_ forwardedItem: ChatItem, _ fromChatInfo: ChatInfo, _ ttl: Int?) async -> ChatItem? { - if let chatItem = await apiForwardChatItem( + func forwardItems(_ forwardedItems: [ChatItem], _ fromChatInfo: ChatInfo, _ ttl: Int?) async -> [ChatItem] { + if let chatItems = await apiForwardChatItems( toChatType: chat.chatInfo.chatType, toChatId: chat.chatInfo.apiId, fromChatType: fromChatInfo.chatType, fromChatId: fromChatInfo.apiId, - itemId: forwardedItem.id, + itemIds: forwardedItems.map { $0.id }, ttl: ttl ) { await MainActor.run { - chatModel.addChatItem(chat.chatInfo, chatItem) + for chatItem in chatItems { + chatModel.addChatItem(chat.chatInfo, chatItem) + } + if forwardedItems.count != chatItems.count { + showAlert( + String.localizedStringWithFormat( + NSLocalizedString("%d messages not forwarded", comment: "alert title"), + forwardedItems.count - chatItems.count + ), + message: NSLocalizedString("Messages were deleted after you selected them.", comment: "alert message") + ) + } } - return chatItem + return chatItems + } else { + return [] } - return nil } func checkLinkPreview() -> MsgContent { @@ -937,14 +969,6 @@ struct ComposeView: View { return .text(msgText) } } - - func saveAnyImage(_ img: UploadContent) -> CryptoFile? { - switch img { - case let .simpleImage(image): return saveImage(image) - case let .animatedImage(image): return saveAnimImage(image) - default: return nil - } - } } private func startVoiceMessageRecording() async { diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift index 6245bbe21f..fa999961fc 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift @@ -12,7 +12,7 @@ import SimpleXChat struct ContextItemView: View { @EnvironmentObject var theme: AppTheme @ObservedObject var chat: Chat - let contextItem: ChatItem + let contextItems: [ChatItem] let contextIcon: String let cancelContextItem: () -> Void var showSender: Bool = true @@ -24,13 +24,22 @@ struct ContextItemView: View { .aspectRatio(contentMode: .fit) .frame(width: 16, height: 16) .foregroundColor(theme.colors.secondary) - if showSender, let sender = contextItem.memberDisplayName { - VStack(alignment: .leading, spacing: 4) { - Text(sender).font(.caption).foregroundColor(theme.colors.secondary) - msgContentView(lines: 2) - } + if let singleItem = contextItems.first, contextItems.count == 1 { + if showSender, let sender = singleItem.memberDisplayName { + VStack(alignment: .leading, spacing: 4) { + Text(sender).font(.caption).foregroundColor(theme.colors.secondary) + msgContentView(lines: 2, contextItem: singleItem) + } + } else { + msgContentView(lines: 3, contextItem: singleItem) + } } else { - msgContentView(lines: 3) + Text( + chat.chatInfo.chatType == .local + ? "Saving \(contextItems.count) messages" + : "Forwarding \(contextItems.count) messages" + ) + .italic() } Spacer() Button { @@ -45,29 +54,38 @@ struct ContextItemView: View { .padding(12) .frame(minHeight: 54) .frame(maxWidth: .infinity) - .background(chatItemFrameColor(contextItem, theme)) + .background(background) } - private func msgContentView(lines: Int) -> some View { - contextMsgPreview() + private var background: Color { + contextItems.first + .map { chatItemFrameColor($0, theme) } + ?? Color(uiColor: .tertiarySystemBackground) + } + + private func msgContentView(lines: Int, contextItem: ChatItem) -> some View { + contextMsgPreview(contextItem) .multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading) .lineLimit(lines) } - private func contextMsgPreview() -> Text { + private func contextMsgPreview(_ contextItem: ChatItem) -> Text { return attachment() + messageText(contextItem.text, contextItem.formattedText, nil, preview: true, showSecrets: false, secondaryColor: theme.colors.secondary) func attachment() -> Text { + let isFileLoaded = if let fileSource = getLoadedFileSource(contextItem.file) { + FileManager.default.fileExists(atPath: getAppFilePath(fileSource.filePath).path) + } else { false } switch contextItem.content.msgContent { - case .file: return image("doc.fill") + case .file: return isFileLoaded ? image("doc.fill") : Text("") case .image: return image("photo") - case .voice: return image("play.fill") + case .voice: return isFileLoaded ? image("play.fill") : Text("") default: return Text("") } } func image(_ s: String) -> Text { - Text(Image(systemName: s)).foregroundColor(Color(uiColor: .tertiaryLabel)) + Text(" ") + Text(Image(systemName: s)).foregroundColor(Color(uiColor: .tertiaryLabel)) + textSpace } } } @@ -75,6 +93,6 @@ struct ContextItemView: View { struct ContextItemView_Previews: PreviewProvider { static var previews: some View { let contextItem: ChatItem = ChatItem.getSample(1, .directSnd, .now, "hello") - return ContextItemView(chat: Chat.sampleData, contextItem: contextItem, contextIcon: "pencil.circle", cancelContextItem: {}) + return ContextItemView(chat: Chat.sampleData, contextItems: [contextItem], contextIcon: "pencil.circle", cancelContextItem: {}) } } diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/SendMessageView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/SendMessageView.swift index 9ad6e986bd..8880023e02 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/SendMessageView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/SendMessageView.swift @@ -40,7 +40,7 @@ struct SendMessageView: View { @State private var showCustomTimePicker = false @State private var selectedDisappearingMessageTime: Int? = customDisappearingMessageTimeDefault.get() @State private var progressByTimeout = false - @AppStorage(DEFAULT_LIVE_MESSAGE_ALERT_SHOWN) private var liveMessageAlertShown = false + @UserDefault(DEFAULT_LIVE_MESSAGE_ALERT_SHOWN) private var liveMessageAlertShown = false var body: some View { ZStack { @@ -227,6 +227,7 @@ struct SendMessageView: View { !composeState.editing { if case .noContextItem = composeState.contextItem, !composeState.voicePreview, + !composeState.manyMediaPreviews, let send = sendLiveMessage, let update = updateLiveMessage { Button { diff --git a/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift b/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift index b3fab958bc..e4489e46ee 100644 --- a/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/ContactPreferencesView.swift @@ -14,9 +14,10 @@ struct ContactPreferencesView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme @Binding var contact: Contact - @State var featuresAllowed: ContactFeaturesAllowed - @State var currentFeaturesAllowed: ContactFeaturesAllowed + @Binding var featuresAllowed: ContactFeaturesAllowed + @Binding var currentFeaturesAllowed: ContactFeaturesAllowed @State private var showSaveDialogue = false + let savePreferences: () -> Void var body: some View { let user: User = chatModel.currentUser! @@ -48,7 +49,10 @@ struct ContactPreferencesView: View { savePreferences() dismiss() } - Button("Exit without saving") { dismiss() } + Button("Exit without saving") { + featuresAllowed = currentFeaturesAllowed + dismiss() + } } } @@ -118,31 +122,15 @@ struct ContactPreferencesView: View { private func featureFooter(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> some View { Text(feature.enabledDescription(enabled)) } - - private func savePreferences() { - Task { - do { - let prefs = contactFeaturesAllowedToPrefs(featuresAllowed) - if let toContact = try await apiSetContactPrefs(contactId: contact.contactId, preferences: prefs) { - await MainActor.run { - contact = toContact - chatModel.updateContact(toContact) - currentFeaturesAllowed = featuresAllowed - } - } - } catch { - logger.error("ContactPreferencesView apiSetContactPrefs error: \(responseError(error))") - } - } - } } struct ContactPreferencesView_Previews: PreviewProvider { static var previews: some View { ContactPreferencesView( contact: Binding.constant(Contact.sampleData), - featuresAllowed: ContactFeaturesAllowed.sampleData, - currentFeaturesAllowed: ContactFeaturesAllowed.sampleData + featuresAllowed: Binding.constant(ContactFeaturesAllowed.sampleData), + currentFeaturesAllowed: Binding.constant(ContactFeaturesAllowed.sampleData), + savePreferences: {} ) } } diff --git a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift index 189ab95494..bdef8d0a62 100644 --- a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift +++ b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift @@ -78,7 +78,12 @@ struct AddGroupMembersViewCommon: View { let count = selectedContacts.count Section { if creatingGroup { - groupPreferencesButton($groupInfo, true) + GroupPreferencesButton( + groupInfo: $groupInfo, + preferences: groupInfo.fullGroupPreferences, + currentPreferences: groupInfo.fullGroupPreferences, + creatingGroup: true + ) } rolePicker() inviteMembersButton() @@ -105,8 +110,10 @@ struct AddGroupMembersViewCommon: View { .padding(.leading, 2) let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase let members = s == "" ? membersToAdd : membersToAdd.filter { $0.chatViewName.localizedLowercase.contains(s) } - ForEach(members) { contact in - contactCheckView(contact) + ForEach(members + [dummyContact]) { contact in + if contact.contactId != dummyContact.contactId { + contactCheckView(contact) + } } } } @@ -130,12 +137,21 @@ struct AddGroupMembersViewCommon: View { .modifier(ThemedBackground(grouped: true)) } - private func inviteMembersButton() -> some View { + // Resolves keyboard losing focus bug in iOS16 and iOS17, + // when there are no items inside `ForEach(memebers)` loop + private let dummyContact: Contact = { + var dummy = Contact.sampleData + dummy.contactId = -1 + return dummy + }() + + @ViewBuilder private func inviteMembersButton() -> some View { + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Invite to group" : "Invite to chat" Button { inviteMembers() } label: { HStack { - Text("Invite to group") + Text(label) Image(systemName: "checkmark") } } @@ -221,6 +237,7 @@ func searchFieldView(text: Binding, focussed: FocusState.Binding, .focused(focussed) .foregroundColor(onBackgroundColor) .frame(maxWidth: .infinity) + .autocorrectionDisabled(true) Image(systemName: "xmark.circle.fill") .resizable() .scaledToFit() diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 50eb883e92..c4df91bb8b 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -81,13 +81,13 @@ struct GroupChatInfoView: View { .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) Section { - if groupInfo.canEdit { + if groupInfo.isOwner && groupInfo.businessChat == nil { editGroupButton() } - if groupInfo.groupProfile.description != nil || groupInfo.canEdit { + if groupInfo.groupProfile.description != nil || (groupInfo.isOwner && groupInfo.businessChat == nil) { addOrEditWelcomeMessage() } - groupPreferencesButton($groupInfo) + GroupPreferencesButton(groupInfo: $groupInfo, preferences: groupInfo.fullGroupPreferences, currentPreferences: groupInfo.fullGroupPreferences) if members.filter({ $0.wrapped.memberCurrent }).count <= SMALL_GROUPS_RCPS_MEM_LIMIT { sendReceiptsOption() } else { @@ -101,13 +101,20 @@ struct GroupChatInfoView: View { } header: { Text("") } footer: { - Text("Only group owners can change group preferences.") + let label: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "Only group owners can change group preferences." + : "Only chat owners can change preferences." + ) + Text(label) .foregroundColor(theme.colors.secondary) } Section(header: Text("\(members.count + 1) members").foregroundColor(theme.colors.secondary)) { if groupInfo.canAddMembers { - groupLinkButton() + if groupInfo.businessChat == nil { + groupLinkButton() + } if (chat.chatInfo.incognito) { Label("Invite members", systemImage: "plus") .foregroundColor(Color(uiColor: .tertiaryLabel)) @@ -185,7 +192,6 @@ struct GroupChatInfoView: View { logger.error("GroupChatInfoView apiGetGroupLink: \(responseError(error))") } } - .keyboardPadding() } private func groupInfoHeader() -> some View { @@ -277,10 +283,15 @@ struct GroupChatInfoView: View { } private func addMembersButton() -> some View { - NavigationLink { + let label: LocalizedStringKey = switch groupInfo.businessChat?.chatType { + case .customer: "Add team members" + case .business: "Add friends" + case .none: "Invite members" + } + return NavigationLink { addMembersDestinationView() } label: { - Label("Invite members", systemImage: "plus") + Label(label, systemImage: "plus") } } @@ -419,7 +430,7 @@ struct GroupChatInfoView: View { } private var memberVerifiedShield: Text { - (Text(Image(systemName: "checkmark.shield")) + Text(" ")) + (Text(Image(systemName: "checkmark.shield")) + textSpace) .font(.caption) .baselineOffset(2) .kerning(-2) @@ -428,7 +439,7 @@ struct GroupChatInfoView: View { } private func memberInfoView(_ groupMember: GMember) -> some View { - GroupMemberInfoView(groupInfo: groupInfo, groupMember: groupMember) + GroupMemberInfoView(groupInfo: groupInfo, chat: chat, groupMember: groupMember) .navigationBarHidden(false) } @@ -488,11 +499,12 @@ struct GroupChatInfoView: View { } } - private func deleteGroupButton() -> some View { + @ViewBuilder private func deleteGroupButton() -> some View { + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Delete group" : "Delete chat" Button(role: .destructive) { alert = .deleteGroupAlert } label: { - Label("Delete group", systemImage: "trash") + Label(label, systemImage: "trash") .foregroundColor(Color.red) } } @@ -506,20 +518,22 @@ struct GroupChatInfoView: View { } } - private func leaveGroupButton() -> some View { + @ViewBuilder private func leaveGroupButton() -> some View { + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Leave group" : "Leave chat" Button(role: .destructive) { alert = .leaveGroupAlert } label: { - Label("Leave group", systemImage: "rectangle.portrait.and.arrow.right") + Label(label, systemImage: "rectangle.portrait.and.arrow.right") .foregroundColor(Color.red) } } // TODO reuse this and clearChatAlert with ChatInfoView private func deleteGroupAlert() -> Alert { + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Delete group?" : "Delete chat?" return Alert( - title: Text("Delete group?"), - message: deleteGroupAlertMessage(), + title: Text(label), + message: deleteGroupAlertMessage(groupInfo), primaryButton: .destructive(Text("Delete")) { Task { do { @@ -538,10 +552,6 @@ struct GroupChatInfoView: View { ) } - private func deleteGroupAlertMessage() -> Text { - groupInfo.membership.memberCurrent ? Text("Group will be deleted for all members - this cannot be undone!") : Text("Group will be deleted for you - this cannot be undone!") - } - private func clearChatAlert() -> Alert { Alert( title: Text("Clear conversation?"), @@ -557,9 +567,15 @@ struct GroupChatInfoView: View { } private func leaveGroupAlert() -> Alert { - Alert( - title: Text("Leave group?"), - message: Text("You will stop receiving messages from this group. Chat history will be preserved."), + let titleLabel: LocalizedStringKey = groupInfo.businessChat == nil ? "Leave group?" : "Leave chat?" + let messageLabel: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "You will stop receiving messages from this group. Chat history will be preserved." + : "You will stop receiving messages from this chat. Chat history will be preserved." + ) + return Alert( + title: Text(titleLabel), + message: Text(messageLabel), primaryButton: .destructive(Text("Leave")) { Task { await leaveGroup(chat.chatInfo.apiId) @@ -603,9 +619,14 @@ struct GroupChatInfoView: View { } private func removeMemberAlert(_ mem: GroupMember) -> Alert { - Alert( + let messageLabel: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "Member will be removed from group - this cannot be undone!" + : "Member will be removed from chat - this cannot be undone!" + ) + return Alert( title: Text("Remove member?"), - message: Text("Member will be removed from group - this cannot be undone!"), + message: Text(messageLabel), primaryButton: .destructive(Text("Remove")) { Task { do { @@ -625,26 +646,80 @@ struct GroupChatInfoView: View { } } -func groupPreferencesButton(_ groupInfo: Binding, _ creatingGroup: Bool = false) -> some View { - NavigationLink { - GroupPreferencesView( - groupInfo: groupInfo, - preferences: groupInfo.wrappedValue.fullGroupPreferences, - currentPreferences: groupInfo.wrappedValue.fullGroupPreferences, - creatingGroup: creatingGroup - ) - .navigationBarTitle("Group preferences") - .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.large) - } label: { - if creatingGroup { - Text("Set group preferences") - } else { - Label("Group preferences", systemImage: "switch.2") +func deleteGroupAlertMessage(_ groupInfo: GroupInfo) -> Text { + groupInfo.businessChat == nil ? ( + groupInfo.membership.memberCurrent ? Text("Group will be deleted for all members - this cannot be undone!") : Text("Group will be deleted for you - this cannot be undone!") + ) : ( + groupInfo.membership.memberCurrent ? Text("Chat will be deleted for all members - this cannot be undone!") : Text("Chat will be deleted for you - this cannot be undone!") + ) +} + +struct GroupPreferencesButton: View { + @Binding var groupInfo: GroupInfo + @State var preferences: FullGroupPreferences + @State var currentPreferences: FullGroupPreferences + var creatingGroup: Bool = false + + private var label: LocalizedStringKey { + groupInfo.businessChat == nil ? "Group preferences" : "Chat preferences" + } + + var body: some View { + NavigationLink { + GroupPreferencesView( + groupInfo: $groupInfo, + preferences: $preferences, + currentPreferences: currentPreferences, + creatingGroup: creatingGroup, + savePreferences: savePreferences + ) + .navigationBarTitle(label) + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + .onDisappear { + let saveText = NSLocalizedString( + creatingGroup ? "Save" : "Save and notify group members", + comment: "alert button" + ) + + if groupInfo.fullGroupPreferences != preferences { + showAlert( + title: NSLocalizedString("Save preferences?", comment: "alert title"), + buttonTitle: saveText, + buttonAction: { savePreferences() }, + cancelButton: true + ) + } + } + } label: { + if creatingGroup { + Text("Set group preferences") + } else { + Label(label, systemImage: "switch.2") + } } } + + private func savePreferences() { + Task { + do { + var gp = groupInfo.groupProfile + gp.groupPreferences = toGroupPreferences(preferences) + let gInfo = try await apiUpdateGroup(groupInfo.groupId, gp) + await MainActor.run { + groupInfo = gInfo + ChatModel.shared.updateGroup(gInfo) + currentPreferences = preferences + } + } catch { + logger.error("GroupPreferencesView apiUpdateGroup error: \(responseError(error))") + } + } + } + } + func cantInviteIncognitoAlert() -> Alert { Alert( title: Text("Can't invite contacts!"), diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index ddf3b8e4b9..a18de1b349 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -14,10 +14,15 @@ struct GroupMemberInfoView: View { @EnvironmentObject var theme: AppTheme @Environment(\.dismiss) var dismiss: DismissAction @State var groupInfo: GroupInfo + @ObservedObject var chat: Chat @ObservedObject var groupMember: GMember var navigation: Bool = false @State private var connectionStats: ConnectionStats? = nil @State private var connectionCode: String? = nil + @State private var connectionLoaded: Bool = false + @State private var knownContactChat: Chat? = nil + @State private var knownContact: Contact? = nil + @State private var knownContactConnectionStats: ConnectionStats? = nil @State private var newRole: GroupMemberRole = .member @State private var alert: GroupMemberInfoViewAlert? @State private var sheet: PlanAndConnectActionSheet? @@ -94,128 +99,149 @@ struct GroupMemberInfoView: View { .listRowSeparator(.hidden) .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) - if member.memberActive { - Section { - if let code = connectionCode { verifyCodeButton(code) } - if let connStats = connectionStats, - connStats.ratchetSyncAllowed { - synchronizeConnectionButton() - } - // } else if developerTools { - // synchronizeConnectionButtonForce() - // } - } - } + if connectionLoaded { - if let contactLink = member.contactLink { - Section { - SimpleXLinkQRCode(uri: contactLink) - Button { - showShareSheet(items: [simplexChatLink(contactLink)]) - } label: { - Label("Share address", systemImage: "square.and.arrow.up") + if member.memberActive { + Section { + if let code = connectionCode { verifyCodeButton(code) } + if let connStats = connectionStats, + connStats.ratchetSyncAllowed { + synchronizeConnectionButton() + } + // } else if developerTools { + // synchronizeConnectionButtonForce() + // } } - if let contactId = member.memberContactId { - if knownDirectChat(contactId) == nil && !groupInfo.fullGroupPreferences.directMessages.on(for: groupInfo.membership) { + } + + if let contactLink = member.contactLink { + Section { + SimpleXLinkQRCode(uri: contactLink) + Button { + showShareSheet(items: [simplexChatLink(contactLink)]) + } label: { + Label("Share address", systemImage: "square.and.arrow.up") + } + if member.memberContactId != nil { + if knownContactChat == nil && !groupInfo.fullGroupPreferences.directMessages.on(for: groupInfo.membership) { + connectViaAddressButton(contactLink) + } + } else { connectViaAddressButton(contactLink) } - } else { - connectViaAddressButton(contactLink) + } header: { + Text("Address") + .foregroundColor(theme.colors.secondary) + } footer: { + Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.") + .foregroundColor(theme.colors.secondary) } - } header: { - Text("Address") - .foregroundColor(theme.colors.secondary) - } footer: { - Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.") - .foregroundColor(theme.colors.secondary) } - } - Section(header: Text("Member").foregroundColor(theme.colors.secondary)) { - infoRow("Group", groupInfo.displayName) + Section(header: Text("Member").foregroundColor(theme.colors.secondary)) { + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Group" : "Chat" + infoRow(label, groupInfo.displayName) - if let roles = member.canChangeRoleTo(groupInfo: groupInfo) { - Picker("Change role", selection: $newRole) { - ForEach(roles) { role in - Text(role.text) + if let roles = member.canChangeRoleTo(groupInfo: groupInfo) { + Picker("Change role", selection: $newRole) { + ForEach(roles) { role in + Text(role.text) + } } + .frame(height: 36) + } else { + infoRow("Role", member.memberRole.text) } - .frame(height: 36) - } else { - infoRow("Role", member.memberRole.text) } - } - if let connStats = connectionStats { - Section(header: Text("Servers").foregroundColor(theme.colors.secondary)) { - // TODO network connection status - Button("Change receiving address") { - alert = .switchAddressAlert - } - .disabled( - connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil } - || connStats.ratchetSyncSendProhibited - ) - if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) { - Button("Abort changing address") { - alert = .abortSwitchAddressAlert + if let connStats = connectionStats { + Section(header: Text("Servers").foregroundColor(theme.colors.secondary)) { + // TODO network connection status + Button("Change receiving address") { + alert = .switchAddressAlert } .disabled( - connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil && !$0.canAbortSwitch } + connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil } || connStats.ratchetSyncSendProhibited ) + if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) { + Button("Abort changing address") { + alert = .abortSwitchAddressAlert + } + .disabled( + connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil && !$0.canAbortSwitch } + || connStats.ratchetSyncSendProhibited + ) + } + smpServers("Receiving via", connStats.rcvQueuesInfo.map { $0.rcvServer }, theme.colors.secondary) + smpServers("Sending via", connStats.sndQueuesInfo.map { $0.sndServer }, theme.colors.secondary) } - smpServers("Receiving via", connStats.rcvQueuesInfo.map { $0.rcvServer }, theme.colors.secondary) - smpServers("Sending via", connStats.sndQueuesInfo.map { $0.sndServer }, theme.colors.secondary) } - } - if groupInfo.membership.memberRole >= .admin { - adminDestructiveSection(member) - } else { - nonAdminBlockSection(member) - } + if groupInfo.membership.memberRole >= .admin { + adminDestructiveSection(member) + } else { + nonAdminBlockSection(member) + } - if developerTools { - Section(header: Text("For console").foregroundColor(theme.colors.secondary)) { - infoRow("Local name", member.localDisplayName) - infoRow("Database ID", "\(member.groupMemberId)") - if let conn = member.activeConn { - let connLevelDesc = conn.connLevel == 0 ? NSLocalizedString("direct", comment: "connection level description") : String.localizedStringWithFormat(NSLocalizedString("indirect (%d)", comment: "connection level description"), conn.connLevel) - infoRow("Connection", connLevelDesc) - } - Button ("Debug delivery") { - Task { - do { - let info = queueInfoText(try await apiGroupMemberQueueInfo(groupInfo.apiId, member.groupMemberId)) - await MainActor.run { alert = .queueInfo(info: info) } - } catch let e { - logger.error("apiContactQueueInfo error: \(responseError(e))") - let a = getErrorAlert(e, "Error") - await MainActor.run { alert = .error(title: a.title, error: a.message) } + if developerTools { + Section(header: Text("For console").foregroundColor(theme.colors.secondary)) { + infoRow("Local name", member.localDisplayName) + infoRow("Database ID", "\(member.groupMemberId)") + if let conn = member.activeConn { + let connLevelDesc = conn.connLevel == 0 ? NSLocalizedString("direct", comment: "connection level description") : String.localizedStringWithFormat(NSLocalizedString("indirect (%d)", comment: "connection level description"), conn.connLevel) + infoRow("Connection", connLevelDesc) + } + Button ("Debug delivery") { + Task { + do { + let info = queueInfoText(try await apiGroupMemberQueueInfo(groupInfo.apiId, member.groupMemberId)) + await MainActor.run { alert = .queueInfo(info: info) } + } catch let e { + logger.error("apiContactQueueInfo error: \(responseError(e))") + let a = getErrorAlert(e, "Error") + await MainActor.run { alert = .error(title: a.title, error: a.message) } + } } } } } + } } .navigationBarHidden(true) - .onAppear { + .task { if #unavailable(iOS 16) { // this condition prevents re-setting picker if !justOpened { return } } justOpened = false - DispatchQueue.main.async { - newRole = member.memberRole - do { - let (_, stats) = try apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId) - let (mem, code) = member.memberActive ? try apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil) + newRole = member.memberRole + do { + let (_, stats) = try await apiGroupMemberInfo(groupInfo.apiId, member.groupMemberId) + let (mem, code) = member.memberActive ? try await apiGetGroupMemberCode(groupInfo.apiId, member.groupMemberId) : (member, nil) + await MainActor.run { _ = chatModel.upsertGroupMember(groupInfo, mem) connectionStats = stats connectionCode = code + connectionLoaded = true + } + } catch let error { + await MainActor.run { + connectionLoaded = true + } + logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))") + } + if let contactId = member.memberContactId, let (contactChat, contact) = knownDirectChat(contactId) { + knownContactChat = contactChat + knownContact = contact + do { + let (stats, _) = try await apiContactInfo(contactChat.chatInfo.apiId) + await MainActor.run { + knownContactConnectionStats = stats + } } catch let error { - logger.error("apiGroupMemberInfo or apiGetGroupMemberCode error: \(responseError(error))") + logger.error("apiContactInfo error: \(responseError(error))") } } } @@ -251,6 +277,11 @@ struct GroupMemberInfoView: View { ProgressView().scaleEffect(2) } } + .onChange(of: chat.chatInfo) { c in + if case let .group(gI) = chat.chatInfo { + groupInfo = gI + } + } .modifier(ThemedBackground(grouped: true)) } @@ -258,10 +289,10 @@ struct GroupMemberInfoView: View { GeometryReader { g in let buttonWidth = g.size.width / 4 HStack(alignment: .center, spacing: 8) { - if let contactId = member.memberContactId, let (chat, contact) = knownDirectChat(contactId) { + if let chat = knownContactChat, let contact = knownContact { knownDirectChatButton(chat, width: buttonWidth) - AudioCallButton(chat: chat, contact: contact, width: buttonWidth) { alert = .someAlert(alert: $0) } - VideoButton(chat: chat, contact: contact, width: buttonWidth) { alert = .someAlert(alert: $0) } + AudioCallButton(chat: chat, contact: contact, connectionStats: $knownContactConnectionStats, width: buttonWidth) { alert = .someAlert(alert: $0) } + VideoButton(chat: chat, contact: contact, connectionStats: $knownContactConnectionStats, width: buttonWidth) { alert = .someAlert(alert: $0) } } else if groupInfo.fullGroupPreferences.directMessages.on(for: groupInfo.membership) { if let contactId = member.memberContactId { newDirectChatButton(contactId, width: buttonWidth) @@ -296,10 +327,15 @@ struct GroupMemberInfoView: View { } func showDirectMessagesProhibitedAlert(_ title: LocalizedStringKey) { + let messageLabel: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "Direct messages between members are prohibited." + : "Direct messages between members are prohibited in this chat." + ) alert = .someAlert(alert: SomeAlert( alert: mkAlert( title: title, - message: "Direct messages between members are prohibited in this group." + message: messageLabel ), id: "can't message member, direct messages prohibited" )) @@ -345,25 +381,49 @@ struct GroupMemberInfoView: View { func createMemberContactButton(width: CGFloat) -> some View { InfoViewButton(image: "message.fill", title: "message", width: width) { - progressIndicator = true - Task { - do { - let memberContact = try await apiCreateMemberContact(groupInfo.apiId, groupMember.groupMemberId) - await MainActor.run { - progressIndicator = false - chatModel.addChat(Chat(chatInfo: .direct(contact: memberContact))) - ItemsModel.shared.loadOpenChat(memberContact.id) { - dismissAllSheets(animated: true) + if let connStats = connectionStats { + if connStats.ratchetSyncState == .ok { + progressIndicator = true + Task { + do { + let memberContact = try await apiCreateMemberContact(groupInfo.apiId, groupMember.groupMemberId) + await MainActor.run { + progressIndicator = false + chatModel.addChat(Chat(chatInfo: .direct(contact: memberContact))) + ItemsModel.shared.loadOpenChat(memberContact.id) { + dismissAllSheets(animated: true) + } + NetworkModel.shared.setContactNetworkStatus(memberContact, .connected) + } + } catch let error { + logger.error("createMemberContactButton apiCreateMemberContact error: \(responseError(error))") + let a = getErrorAlert(error, "Error creating member contact") + await MainActor.run { + progressIndicator = false + alert = .error(title: a.title, error: a.message) + } } - NetworkModel.shared.setContactNetworkStatus(memberContact, .connected) - } - } catch let error { - logger.error("createMemberContactButton apiCreateMemberContact error: \(responseError(error))") - let a = getErrorAlert(error, "Error creating member contact") - await MainActor.run { - progressIndicator = false - alert = .error(title: a.title, error: a.message) } + } else if connStats.ratchetSyncAllowed { + alert = .someAlert(alert: SomeAlert( + alert: Alert( + title: Text("Fix connection?"), + message: Text("Connection requires encryption renegotiation."), + primaryButton: .default(Text("Fix")) { + syncMemberConnection(force: false) + }, + secondaryButton: .cancel() + ), + id: "can't message member, fix connection" + )) + } else { + alert = .someAlert(alert: SomeAlert( + alert: mkAlert( + title: "Can't message member", + message: "Encryption renegotiation in progress." + ), + id: "can't message contact, encryption renegotiation in progress" + )) } } } @@ -379,7 +439,7 @@ struct GroupMemberInfoView: View { Text(Image(systemName: "checkmark.shield")) .foregroundColor(theme.colors.secondary) .font(.title2) - + Text(" ") + + textSpace + Text(mem.displayName) .font(.largeTitle) ) @@ -528,9 +588,14 @@ struct GroupMemberInfoView: View { } private func removeMemberAlert(_ mem: GroupMember) -> Alert { - Alert( + let label: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "Member will be removed from group - this cannot be undone!" + : "Member will be removed from chat - this cannot be undone!" + ) + return Alert( title: Text("Remove member?"), - message: Text("Member will be removed from group - this cannot be undone!"), + message: Text(label), primaryButton: .destructive(Text("Remove")) { Task { do { @@ -553,7 +618,15 @@ struct GroupMemberInfoView: View { private func changeMemberRoleAlert(_ mem: GroupMember) -> Alert { Alert( title: Text("Change member role?"), - message: mem.memberCurrent ? Text("Member role will be changed to \"\(newRole.text)\". All group members will be notified.") : Text("Member role will be changed to \"\(newRole.text)\". The member will receive a new invitation."), + message: ( + mem.memberCurrent + ? ( + groupInfo.businessChat == nil + ? Text("Member role will be changed to \"\(newRole.text)\". All group members will be notified.") + : Text("Member role will be changed to \"\(newRole.text)\". All chat members will be notified.") + ) + : Text("Member role will be changed to \"\(newRole.text)\". The member will receive a new invitation.") + ), primaryButton: .default(Text("Change")) { Task { do { @@ -561,7 +634,7 @@ struct GroupMemberInfoView: View { await MainActor.run { _ = chatModel.upsertGroupMember(groupInfo, updatedMember) } - + } catch let error { newRole = mem.memberRole logger.error("apiMemberRole error: \(responseError(error))") @@ -730,6 +803,7 @@ struct GroupMemberInfoView_Previews: PreviewProvider { static var previews: some View { GroupMemberInfoView( groupInfo: GroupInfo.sampleData, + chat: Chat.sampleData, groupMember: GMember.sampleData ) } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift index 2b0d05375b..9ef53258aa 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift @@ -20,9 +20,10 @@ struct GroupPreferencesView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme @Binding var groupInfo: GroupInfo - @State var preferences: FullGroupPreferences - @State var currentPreferences: FullGroupPreferences + @Binding var preferences: FullGroupPreferences + var currentPreferences: FullGroupPreferences let creatingGroup: Bool + let savePreferences: () -> Void @State private var showSaveDialogue = false var body: some View { @@ -38,7 +39,7 @@ struct GroupPreferencesView: View { featureSection(.simplexLinks, $preferences.simplexLinks.enable, $preferences.simplexLinks.role) featureSection(.history, $preferences.history.enable) - if groupInfo.canEdit { + if groupInfo.isOwner { Section { Button("Reset") { preferences = currentPreferences } Button(saveText) { savePreferences() } @@ -68,7 +69,10 @@ struct GroupPreferencesView: View { savePreferences() dismiss() } - Button("Exit without saving") { dismiss() } + Button("Exit without saving") { + preferences = currentPreferences + dismiss() + } } } @@ -77,7 +81,7 @@ struct GroupPreferencesView: View { let color: Color = enableFeature.wrappedValue == .on ? .green : theme.colors.secondary let icon = enableFeature.wrappedValue == .on ? feature.iconFilled : feature.icon let timedOn = feature == .timedMessages && enableFeature.wrappedValue == .on - if groupInfo.canEdit { + if groupInfo.isOwner { let enable = Binding( get: { enableFeature.wrappedValue == .on }, set: { on, _ in enableFeature.wrappedValue = on ? .on : .off } @@ -123,7 +127,7 @@ struct GroupPreferencesView: View { } } } footer: { - Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.canEdit)) + Text(feature.enableDescription(enableFeature.wrappedValue, groupInfo.isOwner)) .foregroundColor(theme.colors.secondary) } .onChange(of: enableFeature.wrappedValue) { enabled in @@ -132,32 +136,16 @@ struct GroupPreferencesView: View { } } } - - private func savePreferences() { - Task { - do { - var gp = groupInfo.groupProfile - gp.groupPreferences = toGroupPreferences(preferences) - let gInfo = try await apiUpdateGroup(groupInfo.groupId, gp) - await MainActor.run { - groupInfo = gInfo - chatModel.updateGroup(gInfo) - currentPreferences = preferences - } - } catch { - logger.error("GroupPreferencesView apiUpdateGroup error: \(responseError(error))") - } - } - } } struct GroupPreferencesView_Previews: PreviewProvider { static var previews: some View { GroupPreferencesView( groupInfo: Binding.constant(GroupInfo.sampleData), - preferences: FullGroupPreferences.sampleData, + preferences: Binding.constant(FullGroupPreferences.sampleData), currentPreferences: FullGroupPreferences.sampleData, - creatingGroup: false + creatingGroup: false, + savePreferences: {} ) } } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift b/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift index 18cc3f4d80..1617edd11f 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupProfileView.swift @@ -110,10 +110,13 @@ struct GroupProfileView: View { } } .onChange(of: chosenImage) { image in - if let image = image { - groupProfile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) - } else { - groupProfile.image = nil + Task { + let resized: String? = if let image { + await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) + } else { + nil + } + await MainActor.run { groupProfile.image = resized } } } .onAppear { diff --git a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift index 9a9002f9dc..8dfc32f6ea 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupWelcomeView.swift @@ -23,7 +23,7 @@ struct GroupWelcomeView: View { var body: some View { VStack { - if groupInfo.canEdit { + if groupInfo.isOwner && groupInfo.businessChat == nil { editorView() .modifier(BackButton(disabled: Binding.constant(false)) { if welcomeTextUnchanged() { diff --git a/apps/ios/Shared/Views/Chat/ReverseList.swift b/apps/ios/Shared/Views/Chat/ReverseList.swift index 4ce6a1a065..e33adcef58 100644 --- a/apps/ios/Shared/Views/Chat/ReverseList.swift +++ b/apps/ios/Shared/Views/Chat/ReverseList.swift @@ -8,15 +8,16 @@ import SwiftUI import Combine +import SimpleXChat /// A List, which displays it's items in reverse order - from bottom to top -struct ReverseList: UIViewControllerRepresentable { - let items: Array +struct ReverseList: UIViewControllerRepresentable { + let items: Array - @Binding var scrollState: ReverseListScrollModel.State + @Binding var scrollState: ReverseListScrollModel.State /// Closure, that returns user interface for a given item - let content: (Item) -> Content + let content: (ChatItem) -> Content let loadPage: () -> Void @@ -25,7 +26,9 @@ struct ReverseList: UIV } func updateUIViewController(_ controller: Controller, context: Context) { + controller.representer = self if case let .scrollingTo(destination) = scrollState, !items.isEmpty { + controller.view.layer.removeAllAnimations() switch destination { case .nextPage: controller.scrollToNextPage() @@ -42,9 +45,10 @@ struct ReverseList: UIV /// Controller, which hosts SwiftUI cells class Controller: UITableViewController { private enum Section { case main } - private let representer: ReverseList - private var dataSource: UITableViewDiffableDataSource! + var representer: ReverseList + private var dataSource: UITableViewDiffableDataSource! private var itemCount: Int = 0 + private let updateFloatingButtons = PassthroughSubject() private var bag = Set() init(representer: ReverseList) { @@ -71,10 +75,10 @@ struct ReverseList: UIV } // 3. Configure data source - self.dataSource = UITableViewDiffableDataSource( + self.dataSource = UITableViewDiffableDataSource( tableView: tableView ) { (tableView, indexPath, item) -> UITableViewCell? in - if indexPath.item > self.itemCount - 8, self.itemCount > 8 { + if indexPath.item > self.itemCount - 8 { self.representer.loadPage() } let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseId, for: indexPath) @@ -103,6 +107,15 @@ struct ReverseList: UIV name: notificationName, object: nil ) + + updateFloatingButtons + .throttle(for: 0.2, scheduler: DispatchQueue.global(qos: .background), latest: true) + .sink { + if let listState = DispatchQueue.main.sync(execute: { [weak self] in self?.getListState() }) { + ChatView.FloatingButtonModel.shared.updateOnListChange(listState) + } + } + .store(in: &bag) } @available(*, unavailable) @@ -171,8 +184,8 @@ struct ReverseList: UIV Task { representer.scrollState = .atDestination } } - func update(items: Array) { - var snapshot = NSDiffableDataSourceSnapshot() + func update(items: [ChatItem]) { + var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.main]) snapshot.appendItems(items) dataSource.defaultRowAnimation = .none @@ -180,7 +193,50 @@ struct ReverseList: UIV snapshot, animatingDifferences: itemCount != 0 && abs(items.count - itemCount) == 1 ) + // Sets content offset on initial load + if itemCount == 0 { + tableView.setContentOffset( + CGPoint(x: 0, y: -InvertedTableView.inset), + animated: false + ) + } itemCount = items.count + updateFloatingButtons.send() + } + + override func scrollViewDidScroll(_ scrollView: UIScrollView) { + updateFloatingButtons.send() + } + + func getListState() -> ListState? { + if let visibleRows = tableView.indexPathsForVisibleRows, + visibleRows.last?.item ?? 0 < representer.items.count { + let scrollOffset: Double = tableView.contentOffset.y + InvertedTableView.inset + let topItemDate: Date? = + if let lastVisible = visibleRows.last(where: { isVisible(indexPath: $0) }) { + representer.items[lastVisible.item].meta.itemTs + } else { + nil + } + let bottomItemId: ChatItem.ID? = + if let firstVisible = visibleRows.first(where: { isVisible(indexPath: $0) }) { + representer.items[firstVisible.item].id + } else { + nil + } + return (scrollOffset: scrollOffset, topItemDate: topItemDate, bottomItemId: bottomItemId) + } + return nil + } + + private func isVisible(indexPath: IndexPath) -> Bool { + if let relativeFrame = tableView.superview?.convert( + tableView.rectForRow(at: indexPath), + from: tableView + ) { + relativeFrame.maxY > InvertedTableView.inset && + relativeFrame.minY < tableView.frame.height - InvertedTableView.inset + } else { false } } } @@ -224,13 +280,19 @@ struct ReverseList: UIV } } +typealias ListState = ( + scrollOffset: Double, + topItemDate: Date?, + bottomItemId: ChatItem.ID? +) + /// Manages ``ReverseList`` scrolling -class ReverseListScrollModel: ObservableObject { +class ReverseListScrollModel: ObservableObject { /// Represents Scroll State of ``ReverseList`` enum State: Equatable { enum Destination: Equatable { case nextPage - case item(Item.ID) + case item(ChatItem.ID) case bottom } @@ -248,7 +310,7 @@ class ReverseListScrollModel: ObservableObject { state = .scrollingTo(.bottom) } - func scrollToItem(id: Item.ID) { + func scrollToItem(id: ChatItem.ID) { state = .scrollingTo(.item(id)) } } diff --git a/apps/ios/Shared/Views/Chat/SelectableChatItemToolbars.swift b/apps/ios/Shared/Views/Chat/SelectableChatItemToolbars.swift index 87bc73a60e..7b185d8211 100644 --- a/apps/ios/Shared/Views/Chat/SelectableChatItemToolbars.swift +++ b/apps/ios/Shared/Views/Chat/SelectableChatItemToolbars.swift @@ -32,13 +32,17 @@ struct SelectedItemsBottomToolbar: View { var deleteItems: (Bool) -> Void var moderateItems: () -> Void //var shareItems: () -> Void + var forwardItems: () -> Void @State var deleteEnabled: Bool = false @State var deleteForEveryoneEnabled: Bool = false @State var canModerate: Bool = false @State var moderateEnabled: Bool = false - @State var allButtonsDisabled = false + @State var forwardEnabled: Bool = false + + @State var deleteCountProhibited = false + @State var forwardCountProhibited = false var body: some View { VStack(spacing: 0) { @@ -50,10 +54,11 @@ struct SelectedItemsBottomToolbar: View { } label: { Image(systemName: "trash") .resizable() + .scaledToFit() .frame(width: 20, height: 20, alignment: .center) - .foregroundColor(!deleteEnabled || allButtonsDisabled ? theme.colors.secondary: .red) + .foregroundColor(!deleteEnabled || deleteCountProhibited ? theme.colors.secondary: .red) } - .disabled(!deleteEnabled || allButtonsDisabled) + .disabled(!deleteEnabled || deleteCountProhibited) Spacer() Button { @@ -61,24 +66,24 @@ struct SelectedItemsBottomToolbar: View { } label: { Image(systemName: "flag") .resizable() + .scaledToFit() .frame(width: 20, height: 20, alignment: .center) - .foregroundColor(!moderateEnabled || allButtonsDisabled ? theme.colors.secondary : .red) + .foregroundColor(!moderateEnabled || deleteCountProhibited ? theme.colors.secondary : .red) } - .disabled(!moderateEnabled || allButtonsDisabled) + .disabled(!moderateEnabled || deleteCountProhibited) .opacity(canModerate ? 1 : 0) - Spacer() Button { - //shareItems() + forwardItems() } label: { - Image(systemName: "square.and.arrow.up") + Image(systemName: "arrowshape.turn.up.forward") .resizable() + .scaledToFit() .frame(width: 20, height: 20, alignment: .center) - .foregroundColor(allButtonsDisabled ? theme.colors.secondary : theme.colors.primary) + .foregroundColor(!forwardEnabled || forwardCountProhibited ? theme.colors.secondary : theme.colors.primary) } - .disabled(allButtonsDisabled) - .opacity(0) + .disabled(!forwardEnabled || forwardCountProhibited) } .frame(maxHeight: .infinity) .padding([.leading, .trailing], 12) @@ -101,20 +106,22 @@ struct SelectedItemsBottomToolbar: View { private func recheckItems(_ chatInfo: ChatInfo, _ chatItems: [ChatItem], _ selectedItems: Set?) { let count = selectedItems?.count ?? 0 - allButtonsDisabled = count == 0 || count > 20 + deleteCountProhibited = count == 0 || count > 200 + forwardCountProhibited = count == 0 || count > 20 canModerate = possibleToModerate(chatInfo) if let selected = selectedItems { let me: Bool let onlyOwnGroupItems: Bool - (deleteEnabled, deleteForEveryoneEnabled, me, onlyOwnGroupItems, selectedChatItems) = chatItems.reduce((true, true, true, true, [])) { (r, ci) in + (deleteEnabled, deleteForEveryoneEnabled, me, onlyOwnGroupItems, forwardEnabled, selectedChatItems) = chatItems.reduce((true, true, true, true, true, [])) { (r, ci) in if selected.contains(ci.id) { - var (de, dee, me, onlyOwnGroupItems, sel) = r + var (de, dee, me, onlyOwnGroupItems, fe, sel) = r de = de && ci.canBeDeletedForSelf dee = dee && ci.meta.deletable && !ci.localNote onlyOwnGroupItems = onlyOwnGroupItems && ci.chatDir == .groupSnd me = me && ci.content.msgContent != nil && ci.memberToModerate(chatInfo) != nil + fe = fe && ci.content.msgContent != nil && ci.meta.itemDeleted == nil && !ci.isLiveDummy sel.insert(ci.id) // we are collecting new selected items here to account for any changes in chat items list - return (de, dee, me, onlyOwnGroupItems, sel) + return (de, dee, me, onlyOwnGroupItems, fe, sel) } else { return r } diff --git a/apps/ios/Shared/Views/ChatList/ChatHelp.swift b/apps/ios/Shared/Views/ChatList/ChatHelp.swift index c84cdb0b97..7abab33177 100644 --- a/apps/ios/Shared/Views/ChatList/ChatHelp.swift +++ b/apps/ios/Shared/Views/ChatList/ChatHelp.swift @@ -10,7 +10,7 @@ import SwiftUI struct ChatHelp: View { @EnvironmentObject var chatModel: ChatModel - @Binding var showSettings: Bool + let dismissSettingsSheet: DismissAction var body: some View { ScrollView { chatHelp() } @@ -23,7 +23,7 @@ struct ChatHelp: View { VStack(alignment: .leading, spacing: 0) { Text("To ask any questions and to receive updates:") Button("connect to SimpleX Chat developers.") { - showSettings = false + dismissSettingsSheet() DispatchQueue.main.async { UIApplication.shared.open(simplexTeamURL) } @@ -42,7 +42,8 @@ struct ChatHelp: View { Text("above, then choose:") } - Text("**Add contact**: to create a new invitation link, or connect via a link you received.") + Text("**Create 1-time link**: to create and share a new invitation link.") + Text("**Scan / Paste link**: to connect via a link you received.") Text("**Create group**: to create a new group.") } .padding(.top, 24) @@ -61,8 +62,9 @@ struct ChatHelp: View { } struct ChatHelp_Previews: PreviewProvider { + @Environment(\.dismiss) static var mockDismiss + static var previews: some View { - @State var showSettings = false - return ChatHelp(showSettings: $showSettings) + ChatHelp(dismissSettingsSheet: mockDismiss) } } diff --git a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift index c8424ef332..6c5dad1f74 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListNavLink.swift @@ -355,6 +355,7 @@ struct ChatListNavLink: View { .tint(.red) } .frame(height: dynamicRowHeight) + .contentShape(Rectangle()) .onTapGesture { showContactRequestDialog = true } .confirmationDialog("Accept connection request?", isPresented: $showContactRequestDialog, titleVisibility: .visible) { Button("Accept") { Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) } } @@ -392,6 +393,7 @@ struct ChatListNavLink: View { } } } + .contentShape(Rectangle()) .onTapGesture { showContactConnectionInfo = true } @@ -402,8 +404,9 @@ struct ChatListNavLink: View { } private func deleteGroupAlert(_ groupInfo: GroupInfo) -> Alert { - Alert( - title: Text("Delete group?"), + let label: LocalizedStringKey = groupInfo.businessChat == nil ? "Delete group?" : "Delete chat?" + return Alert( + title: Text(label), message: deleteGroupAlertMessage(groupInfo), primaryButton: .destructive(Text("Delete")) { Task { await deleteChat(chat) } @@ -412,10 +415,6 @@ struct ChatListNavLink: View { ) } - private func deleteGroupAlertMessage(_ groupInfo: GroupInfo) -> Text { - groupInfo.membership.memberCurrent ? Text("Group will be deleted for all members - this cannot be undone!") : Text("Group will be deleted for you - this cannot be undone!") - } - private func clearChatAlert() -> Alert { Alert( title: Text("Clear conversation?"), @@ -439,9 +438,15 @@ struct ChatListNavLink: View { } private func leaveGroupAlert(_ groupInfo: GroupInfo) -> Alert { - Alert( - title: Text("Leave group?"), - message: Text("You will stop receiving messages from this group. Chat history will be preserved."), + let titleLabel: LocalizedStringKey = groupInfo.businessChat == nil ? "Leave group?" : "Leave chat?" + let messageLabel: LocalizedStringKey = ( + groupInfo.businessChat == nil + ? "You will stop receiving messages from this group. Chat history will be preserved." + : "You will stop receiving messages from this chat. Chat history will be preserved." + ) + return Alert( + title: Text(titleLabel), + message: Text(messageLabel), primaryButton: .destructive(Text("Leave")) { Task { await leaveGroup(groupInfo.groupId) } }, diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index 8c9d090890..b18e9295b9 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -9,22 +9,119 @@ import SwiftUI import SimpleXChat +enum UserPickerSheet: Identifiable { + case address + case chatPreferences + case chatProfiles + case currentProfile + case useFromDesktop + case settings + + var id: Self { self } + + var navigationTitle: LocalizedStringKey { + switch self { + case .address: "SimpleX address" + case .chatPreferences: "Your preferences" + case .chatProfiles: "Your chat profiles" + case .currentProfile: "Your current profile" + case .useFromDesktop: "Connect to desktop" + case .settings: "Your settings" + } + } +} + +class SaveableSettings: ObservableObject { + @Published var servers: ServerSettings = ServerSettings(currUserServers: [], userServers: [], serverErrors: []) +} + +struct ServerSettings { + public var currUserServers: [UserOperatorServers] + public var userServers: [UserOperatorServers] + public var serverErrors: [UserServersError] +} + +struct UserPickerSheetView: View { + let sheet: UserPickerSheet + @EnvironmentObject var chatModel: ChatModel + @StateObject private var ss = SaveableSettings() + + @State private var loaded = false + + var body: some View { + NavigationView { + ZStack { + if loaded, let currentUser = chatModel.currentUser { + switch sheet { + case .address: + UserAddressView(shareViaProfile: currentUser.addressShared) + case .chatPreferences: + PreferencesView( + profile: currentUser.profile, + preferences: currentUser.fullPreferences, + currentPreferences: currentUser.fullPreferences + ) + case .chatProfiles: + UserProfilesView() + case .currentProfile: + UserProfile() + case .useFromDesktop: + ConnectDesktopView() + case .settings: + SettingsView() + } + } + Color.clear // Required for list background to be rendered during loading + } + .navigationTitle(sheet.navigationTitle) + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } + .overlay { + if let la = chatModel.laRequest { + LocalAuthView(authRequest: la) + } + } + .task { + withAnimation( + .easeOut(duration: 0.1), + { loaded = true } + ) + } + .onDisappear { + if serversCanBeSaved( + ss.servers.currUserServers, + ss.servers.userServers, + ss.servers.serverErrors + ) { + showAlert( + title: NSLocalizedString("Save servers?", comment: "alert title"), + buttonTitle: NSLocalizedString("Save", comment: "alert button"), + buttonAction: { saveServers($ss.servers.currUserServers, $ss.servers.userServers) }, + cancelButton: true + ) + } + } + .environmentObject(ss) + } +} + struct ChatListView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme - @Binding var showSettings: Bool + @Binding var activeUserPickerSheet: UserPickerSheet? @State private var searchMode = false @FocusState private var searchFocussed @State private var searchText = "" @State private var searchShowingSimplexLink = false @State private var searchChatFilteredBySimplexLink: String? = nil - @State private var userPickerVisible = false - @State private var showConnectDesktop = false @State private var scrollToSearchBar = false + @State private var userPickerShown: Bool = false @AppStorage(DEFAULT_SHOW_UNREAD_AND_FAVORITES) private var showUnreadAndFavorites = false @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true @AppStorage(DEFAULT_ONE_HAND_UI_CARD_SHOWN) private var oneHandUICardShown = false + @AppStorage(DEFAULT_ADDRESS_CREATION_CARD_SHOWN) private var addressCreationCardShown = false @AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial var body: some View { @@ -46,21 +143,23 @@ struct ChatListView: View { ), destination: chatView ) { chatListView } - if userPickerVisible { - Rectangle().fill(.white.opacity(0.001)).onTapGesture { - withAnimation { - userPickerVisible.toggle() - } + } + .modifier( + Sheet(isPresented: $userPickerShown) { + UserPicker(userPickerShown: $userPickerShown, activeSheet: $activeUserPickerSheet) + } + ) + .appSheet( + item: $activeUserPickerSheet, + onDismiss: { chatModel.laRequest = nil }, + content: { UserPickerSheetView(sheet: $0) } + ) + .onChange(of: activeUserPickerSheet) { + if $0 != nil { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + userPickerShown = false } } - UserPicker( - showSettings: $showSettings, - showConnectDesktop: $showConnectDesktop, - userPickerVisible: $userPickerVisible - ) - } - .sheet(isPresented: $showConnectDesktop) { - ConnectDesktopView() } } @@ -73,7 +172,7 @@ struct ChatListView: View { .navigationBarHidden(searchMode || oneHandUI) } .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) - .onDisappear() { withAnimation { userPickerVisible = false } } + .onDisappear() { activeUserPickerSheet = nil } .refreshable { AlertManager.shared.showAlert(Alert( title: Text("Reconnect servers?"), @@ -164,7 +263,7 @@ struct ChatListView: View { let user = chatModel.currentUser ?? User.sampleData ZStack(alignment: .topTrailing) { ProfileImage(imageStr: user.image, size: 32, color: Color(uiColor: .quaternaryLabel)) - .padding(.trailing, 4) + .padding([.top, .trailing], 3) let allRead = chatModel.users .filter { u in !u.user.activeUser && !u.user.hidden } .allSatisfy { u in u.unreadCount == 0 } @@ -173,13 +272,7 @@ struct ChatListView: View { } } .onTapGesture { - if chatModel.users.filter({ u in u.user.activeUser || !u.user.hidden }).count > 1 { - withAnimation { - userPickerVisible.toggle() - } - } else { - showSettings = true - } + userPickerShown = true } } @@ -211,20 +304,45 @@ struct ChatListView: View { .padding(.top, oneHandUI ? 8 : 0) .id("searchBar") } + if #available(iOS 16.0, *) { + ForEach(cs, id: \.viewId) { chat in + ChatListNavLink(chat: chat) + .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) + .padding(.trailing, -16) + .disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id)) + .listRowBackground(Color.clear) + } + .offset(x: -8) + } else { + ForEach(cs, id: \.viewId) { chat in + VStack(spacing: .zero) { + Divider() + .padding(.leading, 16) + ChatListNavLink(chat: chat) + .padding(.horizontal, 8) + .padding(.vertical, 6) + } + .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets()) + .background { theme.colors.background } // Hides default list selection colour + .disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id)) + } + } if !oneHandUICardShown { OneHandUICard() + .padding(.vertical, 6) .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) .listRowSeparator(.hidden) .listRowBackground(Color.clear) } - ForEach(cs, id: \.viewId) { chat in - ChatListNavLink(chat: chat) + if !addressCreationCardShown { + AddressCreationCard() + .padding(.vertical, 6) .scaleEffect(x: 1, y: oneHandUI ? -1 : 1, anchor: .center) - .padding(.trailing, -16) - .disabled(chatModel.chatRunning != true || chatModel.deletedChats.contains(chat.chatInfo.id)) + .listRowSeparator(.hidden) .listRowBackground(Color.clear) } - .offset(x: -8) } .listStyle(.plain) .onChange(of: chatModel.chatId) { currentChatId in @@ -252,7 +370,7 @@ struct ChatListView: View { } } - private func unreadBadge(_ text: Text? = Text(" "), size: CGFloat = 18) -> some View { + private func unreadBadge(size: CGFloat = 18) -> some View { Circle() .frame(width: size, height: size) .foregroundColor(theme.colors.primary) @@ -324,7 +442,7 @@ struct ChatListView: View { struct SubsStatusIndicator: View { @State private var subs: SMPServerSubs = SMPServerSubs.newSMPServerSubs @State private var hasSess: Bool = false - @State private var timer: Timer? = nil + @State private var task: Task? @State private var showServersSummary = false @AppStorage(DEFAULT_SHOW_SUBSCRIPTION_PERCENTAGE) private var showSubscriptionPercentage = false @@ -343,10 +461,10 @@ struct SubsStatusIndicator: View { } .disabled(ChatModel.shared.chatRunning != true) .onAppear { - startTimer() + startTask() } .onDisappear { - stopTimer() + stopTask() } .appSheet(isPresented: $showServersSummary) { ServersSummaryView() @@ -354,25 +472,28 @@ struct SubsStatusIndicator: View { } } - private func startTimer() { - timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in - if AppChatState.shared.value == .active { - getSubsTotal() + private func startTask() { + task = Task { + while !Task.isCancelled { + if AppChatState.shared.value == .active, ChatModel.shared.chatRunning == true { + do { + let (subs, hasSess) = try await getAgentSubsTotal() + await MainActor.run { + self.subs = subs + self.hasSess = hasSess + } + } catch let error { + logger.error("getSubsTotal error: \(responseError(error))") + } + } + try? await Task.sleep(nanoseconds: 1_000_000_000) // Sleep for 1 second } } } - func stopTimer() { - timer?.invalidate() - timer = nil - } - - private func getSubsTotal() { - do { - (subs, hasSess) = try getAgentSubsTotal() - } catch let error { - logger.error("getSubsTotal error: \(responseError(error))") - } + func stopTask() { + task?.cancel() + task = nil } } @@ -496,27 +617,29 @@ func chatStoppedIcon() -> some View { } struct ChatListView_Previews: PreviewProvider { + @State static var userPickerSheet: UserPickerSheet? = .none + static var previews: some View { let chatModel = ChatModel() - chatModel.chats = [ - Chat( + chatModel.updateChats([ + ChatData( chatInfo: ChatInfo.sampleData.direct, chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello")] ), - Chat( + ChatData( chatInfo: ChatInfo.sampleData.group, chatItems: [ChatItem.getSample(1, .directSnd, .now, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")] ), - Chat( + ChatData( chatInfo: ChatInfo.sampleData.contactRequest, chatItems: [] ) - ] + ]) return Group { - ChatListView(showSettings: Binding.constant(false)) + ChatListView(activeUserPickerSheet: $userPickerSheet) .environmentObject(chatModel) - ChatListView(showSettings: Binding.constant(false)) + ChatListView(activeUserPickerSheet: $userPickerSheet) .environmentObject(ChatModel()) } } diff --git a/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift b/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift index 9e6d3005b6..13701a40a2 100644 --- a/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatPreviewView.swift @@ -35,11 +35,16 @@ struct ChatPreviewView: View { } .padding(.leading, 4) + let chatTs = if let cItem { + cItem.meta.itemTs + } else { + chat.chatInfo.chatTs + } VStack(spacing: 0) { HStack(alignment: .top) { chatPreviewTitle() Spacer() - (cItem?.timestampText ?? formatTimestampText(chat.chatInfo.chatTs)) + (formatTimestampText(chatTs)) .font(.subheadline) .frame(minWidth: 60, alignment: .trailing) .foregroundColor(theme.colors.secondary) @@ -167,7 +172,7 @@ struct ChatPreviewView: View { } private var verifiedIcon: Text { - (Text(Image(systemName: "checkmark.shield")) + Text(" ")) + (Text(Image(systemName: "checkmark.shield")) + textSpace) .foregroundColor(theme.colors.secondary) .baselineOffset(1) .kerning(-2) @@ -227,12 +232,12 @@ struct ChatPreviewView: View { + messageText(msg, parseSimpleXMarkdown(msg), nil, preview: true, showSecrets: false, secondaryColor: theme.colors.secondary) func image(_ s: String, color: Color = Color(uiColor: .tertiaryLabel)) -> Text { - Text(Image(systemName: s)).foregroundColor(color) + Text(" ") + Text(Image(systemName: s)).foregroundColor(color) + textSpace } func attachment() -> Text { switch draft.preview { - case let .filePreview(fileName, _): return image("doc.fill") + Text(fileName) + Text(" ") + case let .filePreview(fileName, _): return image("doc.fill") + Text(fileName) + textSpace case .mediaPreviews: return image("photo") case let .voicePreview(_, duration): return image("play.fill") + Text(durationText(duration)) default: return Text("") @@ -302,7 +307,7 @@ struct ChatPreviewView: View { case let .link(_, preview): smallContentPreview(size: dynamicMediaSize) { ZStack(alignment: .topTrailing) { - Image(uiImage: UIImage(base64Encoded: preview.image) ?? UIImage(systemName: "arrow.up.right")!) + Image(uiImage: imageFromBase64(preview.image) ?? UIImage(systemName: "arrow.up.right")!) .resizable() .aspectRatio(contentMode: .fill) .frame(width: dynamicMediaSize, height: dynamicMediaSize) @@ -323,13 +328,13 @@ struct ChatPreviewView: View { } case let .image(_, image): smallContentPreview(size: dynamicMediaSize) { - CIImageView(chatItem: ci, preview: UIImage(base64Encoded: image), maxWidth: dynamicMediaSize, smallView: true, showFullScreenImage: $showFullscreenGallery) - .environmentObject(ReverseListScrollModel()) + CIImageView(chatItem: ci, preview: imageFromBase64(image), maxWidth: dynamicMediaSize, smallView: true, showFullScreenImage: $showFullscreenGallery) + .environmentObject(ReverseListScrollModel()) } case let .video(_,image, duration): smallContentPreview(size: dynamicMediaSize) { - CIVideoView(chatItem: ci, preview: UIImage(base64Encoded: image), duration: duration, maxWidth: dynamicMediaSize, videoWidth: nil, smallView: true, showFullscreenPlayer: $showFullscreenGallery) - .environmentObject(ReverseListScrollModel()) + CIVideoView(chatItem: ci, preview: imageFromBase64(image), duration: duration, maxWidth: dynamicMediaSize, videoWidth: nil, smallView: true, showFullscreenPlayer: $showFullscreenGallery) + .environmentObject(ReverseListScrollModel()) } case let .voice(_, duration): smallContentPreviewVoice(size: dynamicMediaSize) { @@ -362,11 +367,11 @@ struct ChatPreviewView: View { case .sndErrorAuth, .sndError: return Text(Image(systemName: "multiply")) .font(.caption) - .foregroundColor(.red) + Text(" ") + .foregroundColor(.red) + textSpace case .sndWarning: return Text(Image(systemName: "exclamationmark.triangle.fill")) .font(.caption) - .foregroundColor(.orange) + Text(" ") + .foregroundColor(.orange) + textSpace default: return Text("") } } diff --git a/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift b/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift index 3c7bf97af9..f5156d86b8 100644 --- a/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift +++ b/apps/ios/Shared/Views/ChatList/ContactConnectionView.swift @@ -16,7 +16,6 @@ struct ContactConnectionView: View { @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize @State private var localAlias = "" @FocusState private var aliasTextFieldFocused: Bool - @State private var showContactConnectionInfo = false var body: some View { if case let .contactConnection(conn) = chat.chatInfo { @@ -32,7 +31,6 @@ struct ContactConnectionView: View { .scaledToFill() .frame(width: 48, height: 48) .foregroundColor(Color(uiColor: .tertiarySystemGroupedBackground).asAnotherColorFromSecondaryVariant(theme)) - .onTapGesture { showContactConnectionInfo = true } } .frame(width: 63, height: 63) .padding(.leading, 4) @@ -72,9 +70,6 @@ struct ContactConnectionView: View { Spacer() } .frame(maxHeight: .infinity) - .appSheet(isPresented: $showContactConnectionInfo) { - ContactConnectionInfo(contactConnection: contactConnection) - } } } } diff --git a/apps/ios/Shared/Views/ChatList/OneHandUICard.swift b/apps/ios/Shared/Views/ChatList/OneHandUICard.swift index 636d165114..059f24cc82 100644 --- a/apps/ios/Shared/Views/ChatList/OneHandUICard.swift +++ b/apps/ios/Shared/Views/ChatList/OneHandUICard.swift @@ -32,7 +32,6 @@ struct OneHandUICard: View { .background(theme.appColors.sentMessage) .cornerRadius(12) .frame(height: dynamicSize(userFont).rowHeight) - .padding(.vertical, 12) .alert(isPresented: $showOneHandUIAlert) { Alert( title: Text("Reachable chat toolbar"), diff --git a/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift b/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift index 477a78e36d..aa802c1af9 100644 --- a/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift +++ b/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift @@ -407,12 +407,18 @@ struct ServersSummaryView: View { struct SubscriptionStatusIndicatorView: View { @EnvironmentObject var m: ChatModel + @EnvironmentObject var theme: AppTheme var subs: SMPServerSubs var hasSess: Bool var body: some View { - let onionHosts = networkUseOnionHostsGroupDefault.get() - let (color, variableValue, opacity, _) = subscriptionStatusColorAndPercentage(m.networkInfo.online, onionHosts, subs, hasSess) + let (color, variableValue, opacity, _) = subscriptionStatusColorAndPercentage( + online: m.networkInfo.online, + usesProxy: networkUseOnionHostsGroupDefault.get() != .no || groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) != nil, + subs: subs, + hasSess: hasSess, + primaryColor: theme.colors.primary + ) if #available(iOS 16.0, *) { Image(systemName: "dot.radiowaves.up.forward", variableValue: variableValue) .foregroundColor(color) @@ -425,26 +431,32 @@ struct SubscriptionStatusIndicatorView: View { struct SubscriptionStatusPercentageView: View { @EnvironmentObject var m: ChatModel + @EnvironmentObject var theme: AppTheme var subs: SMPServerSubs var hasSess: Bool var body: some View { - let onionHosts = networkUseOnionHostsGroupDefault.get() - let (_, _, _, statusPercent) = subscriptionStatusColorAndPercentage(m.networkInfo.online, onionHosts, subs, hasSess) + let (_, _, _, statusPercent) = subscriptionStatusColorAndPercentage( + online: m.networkInfo.online, + usesProxy: networkUseOnionHostsGroupDefault.get() != .no || groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) != nil, + subs: subs, + hasSess: hasSess, + primaryColor: theme.colors.primary + ) Text(verbatim: "\(Int(floor(statusPercent * 100)))%") .foregroundColor(.secondary) .font(.caption) } } -func subscriptionStatusColorAndPercentage(_ online: Bool, _ onionHosts: OnionHosts, _ subs: SMPServerSubs, _ hasSess: Bool) -> (Color, Double, Double, Double) { +func subscriptionStatusColorAndPercentage(online: Bool, usesProxy: Bool, subs: SMPServerSubs, hasSess: Bool, primaryColor: Color) -> (Color, Double, Double, Double) { func roundedToQuarter(_ n: Double) -> Double { n >= 1 ? 1 : n <= 0 ? 0 : (n * 4).rounded() / 4 } - let activeColor: Color = onionHosts == .require ? .indigo : .accentColor + let activeColor: Color = usesProxy ? .indigo : primaryColor let noConnColorAndPercent: (Color, Double, Double, Double) = (Color(uiColor: .tertiaryLabel), 1, 1, 0) let activeSubsRounded = roundedToQuarter(subs.shareOfActive) @@ -479,15 +491,6 @@ struct SMPServerSummaryView: View { Section("Server address") { Text(summary.smpServer) .textSelection(.enabled) - if summary.known == true { - NavigationLink { - ProtocolServersView(serverProtocol: .smp) - .navigationTitle("Your SMP servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("Open server settings") - } - } } if let stats = summary.stats { @@ -584,7 +587,7 @@ struct SMPStatsView: View { } header: { Text("Statistics") } footer: { - Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is private to your device.") + Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is kept private on your device.") } } } @@ -667,15 +670,6 @@ struct XFTPServerSummaryView: View { Section("Server address") { Text(summary.xftpServer) .textSelection(.enabled) - if summary.known == true { - NavigationLink { - ProtocolServersView(serverProtocol: .xftp) - .navigationTitle("Your XFTP servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("Open server settings") - } - } } if let stats = summary.stats { @@ -709,7 +703,7 @@ struct XFTPStatsView: View { } header: { Text("Statistics") } footer: { - Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is private to your device.") + Text("Starting from \(localTimestamp(statsStartedAt)).") + Text("\n") + Text("All data is kept private on your device.") } } } diff --git a/apps/ios/Shared/Views/ChatList/UserPicker.swift b/apps/ios/Shared/Views/ChatList/UserPicker.swift index eeb7bf14f4..dbe10ad997 100644 --- a/apps/ios/Shared/Views/ChatList/UserPicker.swift +++ b/apps/ios/Shared/Views/ChatList/UserPicker.swift @@ -8,176 +8,281 @@ import SimpleXChat struct UserPicker: View { @EnvironmentObject var m: ChatModel - @Environment(\.scenePhase) var scenePhase @EnvironmentObject var theme: AppTheme - @Binding var showSettings: Bool - @Binding var showConnectDesktop: Bool - @Binding var userPickerVisible: Bool - @State var scrollViewContentSize: CGSize = .zero - @State var disableScrolling: Bool = true - private let menuButtonHeight: CGFloat = 68 - @State var chatViewNameWidth: CGFloat = 0 + @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize + @Environment(\.scenePhase) private var scenePhase: ScenePhase + @Environment(\.colorScheme) private var colorScheme: ColorScheme + @Binding var userPickerShown: Bool + @Binding var activeSheet: UserPickerSheet? + @State private var currentUser: Int64? + @State private var switchingProfile = false + @State private var frameWidth: CGFloat = 0 + @State private var resetScroll = ResetScrollAction() + // Inset grouped list dimensions + private let imageSize: CGFloat = 44 + private let rowPadding: CGFloat = 16 + private let rowVerticalPadding: CGFloat = 11 + private let sectionSpacing: CGFloat = 35 + private var sectionHorizontalPadding: CGFloat { frameWidth > 375 ? 20 : 16 } + private let sectionShape = RoundedRectangle(cornerRadius: 10, style: .continuous) var body: some View { - VStack { - Spacer().frame(height: 1) + let otherUsers: [UserInfo] = m.users + .filter { u in !u.user.hidden && u.user.userId != m.currentUser?.userId } + .sorted(using: KeyPathComparator(\.user.activeOrder, order: .reverse)) + let sectionWidth = max(frameWidth - sectionHorizontalPadding * 2, 0) + let currentUserWidth = max(frameWidth - sectionHorizontalPadding - rowPadding * 2 - 14 - imageSize, 0) + let stopped = m.chatRunning != true + VStack(spacing: sectionSpacing) { + if let user = m.currentUser { + StickyScrollView(resetScroll: $resetScroll) { + HStack(spacing: rowPadding) { + HStack { + ProfileImage(imageStr: user.image, size: imageSize, color: Color(uiColor: .tertiarySystemGroupedBackground)) + .padding(.trailing, 6) + profileName(user).lineLimit(1) + } + .padding(rowPadding) + .frame(width: otherUsers.isEmpty ? sectionWidth : currentUserWidth, alignment: .leading) + .modifier(ListRow { activeSheet = .currentProfile }) + .clipShape(sectionShape) + .disabled(stopped) + .opacity(stopped ? 0.4 : 1) + ForEach(otherUsers) { u in + userView(u, size: imageSize) + .frame(maxWidth: sectionWidth * 0.618) + .fixedSize() + .disabled(stopped) + .opacity(stopped ? 0.4 : 1) + } + } + .padding(.horizontal, sectionHorizontalPadding) + } + .frame(height: 2 * rowPadding + imageSize) + .padding(.top, sectionSpacing) + .overlay(DetermineWidth()) + .onPreferenceChange(DetermineWidth.Key.self) { frameWidth = $0 } + } VStack(spacing: 0) { - ScrollView { - ScrollViewReader { sp in - let users = m.users - .filter({ u in u.user.activeUser || !u.user.hidden }) - .sorted { u, _ in u.user.activeUser } - VStack(spacing: 0) { - ForEach(users) { u in - userView(u) - Divider() - if u.user.activeUser { Divider() } + openSheetOnTap("qrcode", title: m.userAddress == nil ? "Create SimpleX address" : "Your SimpleX address", sheet: .address, disabled: stopped) + openSheetOnTap("switch.2", title: "Chat preferences", sheet: .chatPreferences, disabled: stopped) + openSheetOnTap("person.crop.rectangle.stack", title: "Your chat profiles", sheet: .chatProfiles, disabled: stopped) + openSheetOnTap("desktopcomputer", title: "Use from desktop", sheet: .useFromDesktop, disabled: stopped) + ZStack(alignment: .trailing) { + openSheetOnTap("gearshape", title: "Settings", sheet: .settings, showDivider: false) + Image(systemName: colorScheme == .light ? "sun.max" : "moon.fill") + .resizable() + .scaledToFit() + .symbolRenderingMode(.monochrome) + .foregroundColor(theme.colors.secondary) + .frame(maxWidth: 20, maxHeight: .infinity) + .padding(.horizontal, rowPadding) + .background(Color(.systemBackground).opacity(0.01)) + .onTapGesture { + if (colorScheme == .light) { + ThemeManager.applyTheme(systemDarkThemeDefault.get()) + } else { + ThemeManager.applyTheme(DefaultTheme.LIGHT.themeName) } } - .overlay { - GeometryReader { geo -> Color in - DispatchQueue.main.async { - scrollViewContentSize = geo.size - let scenes = UIApplication.shared.connectedScenes - if let windowScene = scenes.first as? UIWindowScene { - let layoutFrame = windowScene.windows[0].safeAreaLayoutGuide.layoutFrame - disableScrolling = scrollViewContentSize.height + menuButtonHeight + 10 < layoutFrame.height - } - } - return Color.clear - } + .onLongPressGesture { + ThemeManager.applyTheme(DefaultTheme.SYSTEM_THEME_NAME) } - .onChange(of: userPickerVisible) { visible in - if visible, let u = users.first { - sp.scrollTo(u.id) - } - } - } - } - .simultaneousGesture(DragGesture(minimumDistance: disableScrolling ? 0 : 10000000)) - .frame(maxHeight: scrollViewContentSize.height) - - menuButton("Use from desktop", icon: "desktopcomputer") { - showConnectDesktop = true - withAnimation { - userPickerVisible.toggle() - } - } - Divider() - menuButton("Settings", icon: "gearshape") { - showSettings = true - withAnimation { - userPickerVisible.toggle() - } } } + .clipShape(sectionShape) + .padding(.horizontal, sectionHorizontalPadding) + .padding(.bottom, sectionSpacing) } - .clipShape(RoundedRectangle(cornerRadius: 16)) - .background( - Rectangle() - .fill(theme.colors.surface) - .cornerRadius(16) - .shadow(color: .black.opacity(0.12), radius: 24, x: 0, y: 0) - ) - .onPreferenceChange(DetermineWidth.Key.self) { chatViewNameWidth = $0 } - .frame(maxWidth: chatViewNameWidth > 0 ? min(300, chatViewNameWidth + 130) : 300) - .padding(8) - .opacity(userPickerVisible ? 1.0 : 0.0) .onAppear { - do { - // This check prevents the call of listUsers after the app is suspended, and the database is closed. - if case .active = scenePhase { - m.users = try listUsers() - } - } catch let error { - logger.error("Error loading users \(responseError(error))") - } - } - } - - private func userView(_ u: UserInfo) -> some View { - let user = u.user - return Button(action: { - if user.activeUser { - showSettings = true - withAnimation { - userPickerVisible.toggle() - } - } else { + // This check prevents the call of listUsers after the app is suspended, and the database is closed. + if case .active = scenePhase { + currentUser = m.currentUser?.userId Task { do { - try await changeActiveUserAsync_(user.userId, viewPwd: nil) - await MainActor.run { userPickerVisible = false } - } catch { + let users = try await listUsersAsync() await MainActor.run { - AlertManager.shared.showAlertMsg( - title: "Error switching profile!", - message: "Error: \(responseError(error))" - ) + m.users = users + currentUser = m.currentUser?.userId } + } catch { + logger.error("Error loading users \(responseError(error))") } } } - }, label: { - HStack(spacing: 0) { - ProfileImage(imageStr: user.image, size: 44, color: Color(uiColor: .tertiarySystemFill)) - .padding(.trailing, 12) - Text(user.chatViewName) - .fontWeight(user.activeUser ? .medium : .regular) - .foregroundColor(theme.colors.onBackground) - .overlay(DetermineWidth()) - Spacer() - if user.activeUser { - Image(systemName: "checkmark") - } else if u.unreadCount > 0 { - unreadCounter(u.unreadCount, color: user.showNtfs ? theme.colors.primary : theme.colors.secondary) - } else if !user.showNtfs { - Image(systemName: "speaker.slash") + } + .onChange(of: userPickerShown) { + if !$0 { resetScroll() } + } + .modifier(ThemedBackground(grouped: true)) + .disabled(switchingProfile) + } + + private func userView(_ u: UserInfo, size: CGFloat) -> some View { + HStack { + ZStack(alignment: .topTrailing) { + ProfileImage(imageStr: u.user.image, size: size, color: Color(uiColor: .tertiarySystemGroupedBackground)) + if (u.unreadCount > 0) { + UnreadBadge(userInfo: u).offset(x: 4, y: -4) } } - .padding(.trailing) - .padding([.leading, .vertical], 12) - }) - .buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill))) - } - - private func menuButton(_ title: LocalizedStringKey, icon: String, action: @escaping () -> Void) -> some View { - Button(action: action) { - HStack(spacing: 0) { - Text(title) - .overlay(DetermineWidth()) - Spacer() - Image(systemName: icon) - .symbolRenderingMode(.monochrome) - .foregroundColor(theme.colors.secondary) - } - .padding(.horizontal) - .padding(.vertical, 22) - .frame(height: menuButtonHeight) + .padding(.trailing, 6) + Text(u.user.displayName).font(.title2).lineLimit(1) + } + .padding(rowPadding) + .modifier(ListRow { + switchingProfile = true + Task { + do { + try await changeActiveUserAsync_(u.user.userId, viewPwd: nil) + await MainActor.run { + switchingProfile = false + userPickerShown = false + } + } catch { + await MainActor.run { + switchingProfile = false + showAlert( + NSLocalizedString("Error switching profile!", comment: "alertTitle"), + message: String.localizedStringWithFormat(NSLocalizedString("Error: %@", comment: "alert message"), responseError(error)) + ) + } + } + } + }) + .clipShape(sectionShape) + } + + private func openSheetOnTap(_ icon: String, title: LocalizedStringKey, sheet: UserPickerSheet, showDivider: Bool = true, disabled: Bool = false) -> some View { + ZStack(alignment: .bottom) { + settingsRow(icon, color: theme.colors.secondary) { + Text(title).foregroundColor(.primary).opacity(disabled ? 0.4 : 1) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, rowPadding) + .padding(.vertical, rowVerticalPadding) + .modifier(ListRow { activeSheet = sheet }) + .disabled(disabled) + if showDivider { + Divider().padding(.leading, 52) + } } - .buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill))) } } -private func unreadCounter(_ unread: Int, color: Color) -> some View { - unreadCountText(unread) - .font(.caption) - .foregroundColor(.white) - .padding(.horizontal, 4) - .frame(minWidth: 18, minHeight: 18) - .background(color) - .cornerRadius(10) +struct UnreadBadge: View { + var userInfo: UserInfo + @EnvironmentObject var theme: AppTheme + @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize + + var body: some View { + let size = dynamicSize(userFont).chatInfoSize + unreadCountText(userInfo.unreadCount) + .font(userFont <= .xxxLarge ? .caption : .caption2) + .foregroundColor(.white) + .padding(.horizontal, dynamicSize(userFont).unreadPadding) + .frame(minWidth: size, minHeight: size) + .background(userInfo.user.showNtfs ? theme.colors.primary : theme.colors.secondary) + .cornerRadius(dynamicSize(userFont).unreadCorner) + } } +struct ListRow: ViewModifier { + @Environment(\.colorScheme) private var colorScheme: ColorScheme + @State private var touchDown = false + let action: () -> Void + + func body(content: Content) -> some View { + ZStack { + elevatedSecondarySystemGroupedBackground + Color(.systemGray4).opacity(touchDown ? 1 : 0) + content + TouchOverlay(touchDown: $touchDown, action: action) + } + } + + var elevatedSecondarySystemGroupedBackground: Color { + switch colorScheme { + case .dark: Color(0xFF2C2C2E) + default: Color(0xFFFFFFFF) + } + } + + struct TouchOverlay: UIViewRepresentable { + @Binding var touchDown: Bool + let action: () -> Void + + func makeUIView(context: Context) -> TouchView { + let touchView = TouchView() + let gesture = UILongPressGestureRecognizer( + target: touchView, + action: #selector(touchView.longPress(gesture:)) + ) + gesture.delegate = touchView + gesture.minimumPressDuration = 0 + touchView.addGestureRecognizer(gesture) + return touchView + } + + func updateUIView(_ touchView: TouchView, context: Context) { + touchView.representer = self + } + + class TouchView: UIView, UIGestureRecognizerDelegate { + var representer: TouchOverlay? + private var startLocation: CGPoint? + private var task: Task? + + @objc + func longPress(gesture: UILongPressGestureRecognizer) { + switch gesture.state { + case .began: + startLocation = gesture.location(in: nil) + task = Task { + do { + try await Task.sleep(nanoseconds: 200_000000) + await MainActor.run { representer?.touchDown = true } + } catch { } + } + case .ended: + if hitTest(gesture.location(in: self), with: nil) == self { + representer?.action() + } + task?.cancel() + representer?.touchDown = false + case .changed: + if let startLocation { + let location = gesture.location(in: nil) + let dx = location.x - startLocation.x + let dy = location.y - startLocation.y + if sqrt(pow(dx, 2) + pow(dy, 2)) > 10 { gesture.state = .failed } + } + case .cancelled, .failed: + task?.cancel() + representer?.touchDown = false + default: break + } + } + + func gestureRecognizer( + _: UIGestureRecognizer, + shouldRecognizeSimultaneouslyWith: UIGestureRecognizer + ) -> Bool { true } + } + } +} + + struct UserPicker_Previews: PreviewProvider { static var previews: some View { + @State var activeSheet: UserPickerSheet? + let m = ChatModel() m.users = [UserInfo.sampleData, UserInfo.sampleData] return UserPicker( - showSettings: Binding.constant(false), - showConnectDesktop: Binding.constant(false), - userPickerVisible: Binding.constant(true) + userPickerShown: .constant(true), + activeSheet: $activeSheet ) .environmentObject(m) } diff --git a/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift b/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift index 4b43610236..898a47cc86 100644 --- a/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift +++ b/apps/ios/Shared/Views/Contacts/ContactListNavLink.swift @@ -151,7 +151,7 @@ struct ContactListNavLink: View { } private var verifiedIcon: Text { - (Text(Image(systemName: "checkmark.shield")) + Text(" ")) + (Text(Image(systemName: "checkmark.shield")) + textSpace) .foregroundColor(.secondary) .baselineOffset(1) .kerning(-2) diff --git a/apps/ios/Shared/Views/Database/ChatArchiveView.swift b/apps/ios/Shared/Views/Database/ChatArchiveView.swift deleted file mode 100644 index 3ab4ac9a31..0000000000 --- a/apps/ios/Shared/Views/Database/ChatArchiveView.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// ChatArchiveView.swift -// SimpleXChat -// -// Created by Evgeny on 23/06/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -struct ChatArchiveView: View { - @EnvironmentObject var theme: AppTheme - var archiveName: String - @AppStorage(DEFAULT_CHAT_ARCHIVE_NAME) private var chatArchiveName: String? - @AppStorage(DEFAULT_CHAT_ARCHIVE_TIME) private var chatArchiveTime: Double = 0 - @State private var showDeleteAlert = false - - var body: some View { - let fileUrl = getDocumentsDirectory().appendingPathComponent(archiveName) - let fileTs = chatArchiveTimeDefault.get() - List { - Section { - settingsRow("square.and.arrow.up", color: theme.colors.secondary) { - Button { - showShareSheet(items: [fileUrl]) - } label: { - Text("Save archive") - } - } - settingsRow("trash", color: theme.colors.secondary) { - Button { - showDeleteAlert = true - } label: { - Text("Delete archive").foregroundColor(.red) - } - } - } header: { - Text("Chat archive") - .foregroundColor(theme.colors.secondary) - } footer: { - Text("Created on \(fileTs)") - .foregroundColor(theme.colors.secondary) - } - } - .alert(isPresented: $showDeleteAlert) { - Alert( - title: Text("Delete chat archive?"), - primaryButton: .destructive(Text("Delete")) { - do { - try FileManager.default.removeItem(atPath: fileUrl.path) - chatArchiveName = nil - chatArchiveTime = 0 - } catch let error { - logger.error("removeItem error \(String(describing: error))") - } - }, - secondaryButton: .cancel() - ) - } - } -} - -struct ChatArchiveView_Previews: PreviewProvider { - static var previews: some View { - ChatArchiveView(archiveName: "") - } -} diff --git a/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift b/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift index be167b92b9..3cd37e4930 100644 --- a/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift @@ -48,6 +48,8 @@ struct DatabaseEncryptionView: View { @State private var confirmNewKey = "" @State private var currentKeyShown = false + let stopChatRunBlockStartChat: (Binding, @escaping () async throws -> Bool) -> Void + var body: some View { ZStack { List { @@ -134,46 +136,61 @@ struct DatabaseEncryptionView: View { .onAppear { if initialRandomDBPassphrase { currentKey = kcDatabasePassword.get() ?? "" } } - .disabled(m.chatRunning != false) + .disabled(progressIndicator) .alert(item: $alert) { item in databaseEncryptionAlert(item) } } - private func encryptDatabase() { - progressIndicator = true - Task { - do { - encryptionStartedDefault.set(true) - encryptionStartedAtDefault.set(Date.now) - if !m.chatDbChanged { - try apiSaveAppSettings(settings: AppSettings.current.prepareForExport()) - } - try await apiStorageEncryption(currentKey: currentKey, newKey: newKey) - encryptionStartedDefault.set(false) - initialRandomDBPassphraseGroupDefault.set(false) - if migration { - storeDBPassphraseGroupDefault.set(useKeychain) - } - if useKeychain { - if kcDatabasePassword.set(newKey) { - await resetFormAfterEncryption(true) - await operationEnded(.databaseEncrypted) - } else { - await resetFormAfterEncryption() - await operationEnded(.error(title: "Keychain error", error: "Error saving passphrase to keychain")) - } - } else { - if migration { - removePassphraseFromKeyChain() - } - await resetFormAfterEncryption() + private func encryptDatabaseAsync() async -> Bool { + await MainActor.run { + progressIndicator = true + } + do { + encryptionStartedDefault.set(true) + encryptionStartedAtDefault.set(Date.now) + if !m.chatDbChanged { + try apiSaveAppSettings(settings: AppSettings.current.prepareForExport()) + } + try await apiStorageEncryption(currentKey: currentKey, newKey: newKey) + encryptionStartedDefault.set(false) + initialRandomDBPassphraseGroupDefault.set(false) + if migration { + storeDBPassphraseGroupDefault.set(useKeychain) + } + if useKeychain { + if kcDatabasePassword.set(newKey) { + await resetFormAfterEncryption(true) await operationEnded(.databaseEncrypted) - } - } catch let error { - if case .chatCmdError(_, .errorDatabase(.errorExport(.errorNotADatabase))) = error as? ChatResponse { - await operationEnded(.currentPassphraseError) } else { - await operationEnded(.error(title: "Error encrypting database", error: "\(responseError(error))")) + await resetFormAfterEncryption() + await operationEnded(.error(title: "Keychain error", error: "Error saving passphrase to keychain")) } + } else { + if migration { + removePassphraseFromKeyChain() + } + await resetFormAfterEncryption() + await operationEnded(.databaseEncrypted) + } + return true + } catch let error { + if case .chatCmdError(_, .errorDatabase(.errorExport(.errorNotADatabase))) = error as? ChatResponse { + await operationEnded(.currentPassphraseError) + } else { + await operationEnded(.error(title: "Error encrypting database", error: "\(responseError(error))")) + } + return false + } + } + + private func encryptDatabase() { + // it will try to stop and start the chat in case of: non-migration && successful encryption. In migration the chat will remain stopped + if migration { + Task { + await encryptDatabaseAsync() + } + } else { + stopChatRunBlockStartChat($progressIndicator) { + return await encryptDatabaseAsync() } } } @@ -371,6 +388,6 @@ func validKey(_ s: String) -> Bool { struct DatabaseEncryptionView_Previews: PreviewProvider { static var previews: some View { - DatabaseEncryptionView(useKeychain: Binding.constant(true), migration: false) + DatabaseEncryptionView(useKeychain: Binding.constant(true), migration: false, stopChatRunBlockStartChat: { _, _ in true }) } } diff --git a/apps/ios/Shared/Views/Database/DatabaseErrorView.swift b/apps/ios/Shared/Views/Database/DatabaseErrorView.swift index 9d71e2a788..6222a28fb4 100644 --- a/apps/ios/Shared/Views/Database/DatabaseErrorView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseErrorView.swift @@ -11,6 +11,7 @@ import SimpleXChat struct DatabaseErrorView: View { @EnvironmentObject var m: ChatModel + @EnvironmentObject var theme: AppTheme @State var status: DBMigrationResult @State private var dbKey = "" @State private var storedDBKey = kcDatabasePassword.get() @@ -28,23 +29,39 @@ struct DatabaseErrorView: View { } @ViewBuilder private func databaseErrorView() -> some View { - VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .center, spacing: 20) { switch status { case let .errorNotADatabase(dbFile): if useKeychain && storedDBKey != nil && storedDBKey != "" { titleText("Wrong database passphrase") Text("Database passphrase is different from saved in the keychain.") + .font(.callout) + .foregroundColor(theme.colors.secondary) + .multilineTextAlignment(.center) + .padding(.horizontal, 25) + databaseKeyField(onSubmit: saveAndRunChat) - saveAndOpenButton() - fileNameText(dbFile) + Spacer() + VStack(spacing: 10) { + saveAndOpenButton() + fileNameText(dbFile) + } } else { titleText("Encrypted database") Text("Database passphrase is required to open chat.") + .font(.callout) + .foregroundColor(theme.colors.secondary) + .multilineTextAlignment(.center) + .padding(.horizontal, 25) + .padding(.bottom, 5) + if useKeychain { databaseKeyField(onSubmit: saveAndRunChat) + Spacer() saveAndOpenButton() } else { databaseKeyField(onSubmit: { runChat() }) + Spacer() openChatButton() } } @@ -52,73 +69,105 @@ struct DatabaseErrorView: View { switch migrationError { case let .upgrade(upMigrations): titleText("Database upgrade") - Button("Upgrade and open chat") { runChat(confirmMigrations: .yesUp) } - fileNameText(dbFile) migrationsText(upMigrations.map(\.upName)) + Spacer() + VStack(spacing: 10) { + Button("Upgrade and open chat") { + runChat(confirmMigrations: .yesUp) + }.buttonStyle(OnboardingButtonStyle(isDisabled: false)) + fileNameText(dbFile) + } case let .downgrade(downMigrations): titleText("Database downgrade") - Text("Warning: you may lose some data!").bold() - Button("Downgrade and open chat") { runChat(confirmMigrations: .yesUpDown) } - fileNameText(dbFile) + Text("Warning: you may lose some data!") + .bold() + .padding(.horizontal, 25) + .multilineTextAlignment(.center) + migrationsText(downMigrations) + Spacer() + VStack(spacing: 10) { + Button("Downgrade and open chat") { + runChat(confirmMigrations: .yesUpDown) + }.buttonStyle(OnboardingButtonStyle(isDisabled: false)) + fileNameText(dbFile) + } case let .migrationError(mtrError): titleText("Incompatible database version") - fileNameText(dbFile) - Text("Error: ") + Text(mtrErrorDescription(mtrError)) + fileNameText(dbFile, font: .callout) + errorView(Text(mtrErrorDescription(mtrError))) } case let .errorSQL(dbFile, migrationSQLError): titleText("Database error") - fileNameText(dbFile) - Text("Error: \(migrationSQLError)") + fileNameText(dbFile, font: .callout) + errorView(Text("Error: \(migrationSQLError)")) case .errorKeychain: titleText("Keychain error") - Text("Cannot access keychain to save database password") + errorView(Text("Cannot access keychain to save database password")) case .invalidConfirmation: // this can only happen if incorrect parameter is passed - Text(String("Invalid migration confirmation")).font(.title) + titleText("Invalid migration confirmation") + errorView() + case let .unknown(json): titleText("Database error") - Text("Unknown database error: \(json)") + errorView(Text("Unknown database error: \(json)")) case .ok: EmptyView() } if showRestoreDbButton { - Spacer().frame(height: 10) + Spacer() Text("The attempt to change database passphrase was not completed.") + .multilineTextAlignment(.center) + .padding(.horizontal, 25) + .font(.footnote) + restoreDbButton() } } - .padding() + .padding(.horizontal, 25) + .padding(.top, 75) + .padding(.bottom, 25) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .onAppear() { showRestoreDbButton = shouldShowRestoreDbButton() } } - private func titleText(_ s: LocalizedStringKey) -> Text { - Text(s).font(.title) + private func titleText(_ s: LocalizedStringKey) -> some View { + Text(s).font(.largeTitle).bold().multilineTextAlignment(.center) } - private func fileNameText(_ f: String) -> Text { - Text("File: \((f as NSString).lastPathComponent)") + private func fileNameText(_ f: String, font: Font = .caption) -> Text { + Text("File: \((f as NSString).lastPathComponent)").font(font) } - private func migrationsText(_ ms: [String]) -> Text { - Text("Migrations: \(ms.joined(separator: ", "))") + private func migrationsText(_ ms: [String]) -> some View { + (Text("Migrations:").font(.subheadline) + Text(verbatim: "\n") + Text(ms.joined(separator: "\n")).font(.caption)) + .multilineTextAlignment(.center) + .padding(.horizontal, 25) } private func databaseKeyField(onSubmit: @escaping () -> Void) -> some View { PassphraseField(key: $dbKey, placeholder: "Enter passphrase…", valid: validKey(dbKey), onSubmit: onSubmit) + .padding(.vertical, 10) + .padding(.horizontal) + .background( + RoundedRectangle(cornerRadius: 10, style: .continuous) + .fill(Color(uiColor: .tertiarySystemFill)) + ) } private func saveAndOpenButton() -> some View { Button("Save passphrase and open chat") { saveAndRunChat() } + .buttonStyle(OnboardingButtonStyle(isDisabled: false)) } private func openChatButton() -> some View { Button("Open chat") { runChat() } + .buttonStyle(OnboardingButtonStyle(isDisabled: false)) } private func saveAndRunChat() { @@ -192,8 +241,9 @@ struct DatabaseErrorView: View { secondaryButton: .cancel() )) } label: { - Text("Restore database backup").foregroundColor(.red) + Text("Restore database backup") } + .buttonStyle(OnboardingButtonStyle(isDisabled: false)) } private func restoreDb() { @@ -208,6 +258,23 @@ struct DatabaseErrorView: View { )) } } + + private func errorView(_ s: Text? = nil) -> some View { + VStack(spacing: 35) { + Image(systemName: "exclamationmark.triangle.fill") + .resizable() + .frame(width: 50, height: 50) + .foregroundColor(.red) + + if let text = s { + text + .multilineTextAlignment(.center) + .font(.footnote) + } + } + .padding() + .frame(maxWidth: .infinity) + } } struct DatabaseErrorView_Previews: PreviewProvider { diff --git a/apps/ios/Shared/Views/Database/DatabaseView.swift b/apps/ios/Shared/Views/Database/DatabaseView.swift index 6b6d3796dc..4a367f7722 100644 --- a/apps/ios/Shared/Views/Database/DatabaseView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseView.swift @@ -44,8 +44,9 @@ enum DatabaseAlert: Identifiable { struct DatabaseView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme - @Binding var showSettings: Bool + let dismissSettingsSheet: DismissAction @State private var runChat = false + @State private var stoppingChat = false @State private var alert: DatabaseAlert? = nil @State private var showFileImporter = false @State private var importedArchivePath: URL? @@ -57,6 +58,8 @@ struct DatabaseView: View { @State private var useKeychain = storeDBPassphraseGroupDefault.get() @State private var appFilesCountAndSize: (Int, Int)? + @State private var showDatabaseEncryptionView = false + @State var chatItemTTL: ChatItemTTL @State private var currentChatItemTTL: ChatItemTTL = .none @@ -69,7 +72,20 @@ struct DatabaseView: View { } } + @ViewBuilder private func chatDatabaseView() -> some View { + NavigationLink(isActive: $showDatabaseEncryptionView) { + DatabaseEncryptionView(useKeychain: $useKeychain, migration: false, stopChatRunBlockStartChat: { progressIndicator, block in + stopChatRunBlockStartChat(false, progressIndicator, block) + }) + .navigationTitle("Database passphrase") + .modifier(ThemedBackground(grouped: true)) + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() + List { let stopped = m.chatRunning == false Section { @@ -101,9 +117,10 @@ struct DatabaseView: View { isOn: $runChat ) .onChange(of: runChat) { _ in - if (runChat) { - startChat() - } else { + if runChat { + DatabaseView.startChat($runChat, $progressIndicator) + } else if !stoppingChat { + stoppingChat = false alert = .stopChat } } @@ -123,7 +140,9 @@ struct DatabaseView: View { let color: Color = unencrypted ? .orange : theme.colors.secondary settingsRow(unencrypted ? "lock.open" : useKeychain ? "key" : "lock", color: color) { NavigationLink { - DatabaseEncryptionView(useKeychain: $useKeychain, migration: false) + DatabaseEncryptionView(useKeychain: $useKeychain, migration: false, stopChatRunBlockStartChat: { progressIndicator, block in + stopChatRunBlockStartChat(false, progressIndicator, block) + }) .navigationTitle("Database passphrase") .modifier(ThemedBackground(grouped: true)) } label: { @@ -133,9 +152,14 @@ struct DatabaseView: View { settingsRow("square.and.arrow.up", color: theme.colors.secondary) { Button("Export database") { if initialRandomDBPassphraseGroupDefault.get() && !unencrypted { - alert = .exportProhibited + showDatabaseEncryptionView = true + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + alert = .exportProhibited + } } else { - exportArchive() + stopChatRunBlockStartChat(stopped, $progressIndicator) { + await exportArchive() + } } } } @@ -144,20 +168,6 @@ struct DatabaseView: View { showFileImporter = true } } - if let archiveName = chatArchiveName { - let title: LocalizedStringKey = chatArchiveTimeDefault.get() < chatLastStartGroupDefault.get() - ? "Old database archive" - : "New database archive" - settingsRow("archivebox", color: theme.colors.secondary) { - NavigationLink { - ChatArchiveView(archiveName: archiveName) - .navigationTitle(title) - .modifier(ThemedBackground(grouped: true)) - } label: { - Text(title) - } - } - } settingsRow("trash.slash", color: theme.colors.secondary) { Button("Delete database", role: .destructive) { alert = .deleteChat @@ -167,14 +177,10 @@ struct DatabaseView: View { Text("Chat database") .foregroundColor(theme.colors.secondary) } footer: { - Text( - stopped - ? "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." - : "Stop chat to enable database actions" - ) + Text("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.") .foregroundColor(theme.colors.secondary) } - .disabled(!stopped) + .disabled(progressIndicator) if case .group = dbContainer, legacyDatabase { Section(header: Text("Old database").foregroundColor(theme.colors.secondary)) { @@ -190,7 +196,7 @@ struct DatabaseView: View { Button(m.users.count > 1 ? "Delete files for all chat profiles" : "Delete all files", role: .destructive) { alert = .deleteFilesAndMedia } - .disabled(!stopped || appFilesCountAndSize?.0 == 0) + .disabled(progressIndicator || appFilesCountAndSize?.0 == 0) } header: { Text("Files & media") .foregroundColor(theme.colors.secondary) @@ -255,7 +261,10 @@ struct DatabaseView: View { title: Text("Import chat database?"), message: Text("Your current chat database will be DELETED and REPLACED with the imported one.") + Text("This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost."), primaryButton: .destructive(Text("Import")) { - importArchive(fileURL) + stopChatRunBlockStartChat(m.chatRunning == false, $progressIndicator) { + _ = await DatabaseView.importArchive(fileURL, $progressIndicator, $alert) + return true + } }, secondaryButton: .cancel() ) @@ -263,19 +272,15 @@ struct DatabaseView: View { return Alert(title: Text("Error: no database file")) } case .archiveImported: - return Alert( - title: Text("Chat database imported"), - message: Text("Restart the app to use imported chat database") - ) + let (title, message) = archiveImportedAlertText() + return Alert(title: Text(title), message: Text(message)) case let .archiveImportedWithErrors(errs): - return Alert( - title: Text("Chat database imported"), - message: Text("Restart the app to use imported chat database") + Text(verbatim: "\n\n") + Text("Some non-fatal errors occurred during import:") + archiveErrorsText(errs) - ) + let (title, message) = archiveImportedWithErrorsAlertText(errs: errs) + return Alert(title: Text(title), message: Text(message)) case let .archiveExportedWithErrors(archivePath, errs): return Alert( title: Text("Chat database exported"), - message: Text("You may save the exported archive.") + Text(verbatim: "\n\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs), + message: Text("You may save the exported archive.") + Text(verbatim: "\n") + Text("Some file(s) were not exported:") + Text(archiveErrorsText(errs)), dismissButton: .default(Text("Continue")) { showShareSheet(items: [archivePath]) } @@ -285,15 +290,17 @@ struct DatabaseView: View { title: Text("Delete chat profile?"), message: Text("This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost."), primaryButton: .destructive(Text("Delete")) { - deleteChat() + let wasStopped = m.chatRunning == false + stopChatRunBlockStartChat(wasStopped, $progressIndicator) { + _ = await deleteChat() + return true + } }, secondaryButton: .cancel() ) case .chatDeleted: - return Alert( - title: Text("Chat database deleted"), - message: Text("Restart the app to create a new chat profile") - ) + let (title, message) = chatDeletedAlertText() + return Alert(title: Text(title), message: Text(message)) case .deleteLegacyDatabase: return Alert( title: Text("Delete old database?"), @@ -308,7 +315,10 @@ struct DatabaseView: View { title: Text("Delete files and media?"), message: Text("This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain."), primaryButton: .destructive(Text("Delete")) { - deleteFiles() + stopChatRunBlockStartChat(m.chatRunning == false, $progressIndicator) { + deleteFiles() + return true + } }, secondaryButton: .cancel() ) @@ -328,95 +338,180 @@ struct DatabaseView: View { } } - private func authStopChat() { + private func authStopChat(_ onStop: (() -> Void)? = nil) { if UserDefaults.standard.bool(forKey: DEFAULT_PERFORM_LA) { authenticate(reason: NSLocalizedString("Stop SimpleX", comment: "authentication reason")) { laResult in switch laResult { - case .success: stopChat() - case .unavailable: stopChat() + case .success: stopChat(onStop) + case .unavailable: stopChat(onStop) case .failed: withAnimation { runChat = true } } } } else { - stopChat() + stopChat(onStop) } } - private func stopChat() { + private func stopChat(_ onStop: (() -> Void)? = nil) { Task { do { try await stopChatAsync() + onStop?() } catch let error { await MainActor.run { runChat = true - alert = .error(title: "Error stopping chat", error: responseError(error)) + showAlert("Error stopping chat", message: responseError(error)) } } } } - private func exportArchive() { - progressIndicator = true - Task { - do { - let (archivePath, archiveErrors) = try await exportChatArchive() - if archiveErrors.isEmpty { - showShareSheet(items: [archivePath]) - await MainActor.run { progressIndicator = false } - } else { - await MainActor.run { - alert = .archiveExportedWithErrors(archivePath: archivePath, archiveErrors: archiveErrors) - progressIndicator = false + func stopChatRunBlockStartChat( + _ stopped: Bool, + _ progressIndicator: Binding, + _ block: @escaping () async throws -> Bool + ) { + // if the chat was running, the sequence is: stop chat, run block, start chat. + // Otherwise, just run block and do nothing - the toggle will be visible anyway and the user can start the chat or not + if stopped { + Task { + do { + _ = try await block() + } catch { + logger.error("Error while executing block: \(error)") + } + } + } else { + authStopChat { + stoppingChat = true + runChat = false + Task { + // if it throws, let's start chat again anyway + var canStart = false + do { + canStart = try await block() + } catch { + logger.error("Error executing block: \(error)") + canStart = true + } + if canStart { + await MainActor.run { + DatabaseView.startChat($runChat, $progressIndicator) + } } } + } + } + } + + static func startChat(_ runChat: Binding, _ progressIndicator: Binding) { + progressIndicator.wrappedValue = true + let m = ChatModel.shared + if m.chatDbChanged { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + resetChatCtrl() + do { + let hadDatabase = hasDatabase() + try initializeChat(start: true) + m.chatDbChanged = false + AppChatState.shared.set(.active) + if m.chatDbStatus != .ok || !hadDatabase { + // Hide current view and show `DatabaseErrorView` + dismissAllSheets(animated: true) + } + } catch let error { + fatalError("Error starting chat \(responseError(error))") + } + progressIndicator.wrappedValue = false + } + } else { + do { + _ = try apiStartChat() + runChat.wrappedValue = true + m.chatRunning = true + ChatReceiver.shared.start() + chatLastStartGroupDefault.set(Date.now) + AppChatState.shared.set(.active) } catch let error { + runChat.wrappedValue = false + showAlert(NSLocalizedString("Error starting chat", comment: ""), message: responseError(error)) + } + progressIndicator.wrappedValue = false + } + } + + private func exportArchive() async -> Bool { + await MainActor.run { + progressIndicator = true + } + do { + let (archivePath, archiveErrors) = try await exportChatArchive() + if archiveErrors.isEmpty { + showShareSheet(items: [archivePath]) + await MainActor.run { progressIndicator = false } + } else { await MainActor.run { - alert = .error(title: "Error exporting chat database", error: responseError(error)) + alert = .archiveExportedWithErrors(archivePath: archivePath, archiveErrors: archiveErrors) progressIndicator = false } } + } catch let error { + await MainActor.run { + alert = .error(title: "Error exporting chat database", error: responseError(error)) + progressIndicator = false + } } + return false } - private func importArchive(_ archivePath: URL) { + static func importArchive( + _ archivePath: URL, + _ progressIndicator: Binding, + _ alert: Binding + ) async -> Bool { if archivePath.startAccessingSecurityScopedResource() { - progressIndicator = true - Task { - do { - try await apiDeleteStorage() - try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true) - do { - let config = ArchiveConfig(archivePath: archivePath.path) - let archiveErrors = try await apiImportArchive(config: config) - _ = kcDatabasePassword.remove() - if archiveErrors.isEmpty { - await operationEnded(.archiveImported) - } else { - await operationEnded(.archiveImportedWithErrors(archiveErrors: archiveErrors)) - } - } catch let error { - await operationEnded(.error(title: "Error importing chat database", error: responseError(error))) - } - } catch let error { - await operationEnded(.error(title: "Error deleting chat database", error: responseError(error))) - } - archivePath.stopAccessingSecurityScopedResource() + await MainActor.run { + progressIndicator.wrappedValue = true } + do { + try await apiDeleteStorage() + try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true) + do { + let config = ArchiveConfig(archivePath: archivePath.path) + let archiveErrors = try await apiImportArchive(config: config) + shouldImportAppSettingsDefault.set(true) + _ = kcDatabasePassword.remove() + if archiveErrors.isEmpty { + await operationEnded(.archiveImported, progressIndicator, alert) + } else { + await operationEnded(.archiveImportedWithErrors(archiveErrors: archiveErrors), progressIndicator, alert) + } + return true + } catch let error { + await operationEnded(.error(title: "Error importing chat database", error: responseError(error)), progressIndicator, alert) + } + } catch let error { + await operationEnded(.error(title: "Error deleting chat database", error: responseError(error)), progressIndicator, alert) + } + archivePath.stopAccessingSecurityScopedResource() } else { - alert = .error(title: "Error accessing database file") + showAlert("Error accessing database file") } + return false } - private func deleteChat() { - progressIndicator = true - Task { - do { - try await deleteChatAsync() - await operationEnded(.chatDeleted) - appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory()) - } catch let error { - await operationEnded(.error(title: "Error deleting database", error: responseError(error))) - } + private func deleteChat() async -> Bool { + await MainActor.run { + progressIndicator = true + } + do { + try await deleteChatAsync() + appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory()) + await DatabaseView.operationEnded(.chatDeleted, $progressIndicator, $alert) + return true + } catch let error { + await DatabaseView.operationEnded(.error(title: "Error deleting database", error: responseError(error)), $progressIndicator, $alert) + return false } } @@ -428,39 +523,28 @@ struct DatabaseView: View { } } - private func operationEnded(_ dbAlert: DatabaseAlert) async { + private static func operationEnded(_ dbAlert: DatabaseAlert, _ progressIndicator: Binding, _ alert: Binding) async { await MainActor.run { + let m = ChatModel.shared m.chatDbChanged = true m.chatInitialized = false - progressIndicator = false - alert = dbAlert + progressIndicator.wrappedValue = false } - } - - private func startChat() { - if m.chatDbChanged { - showSettings = false - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - resetChatCtrl() - do { - try initializeChat(start: true) - m.chatDbChanged = false - AppChatState.shared.set(.active) - } catch let error { - fatalError("Error starting chat \(responseError(error))") - } - } - } else { - do { - _ = try apiStartChat() - runChat = true - m.chatRunning = true - ChatReceiver.shared.start() - chatLastStartGroupDefault.set(Date.now) - AppChatState.shared.set(.active) - } catch let error { - runChat = false - alert = .error(title: "Error starting chat", error: responseError(error)) + await withCheckedContinuation { cont in + let okAlertActionWaiting = UIAlertAction(title: NSLocalizedString("Ok", comment: "alert button"), style: .default, handler: { _ in cont.resume() }) + // show these alerts globally so they are visible when all sheets will be hidden + if case .archiveImported = dbAlert { + let (title, message) = archiveImportedAlertText() + showAlert(title, message: message, actions: { [okAlertActionWaiting] }) + } else if case .archiveImportedWithErrors(let errs) = dbAlert { + let (title, message) = archiveImportedWithErrorsAlertText(errs: errs) + showAlert(title, message: message, actions: { [okAlertActionWaiting] }) + } else if case .chatDeleted = dbAlert { + let (title, message) = chatDeletedAlertText() + showAlert(title, message: message, actions: { [okAlertActionWaiting] }) + } else { + alert.wrappedValue = dbAlert + cont.resume() } } } @@ -491,7 +575,7 @@ struct DatabaseView: View { appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory()) do { let chats = try apiGetChats() - m.updateChats(with: chats) + m.updateChats(chats) } catch let error { logger.error("apiGetChats: cannot update chats \(responseError(error))") } @@ -503,8 +587,28 @@ struct DatabaseView: View { } } -func archiveErrorsText(_ errs: [ArchiveError]) -> Text { - return Text("\n" + errs.map(showArchiveError).joined(separator: "\n")) +private func archiveImportedAlertText() -> (String, String) { + ( + NSLocalizedString("Chat database imported", comment: ""), + NSLocalizedString("Restart the app to use imported chat database", comment: "") + ) +} +private func archiveImportedWithErrorsAlertText(errs: [ArchiveError]) -> (String, String) { + ( + NSLocalizedString("Chat database imported", comment: ""), + NSLocalizedString("Restart the app to use imported chat database", comment: "") + "\n" + NSLocalizedString("Some non-fatal errors occurred during import:", comment: "") + archiveErrorsText(errs) + ) +} + +private func chatDeletedAlertText() -> (String, String) { + ( + NSLocalizedString("Chat database deleted", comment: ""), + NSLocalizedString("Restart the app to create a new chat profile", comment: "") + ) +} + +func archiveErrorsText(_ errs: [ArchiveError]) -> String { + return "\n" + errs.map(showArchiveError).joined(separator: "\n") func showArchiveError(_ err: ArchiveError) -> String { switch err { @@ -533,7 +637,9 @@ func deleteChatAsync() async throws { } struct DatabaseView_Previews: PreviewProvider { + @Environment(\.dismiss) static var mockDismiss + static var previews: some View { - DatabaseView(showSettings: Binding.constant(false), chatItemTTL: .none) + DatabaseView(dismissSettingsSheet: mockDismiss, chatItemTTL: .none) } } diff --git a/apps/ios/Shared/Views/Database/MigrateToAppGroupView.swift b/apps/ios/Shared/Views/Database/MigrateToAppGroupView.swift index e79f24c6d9..79c0a42ae0 100644 --- a/apps/ios/Shared/Views/Database/MigrateToAppGroupView.swift +++ b/apps/ios/Shared/Views/Database/MigrateToAppGroupView.swift @@ -117,7 +117,7 @@ struct MigrateToAppGroupView: View { setV3DBMigration(.migration_error) migrationError = "Error starting chat: \(responseError(error))" } - deleteOldArchive() + deleteOldChatArchive() } label: { Text("Start chat") .font(.title) @@ -235,14 +235,16 @@ func exportChatArchive(_ storagePath: URL? = nil) async throws -> (URL, [Archive try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true) let errs = try await apiExportArchive(config: config) if storagePath == nil { - deleteOldArchive() + deleteOldChatArchive() UserDefaults.standard.set(archiveName, forKey: DEFAULT_CHAT_ARCHIVE_NAME) chatArchiveTimeDefault.set(archiveTime) } return (archivePath, errs) } -func deleteOldArchive() { +/// Deprecated. Remove in the end of 2025. All unused archives should be deleted for the most users til then. +/// Remove DEFAULT_CHAT_ARCHIVE_NAME and DEFAULT_CHAT_ARCHIVE_TIME as well +func deleteOldChatArchive() { let d = UserDefaults.standard if let archiveName = d.string(forKey: DEFAULT_CHAT_ARCHIVE_NAME) { do { diff --git a/apps/ios/Shared/Views/Helpers/AppSheet.swift b/apps/ios/Shared/Views/Helpers/AppSheet.swift index 0ade1c0d8e..1e334367e8 100644 --- a/apps/ios/Shared/Views/Helpers/AppSheet.swift +++ b/apps/ios/Shared/Views/Helpers/AppSheet.swift @@ -11,6 +11,12 @@ import SwiftUI class AppSheetState: ObservableObject { static let shared = AppSheetState() @Published var scenePhaseActive: Bool = false + + func redactionReasons(_ protectScreen: Bool) -> RedactionReasons { + !protectScreen || scenePhaseActive + ? RedactionReasons() + : RedactionReasons.placeholder + } } private struct PrivacySensitive: ViewModifier { @@ -19,11 +25,7 @@ private struct PrivacySensitive: ViewModifier { @ObservedObject var appSheetState: AppSheetState = AppSheetState.shared func body(content: Content) -> some View { - if !protectScreen { - content - } else { - content.privacySensitive(!appSheetState.scenePhaseActive).redacted(reason: .privacy) - } + content.redacted(reason: appSheetState.redactionReasons(protectScreen)) } } diff --git a/apps/ios/Shared/Views/Helpers/ChatItemClipShape.swift b/apps/ios/Shared/Views/Helpers/ChatItemClipShape.swift index 477dc567eb..9aa6ac86cf 100644 --- a/apps/ios/Shared/Views/Helpers/ChatItemClipShape.swift +++ b/apps/ios/Shared/Views/Helpers/ChatItemClipShape.swift @@ -14,50 +14,55 @@ import SimpleXChat /// Supports [Dynamic Type](https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically) /// by retaining pill shape, even when ``ChatItem``'s height is less that twice its corner radius struct ChatItemClipped: ViewModifier { - struct ClipShape: Shape { - let maxCornerRadius: Double - - func path(in rect: CGRect) -> Path { - Path( - roundedRect: rect, - cornerRadius: min((rect.height / 2), maxCornerRadius), - style: .circular - ) - } - } - + @AppStorage(DEFAULT_CHAT_ITEM_ROUNDNESS) private var roundness = defaultChatItemRoundness + @AppStorage(DEFAULT_CHAT_ITEM_TAIL) private var tailEnabled = true + private let chatItem: (content: CIContent, chatDir: CIDirection)? + private let tailVisible: Bool + init() { - clipShape = ClipShape( - maxCornerRadius: 18 - ) + self.chatItem = nil + self.tailVisible = false + } + + init(_ ci: ChatItem, tailVisible: Bool) { + self.chatItem = (ci.content, ci.chatDir) + self.tailVisible = tailVisible } - init(_ chatItem: ChatItem) { - clipShape = ClipShape( - maxCornerRadius: { - switch chatItem.content { - case - .sndMsgContent, + private func shapeStyle() -> ChatItemShape.Style { + if let ci = chatItem { + switch ci.content { + case + .sndMsgContent, .rcvMsgContent, .rcvDecryptionError, - .rcvGroupInvitation, - .sndGroupInvitation, - .sndDeleted, - .rcvDeleted, .rcvIntegrityError, - .sndModerated, - .rcvModerated, - .rcvBlocked, - .invalidJSON: 18 - default: 8 + .invalidJSON: + let tail = if let mc = ci.content.msgContent, mc.isImageOrVideo && mc.text.isEmpty { + false + } else { + tailVisible } - }() - ) + return tailEnabled + ? .bubble( + padding: ci.chatDir.sent ? .trailing : .leading, + tailVisible: tail + ) + : .roundRect(radius: msgRectMaxRadius) + case .rcvGroupInvitation, .sndGroupInvitation: + return .roundRect(radius: msgRectMaxRadius) + default: return .roundRect(radius: 8) + } + } else { + return .roundRect(radius: msgRectMaxRadius) + } } - - private let clipShape: ClipShape - + func body(content: Content) -> some View { + let clipShape = ChatItemShape( + roundness: roundness, + style: shapeStyle() + ) content .contentShape(.dragPreview, clipShape) .contentShape(.contextMenuPreview, clipShape) @@ -65,4 +70,106 @@ struct ChatItemClipped: ViewModifier { } } +struct ChatTailPadding: ViewModifier { + func body(content: Content) -> some View { + content.padding(.horizontal, -msgTailWidth) + } +} +private let msgRectMaxRadius: Double = 18 +private let msgBubbleMaxRadius: Double = msgRectMaxRadius * 1.2 +private let msgTailWidth: Double = 9 +private let msgTailMinHeight: Double = msgTailWidth * 1.254 // ~56deg +private let msgTailMaxHeight: Double = msgTailWidth * 1.732 // 60deg + +struct ChatItemShape: Shape { + fileprivate enum Style { + case bubble(padding: HorizontalEdge, tailVisible: Bool) + case roundRect(radius: Double) + } + + fileprivate let roundness: Double + fileprivate let style: Style + + func path(in rect: CGRect) -> Path { + switch style { + case let .bubble(padding, tailVisible): + let w = rect.width + let h = rect.height + let rxMax = min(msgBubbleMaxRadius, w / 2) + let ryMax = min(msgBubbleMaxRadius, h / 2) + let rx = roundness * rxMax + let ry = roundness * ryMax + let tailHeight = min(msgTailMinHeight + roundness * (msgTailMaxHeight - msgTailMinHeight), h / 2) + var path = Path() + // top side + path.move(to: CGPoint(x: rx, y: 0)) + path.addLine(to: CGPoint(x: w - rx, y: 0)) + if roundness > 0 { + // top-right corner + path.addQuadCurve(to: CGPoint(x: w, y: ry), control: CGPoint(x: w, y: 0)) + } + if rect.height > 2 * ry { + // right side + path.addLine(to: CGPoint(x: w, y: h - ry)) + } + if roundness > 0 { + // bottom-right corner + path.addQuadCurve(to: CGPoint(x: w - rx, y: h), control: CGPoint(x: w, y: h)) + } + // bottom side + if tailVisible { + path.addLine(to: CGPoint(x: -msgTailWidth, y: h)) + if roundness > 0 { + // bottom-left tail + // distance of control point from touch point, calculated via ratios + let d = tailHeight - msgTailWidth * msgTailWidth / tailHeight + // tail control point + let tc = CGPoint(x: 0, y: h - tailHeight + d * sqrt(roundness)) + // bottom-left tail curve + path.addQuadCurve(to: CGPoint(x: 0, y: h - tailHeight), control: tc) + } else { + path.addLine(to: CGPoint(x: 0, y: h - tailHeight)) + } + if rect.height > ry + tailHeight { + // left side + path.addLine(to: CGPoint(x: 0, y: ry)) + } + } else { + path.addLine(to: CGPoint(x: rx, y: h)) + path.addQuadCurve(to: CGPoint(x: 0, y: h - ry), control: CGPoint(x: 0 , y: h)) + if rect.height > 2 * ry { + // left side + path.addLine(to: CGPoint(x: 0, y: ry)) + } + } + if roundness > 0 { + // top-left corner + path.addQuadCurve(to: CGPoint(x: rx, y: 0), control: CGPoint(x: 0, y: 0)) + } + path.closeSubpath() + return switch padding { + case .leading: path + case .trailing: path + .scale(x: -1, y: 1, anchor: .center) + .path(in: rect) + } + case let .roundRect(radius): + return Path(roundedRect: rect, cornerRadius: radius * roundness) + } + } + + var offset: Double? { + switch style { + case let .bubble(padding, isTailVisible): + if isTailVisible { + switch padding { + case .leading: -msgTailWidth + case .trailing: msgTailWidth + } + } else { 0 } + case .roundRect: 0 + } + } + +} diff --git a/apps/ios/Shared/Views/Helpers/ChatWallpaper.swift b/apps/ios/Shared/Views/Helpers/ChatWallpaper.swift index 9eea278d4e..cc5be9e7bb 100644 --- a/apps/ios/Shared/Views/Helpers/ChatWallpaper.swift +++ b/apps/ios/Shared/Views/Helpers/ChatWallpaper.swift @@ -100,7 +100,7 @@ extension PresetWallpaper { scale } else if let type = ChatModel.shared.currentUser?.uiThemes?.preferredMode(base.mode == DefaultThemeMode.dark)?.wallpaper?.toAppWallpaper().type, type.sameType(WallpaperType.preset(filename, nil)) { type.scale - } else if let scale = themeOverridesDefault.get().first(where: { $0.wallpaper != nil && $0.wallpaper!.preset == filename })?.wallpaper?.scale { + } else if let scale = themeOverridesDefault.get().first(where: { $0.wallpaper != nil && $0.wallpaper!.preset == filename && $0.base == base })?.wallpaper?.scale { scale } else { Float(1.0) diff --git a/apps/ios/Shared/Views/Helpers/InvertedForegroundStyle.swift b/apps/ios/Shared/Views/Helpers/InvertedForegroundStyle.swift new file mode 100644 index 0000000000..dca413dafe --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/InvertedForegroundStyle.swift @@ -0,0 +1,21 @@ +// +// Test.swift +// SimpleX (iOS) +// +// Created by Levitating Pineapple on 31/08/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +extension View { + @ViewBuilder + func invertedForegroundStyle(enabled: Bool = true) -> some View { + if enabled { + foregroundStyle(Material.ultraThin) + .environment(\.colorScheme, .dark) + .grayscale(1) + .contrast(-20) + } else { self } + } +} diff --git a/apps/ios/Shared/Views/Helpers/KeyboardPadding.swift b/apps/ios/Shared/Views/Helpers/KeyboardPadding.swift deleted file mode 100644 index 45d766ddfd..0000000000 --- a/apps/ios/Shared/Views/Helpers/KeyboardPadding.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// KeyboardPadding.swift -// SimpleX (iOS) -// -// Created by Evgeny on 10/07/2023. -// Copyright © 2023 SimpleX Chat. All rights reserved. -// - -import SwiftUI - -extension View { - @ViewBuilder func keyboardPadding() -> some View { - if #available(iOS 17.0, *) { - GeometryReader { g in - self.padding(.bottom, max(0, ChatModel.shared.keyboardHeight - g.safeAreaInsets.bottom)) - } - } else { - self - } - } -} diff --git a/apps/ios/Shared/Views/Helpers/ProfileImage.swift b/apps/ios/Shared/Views/Helpers/ProfileImage.swift index 248504c59b..3eedd56441 100644 --- a/apps/ios/Shared/Views/Helpers/ProfileImage.swift +++ b/apps/ios/Shared/Views/Helpers/ProfileImage.swift @@ -20,7 +20,7 @@ struct ProfileImage: View { @AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner var body: some View { - if let uiImage = UIImage(base64Encoded: imageStr) { + if let uiImage = imageFromBase64(imageStr) { clipProfileImage(Image(uiImage: uiImage), size: size, radius: radius, blurred: blurred) } else { let c = color.asAnotherColorFromSecondaryVariant(theme) diff --git a/apps/ios/Shared/Views/Helpers/ShareSheet.swift b/apps/ios/Shared/Views/Helpers/ShareSheet.swift index 936c6cb3ab..b8de0e4ceb 100644 --- a/apps/ios/Shared/Views/Helpers/ShareSheet.swift +++ b/apps/ios/Shared/Views/Helpers/ShareSheet.swift @@ -8,15 +8,63 @@ import SwiftUI -func showShareSheet(items: [Any], completed: (() -> Void)? = nil) { +func getTopViewController() -> UIViewController? { let keyWindowScene = UIApplication.shared.connectedScenes.first { $0.activationState == .foregroundActive } as? UIWindowScene if let keyWindow = keyWindowScene?.windows.filter(\.isKeyWindow).first, - let presentedViewController = keyWindow.rootViewController?.presentedViewController ?? keyWindow.rootViewController { + let rootViewController = keyWindow.rootViewController { + // Find the top-most presented view controller + var topController = rootViewController + while let presentedViewController = topController.presentedViewController { + topController = presentedViewController + } + return topController + } + return nil +} + +func showShareSheet(items: [Any], completed: (() -> Void)? = nil) { + if let topController = getTopViewController() { let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) if let completed = completed { - let handler: UIActivityViewController.CompletionWithItemsHandler = { _,_,_,_ in completed() } - activityViewController.completionWithItemsHandler = handler - } - presentedViewController.present(activityViewController, animated: true) + activityViewController.completionWithItemsHandler = { _, _, _, _ in + completed() + } + } + topController.present(activityViewController, animated: true) } } + +func showAlert( + title: String, + message: String? = nil, + buttonTitle: String, + buttonAction: @escaping () -> Void, + cancelButton: Bool +) -> Void { + if let topController = getTopViewController() { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: buttonTitle, style: .default) { _ in + buttonAction() + }) + if cancelButton { + alert.addAction(cancelAlertAction) + } + topController.present(alert, animated: true) + } +} + +func showAlert( + _ title: String, + message: String? = nil, + actions: () -> [UIAlertAction] = { [okAlertAction] } +) { + if let topController = getTopViewController() { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + for action in actions() { alert.addAction(action) } + topController.present(alert, animated: true) + } +} + +let okAlertAction = UIAlertAction(title: NSLocalizedString("Ok", comment: "alert button"), style: .default) + +let cancelAlertAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: "alert button"), style: .cancel) diff --git a/apps/ios/Shared/Views/Helpers/SheetRepresentable.swift b/apps/ios/Shared/Views/Helpers/SheetRepresentable.swift new file mode 100644 index 0000000000..841d5c7eda --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/SheetRepresentable.swift @@ -0,0 +1,188 @@ +// +// SwiftUISheet.swift +// SimpleX (iOS) +// +// Created by user on 23/09/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +private let sheetAnimationDuration: Double = 0.35 + +// Refrence: https://easings.net/ +private let easeOutCubic = UICubicTimingParameters( + controlPoint1: CGPoint(x: 0.215, y: 0.61), + controlPoint2: CGPoint(x: 0.355, y: 1) +) + +struct Sheet: ViewModifier { + @Binding var isPresented: Bool + @ViewBuilder let sheetContent: () -> SheetContent + + func body(content: Content) -> some View { + ZStack { + content + SheetRepresentable(isPresented: $isPresented, content: sheetContent()) + .allowsHitTesting(isPresented) + .ignoresSafeArea() + } + } +} + +struct SheetRepresentable: UIViewControllerRepresentable { + @Binding var isPresented: Bool + let content: Content + + func makeUIViewController(context: Context) -> Controller { + Controller(content: content, representer: self) + } + + func updateUIViewController(_ sheetController: Controller, context: Context) { + sheetController.animate(isPresented: isPresented) + } + + class Controller: UIViewController { + let hostingController: UIHostingController + private let animator = UIViewPropertyAnimator( + duration: sheetAnimationDuration, + timingParameters: easeOutCubic + ) + private let representer: SheetRepresentable + private var retainedFraction: CGFloat = 0 + private var sheetHeight: Double { hostingController.view.frame.height } + private var task: Task? + + init(content: C, representer: SheetRepresentable) { + self.representer = representer + self.hostingController = UIHostingController(rootView: content) + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { fatalError("init(coder:) missing") } + + deinit { + animator.stopAnimation(true) + animator.finishAnimation(at: .current) + } + + func animate(isPresented: Bool) { + let alreadyAnimating = animator.isRunning && isPresented != animator.isReversed + let sheetFullyDismissed = animator.fractionComplete == (animator.isReversed ? 1 : 0) + let sheetFullyPresented = animator.fractionComplete == (animator.isReversed ? 0 : 1) + + if !isPresented && sheetFullyDismissed || + isPresented && sheetFullyPresented || + alreadyAnimating { + return + } + + animator.pauseAnimation() + animator.isReversed = !isPresented + animator.continueAnimation( + withTimingParameters: isPresented + ? easeOutCubic + : UICubicTimingParameters(animationCurve: .easeIn), + durationFactor: 1 - animator.fractionComplete + ) + handleVisibility() + } + + func handleVisibility() { + if animator.isReversed { + task = Task { + do { + let sleepDuration = UInt64(sheetAnimationDuration * Double(NSEC_PER_SEC)) + try await Task.sleep(nanoseconds: sleepDuration) + view.isHidden = true + } catch { } + } + } else { + task?.cancel() + task = nil + view.isHidden = false + } + } + + override func viewDidLoad() { + view.isHidden = true + view.backgroundColor = .clear + view.addGestureRecognizer( + UITapGestureRecognizer(target: self, action: #selector(tap(gesture:))) + ) + addChild(hostingController) + hostingController.didMove(toParent: self) + if let sheet = hostingController.view { + sheet.isHidden = true + sheet.clipsToBounds = true + sheet.layer.cornerRadius = 10 + sheet.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] + sheet.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan(gesture:)))) + sheet.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(sheet) + NSLayoutConstraint.activate([ + hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), + hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + } + + override func viewDidAppear(_ animated: Bool) { + // Ensures animations are only setup once + // on some iOS version `viewDidAppear` can get called on each state change. + if hostingController.view.isHidden { + hostingController.view.transform = CGAffineTransform(translationX: 0, y: self.sheetHeight) + hostingController.view.isHidden = false + animator.pausesOnCompletion = true + animator.addAnimations { + self.hostingController.view.transform = .identity + self.view.backgroundColor = UIColor { + switch $0.userInterfaceStyle { + case .dark: .black.withAlphaComponent(0.290) + default: .black.withAlphaComponent(0.121) + } + } + } + animator.startAnimation() + animator.pauseAnimation() + } + } + + @objc + func pan(gesture: UIPanGestureRecognizer) { + switch gesture.state { + case .began: + animator.isReversed = false + animator.pauseAnimation() + retainedFraction = animator.fractionComplete + case .changed: + animator.fractionComplete = retainedFraction - gesture.translation(in: view).y / sheetHeight + case .ended, .cancelled: + let velocity = gesture.velocity(in: view).y + animator.isReversed = (velocity - (animator.fractionComplete - 0.5) * 100).sign == .plus + let defaultVelocity = sheetHeight / sheetAnimationDuration + let fractionRemaining = 1 - animator.fractionComplete + let durationFactor = min(max(fractionRemaining / (abs(velocity) / defaultVelocity), 0.5), 1) + animator.continueAnimation(withTimingParameters: nil, durationFactor: durationFactor * fractionRemaining) + handleVisibility() + DispatchQueue.main.asyncAfter(deadline: .now() + sheetAnimationDuration) { + self.representer.isPresented = !self.animator.isReversed + } + default: break + } + } + + @objc + func tap(gesture: UITapGestureRecognizer) { + switch gesture.state { + case .ended: + if gesture.location(in: view).y < view.frame.height - sheetHeight { + representer.isPresented = false + } + default: break + } + } + } +} diff --git a/apps/ios/Shared/Views/Helpers/StickyScrollView.swift b/apps/ios/Shared/Views/Helpers/StickyScrollView.swift new file mode 100644 index 0000000000..5799962778 --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/StickyScrollView.swift @@ -0,0 +1,61 @@ +// +// StickyScrollView.swift +// SimpleX (iOS) +// +// Created by user on 20/09/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +struct StickyScrollView: UIViewRepresentable { + @Binding var resetScroll: ResetScrollAction + @ViewBuilder let content: () -> Content + + func makeUIView(context: Context) -> UIScrollView { + let hc = context.coordinator.hostingController + hc.view.backgroundColor = .clear + let sv = UIScrollView() + sv.showsHorizontalScrollIndicator = false + sv.addSubview(hc.view) + sv.delegate = context.coordinator + DispatchQueue.main.async { + resetScroll = ResetScrollAction { sv.setContentOffset(.zero, animated: false) } + } + return sv + } + + func updateUIView(_ scrollView: UIScrollView, context: Context) { + let hc = context.coordinator.hostingController + hc.rootView = content() + hc.view.frame.size = hc.view.intrinsicContentSize + scrollView.contentSize = hc.view.intrinsicContentSize + } + + func makeCoordinator() -> Coordinator { + Coordinator(content: content()) + } + + class Coordinator: NSObject, UIScrollViewDelegate { + let hostingController: UIHostingController + + init(content: Content) { + self.hostingController = UIHostingController(rootView: content) + } + + func scrollViewWillEndDragging( + _ scrollView: UIScrollView, + withVelocity velocity: CGPoint, + targetContentOffset: UnsafeMutablePointer + ) { + if targetContentOffset.pointee.x < 32 { + targetContentOffset.pointee.x = 0 + } + } + } +} + +struct ResetScrollAction { + var action = { } + func callAsFunction() { action() } +} diff --git a/apps/ios/Shared/Views/Helpers/ThemeModeEditor.swift b/apps/ios/Shared/Views/Helpers/ThemeModeEditor.swift index ae94b4685c..9d5ae2e289 100644 --- a/apps/ios/Shared/Views/Helpers/ThemeModeEditor.swift +++ b/apps/ios/Shared/Views/Helpers/ThemeModeEditor.swift @@ -16,6 +16,7 @@ struct UserWallpaperEditor: View { @State var themeModeOverride: ThemeModeOverride @State var applyToMode: DefaultThemeMode? @State var showMore: Bool = false + @State var showFileImporter: Bool = false @Binding var globalThemeUsed: Bool var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void @@ -125,24 +126,27 @@ struct UserWallpaperEditor: View { CustomizeThemeColorsSection(editColor: { name in editColor(name, theme) }) - ImportExportThemeSection(perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in - let importedFromString = imported.wallpaper?.importFromString() - let importedType = importedFromString?.toAppWallpaper().type - let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get()) - let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType } - let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors - let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors) - Task { - await MainActor.run { - themeModeOverride = res - } - await save(applyToMode, res) - } - } + ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes) } else { AdvancedSettingsButton(theme.colors.primary) { showMore = true } } } + .modifier( + ThemeImporter(isPresented: $showFileImporter) { imported in + let importedFromString = imported.wallpaper?.importFromString() + let importedType = importedFromString?.toAppWallpaper().type + let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get()) + let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType } + let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors + let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors) + Task { + await MainActor.run { + themeModeOverride = res + } + await save(applyToMode, res) + } + } + ) } private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool { @@ -216,6 +220,7 @@ struct ChatWallpaperEditor: View { @State var themeModeOverride: ThemeModeOverride @State var applyToMode: DefaultThemeMode? @State var showMore: Bool = false + @State var showFileImporter: Bool = false @Binding var globalThemeUsed: Bool var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void @@ -328,24 +333,27 @@ struct ChatWallpaperEditor: View { CustomizeThemeColorsSection(editColor: editColor) - ImportExportThemeSection(perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in - let importedFromString = imported.wallpaper?.importFromString() - let importedType = importedFromString?.toAppWallpaper().type - let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get()) - let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType } - let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors - let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors) - Task { - await MainActor.run { - themeModeOverride = res - } - await save(applyToMode, res) - } - } + ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes) } else { AdvancedSettingsButton(theme.colors.primary) { showMore = true } } } + .modifier( + ThemeImporter(isPresented: $showFileImporter) { imported in + let importedFromString = imported.wallpaper?.importFromString() + let importedType = importedFromString?.toAppWallpaper().type + let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get()) + let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType } + let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors + let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors) + Task { + await MainActor.run { + themeModeOverride = res + } + await save(applyToMode, res) + } + } + ) } private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool { diff --git a/apps/ios/Shared/Views/Helpers/UserDefault.swift b/apps/ios/Shared/Views/Helpers/UserDefault.swift new file mode 100644 index 0000000000..5f18465d20 --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/UserDefault.swift @@ -0,0 +1,62 @@ +// +// UserDefault.swift +// SimpleX (iOS) +// +// Created by user on 14/10/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import Combine + +@propertyWrapper +public struct UserDefault: DynamicProperty { + @StateObject private var observer = UserDefaultObserver() + let initialValue: Value + let key: String + let store: UserDefaults + + public init( + wrappedValue: Value, + _ key: String, + store: UserDefaults = .standard + ) { + self.initialValue = wrappedValue + self.key = key + self.store = store + } + + public var wrappedValue: Value { + get { + // Observer can only be accessed after the property wrapper is installed in view (runtime exception) + observer.subscribe(to: key) + return store.object(forKey: key) as? Value ?? initialValue + } + nonmutating set { + store.set(newValue, forKey: key) + } + } +} + +private class UserDefaultObserver: ObservableObject { + private var subscribed = false + + func subscribe(to key: String) { + if !subscribed { + NotificationCenter.default.addObserver( + self, + selector: #selector(userDefaultsDidChange), + name: UserDefaults.didChangeNotification, + object: nil + ) + subscribed = true + } + } + + @objc + private func userDefaultsDidChange(_ notification: Notification) { + Task { @MainActor in objectWillChange.send() } + } + + deinit { NotificationCenter.default.removeObserver(self) } +} diff --git a/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift b/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift index 5e64f7fb0d..27bb95b599 100644 --- a/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift +++ b/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift @@ -65,8 +65,7 @@ struct LocalAuthView: View { // Clear sensitive data on screen just in case app fails to hide its views while new database is created m.chatId = nil ItemsModel.shared.reversedChatItems = [] - m.chats = [] - m.popChatCollector.clear() + m.updateChats([]) m.users = [] _ = kcAppPassword.set(password) _ = kcSelfDestructPassword.remove() diff --git a/apps/ios/Shared/Views/Migration/MigrateFromDevice.swift b/apps/ios/Shared/Views/Migration/MigrateFromDevice.swift index 9cc229ba80..eb8df5fb04 100644 --- a/apps/ios/Shared/Views/Migration/MigrateFromDevice.swift +++ b/apps/ios/Shared/Views/Migration/MigrateFromDevice.swift @@ -24,6 +24,7 @@ private enum MigrationFromState: Equatable { } private enum MigrateFromDeviceViewAlert: Identifiable { + case finishMigration(_ fileId: Int64, _ ctrl: chat_ctrl) case deleteChat(_ title: LocalizedStringKey = "Delete chat profile?", _ text: LocalizedStringKey = "This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost.") case startChat(_ title: LocalizedStringKey = "Start chat?", _ text: LocalizedStringKey = "Warning: starting chat on multiple devices is not supported and will cause message delivery failures") @@ -38,6 +39,7 @@ private enum MigrateFromDeviceViewAlert: Identifiable { var id: String { switch self { + case .finishMigration: return "finishMigration" case let .deleteChat(title, text): return "\(title) \(text)" case let .startChat(title, text): return "\(title) \(text)" @@ -56,8 +58,6 @@ private enum MigrateFromDeviceViewAlert: Identifiable { struct MigrateFromDevice: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme - @Environment(\.dismiss) var dismiss: DismissAction - @Binding var showSettings: Bool @Binding var showProgressOnSettings: Bool @State private var migrationState: MigrationFromState = .chatStopInProgress @State private var useKeychain = storeDBPassphraseGroupDefault.get() @@ -106,9 +106,6 @@ struct MigrateFromDevice: View { finishedView(chatDeletion) } } - .modifier(BackButton(label: "Back", disabled: $backDisabled) { - dismiss() - }) .onChange(of: migrationState) { state in backDisabled = switch migrationState { case .chatStopInProgress, .archiving, .linkShown, .finished: true @@ -138,6 +135,15 @@ struct MigrateFromDevice: View { } .alert(item: $alert) { alert in switch alert { + case let .finishMigration(fileId, ctrl): + return Alert( + title: Text("Remove archive?"), + message: Text("The uploaded database archive will be permanently removed from the servers."), + primaryButton: .destructive(Text("Continue")) { + finishMigration(fileId, ctrl) + }, + secondaryButton: .cancel() + ) case let .startChat(title, text): return Alert( title: Text(title), @@ -171,7 +177,7 @@ struct MigrateFromDevice: View { case let .archiveExportedWithErrors(archivePath, errs): return Alert( title: Text("Chat database exported"), - message: Text("You may migrate the exported database.") + Text(verbatim: "\n\n") + Text("Some file(s) were not exported:") + archiveErrorsText(errs), + message: Text("You may migrate the exported database.") + Text(verbatim: "\n") + Text("Some file(s) were not exported:") + Text(archiveErrorsText(errs)), dismissButton: .default(Text("Continue")) { Task { await uploadArchive(path: archivePath) } } @@ -216,7 +222,8 @@ struct MigrateFromDevice: View { } private func passphraseNotSetView() -> some View { - DatabaseEncryptionView(useKeychain: $useKeychain, migration: true) + DatabaseEncryptionView(useKeychain: $useKeychain, migration: true, stopChatRunBlockStartChat: { _, _ in + }) .onChange(of: initialRandomDBPassphrase) { initial in if !initial { migrationState = .uploadConfirmation @@ -318,7 +325,7 @@ struct MigrateFromDevice: View { Text("Cancel migration").foregroundColor(.red) } } - Button(action: { finishMigration(fileId, ctrl) }) { + Button(action: { alert = .finishMigration(fileId, ctrl) }) { settingsRow("checkmark", color: theme.colors.secondary) { Text("Finalize migration").foregroundColor(theme.colors.primary) } @@ -523,9 +530,15 @@ struct MigrateFromDevice: View { } case let .sndStandaloneFileComplete(_, fileTransferMeta, rcvURIs): let cfg = getNetCfg() + let proxy: NetworkProxy? = if cfg.socksProxy == nil { + nil + } else { + networkProxyDefault.get() + } let data = MigrationFileLinkData.init( networkConfig: MigrationFileLinkData.NetworkConfig( socksProxy: cfg.socksProxy, + networkProxy: proxy, hostMode: cfg.hostMode, requiredHostMode: cfg.requiredHostMode ) @@ -590,7 +603,7 @@ struct MigrateFromDevice: View { } catch let error { fatalError("Error starting chat \(responseError(error))") } - showSettings = false + dismissAllSheets(animated: true) } } catch let error { alert = .error(title: "Error deleting database", error: responseError(error)) @@ -613,9 +626,7 @@ struct MigrateFromDevice: View { } // Hide settings anyway if chatDbStatus is not ok, probably passphrase needs to be entered if dismiss || m.chatDbStatus != .ok { - await MainActor.run { - showSettings = false - } + dismissAllSheets(animated: true) } } @@ -767,6 +778,6 @@ private class MigrationChatReceiver { struct MigrateFromDevice_Previews: PreviewProvider { static var previews: some View { - MigrateFromDevice(showSettings: Binding.constant(true), showProgressOnSettings: Binding.constant(false)) + MigrateFromDevice(showProgressOnSettings: Binding.constant(false)) } } diff --git a/apps/ios/Shared/Views/Migration/MigrateToDevice.swift b/apps/ios/Shared/Views/Migration/MigrateToDevice.swift index 67ea1008cd..763cd473fe 100644 --- a/apps/ios/Shared/Views/Migration/MigrateToDevice.swift +++ b/apps/ios/Shared/Views/Migration/MigrateToDevice.swift @@ -93,7 +93,6 @@ struct MigrateToDevice: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme @Environment(\.dismiss) var dismiss: DismissAction - @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false @Binding var migrationState: MigrationToState? @State private var useKeychain = storeDBPassphraseGroupDefault.get() @State private var alert: MigrateToDeviceViewAlert? @@ -102,6 +101,10 @@ struct MigrateToDevice: View { // Prevent from hiding the view until migration is finished or app deleted @State private var backDisabled: Bool = false @State private var showQRCodeScanner: Bool = true + @State private var pasteboardHasStrings = UIPasteboard.general.hasStrings + + @State private var importingArchiveFromFileProgressIndicator = false + @State private var showFileImporter = false var body: some View { VStack { @@ -197,11 +200,15 @@ struct MigrateToDevice: View { } } } - if developerTools { - Section(header: Text("Or paste archive link").foregroundColor(theme.colors.secondary)) { - pasteLinkView() - } + Section(header: Text("Or paste archive link").foregroundColor(theme.colors.secondary)) { + pasteLinkView() } + Section(header: Text("Or import archive file").foregroundColor(theme.colors.secondary)) { + archiveImportFromFileView() + } + } + if importingArchiveFromFileProgressIndicator { + progressView() } } } @@ -218,10 +225,38 @@ struct MigrateToDevice: View { } label: { Text("Tap to paste link") } - .disabled(!ChatModel.shared.pasteboardHasStrings) + .disabled(!pasteboardHasStrings) .frame(maxWidth: .infinity, alignment: .center) } + private func archiveImportFromFileView() -> some View { + Button { + showFileImporter = true + } label: { + Label("Import database", systemImage: "square.and.arrow.down") + } + .disabled(importingArchiveFromFileProgressIndicator) + .fileImporter( + isPresented: $showFileImporter, + allowedContentTypes: [.zip], + allowsMultipleSelection: false + ) { result in + if case let .success(files) = result, let fileURL = files.first { + Task { + let success = await DatabaseView.importArchive(fileURL, $importingArchiveFromFileProgressIndicator, Binding.constant(nil)) + if success { + DatabaseView.startChat( + Binding.constant(false), + $importingArchiveFromFileProgressIndicator + ) + hideView() + } + } + } + } + } + + private func linkDownloadingView(_ link: String) -> some View { ZStack { List { @@ -487,6 +522,9 @@ struct MigrateToDevice: View { do { if !hasChatCtrl() { chatInitControllerRemovingDatabases() + } else if ChatModel.shared.chatRunning == true { + // cannot delete storage if chat is running + try await apiStopChat() } try await apiDeleteStorage() try? FileManager.default.createDirectory(at: getWallpaperDirectory(), withIntermediateDirectories: true) @@ -556,11 +594,22 @@ struct MigrateToDevice: View { do { try? FileManager.default.removeItem(at: getMigrationTempFilesDirectory()) MigrationToDeviceState.save(nil) - appSettings.importIntoApp() - try SimpleX.startChat(refreshInvitations: true) - AlertManager.shared.showAlertMsg(title: "Chat migrated!", message: "Finalize migration on another device.") + try ObjC.catchException { + appSettings.importIntoApp() + } + do { + try SimpleX.startChat(refreshInvitations: true) + AlertManager.shared.showAlertMsg(title: "Chat migrated!", message: "Finalize migration on another device.") + } catch let error { + AlertManager.shared.showAlert(Alert(title: Text("Error starting chat"), message: Text(responseError(error)))) + } } catch let error { - AlertManager.shared.showAlert(Alert(title: Text("Error starting chat"), message: Text(responseError(error)))) + logger.error("Error importing settings: \(error.localizedDescription)") + AlertManager.shared.showAlert( + Alert( + title: Text("Error migrating settings"), + message: Text ("Some app settings were not migrated.") + Text("\n") + Text(responseError(error))) + ) } hideView() } diff --git a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift index 6001dff790..3a64a955c5 100644 --- a/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift +++ b/apps/ios/Shared/Views/NewChat/AddContactLearnMore.swift @@ -28,7 +28,9 @@ struct AddContactLearnMore: View { Text("If you can't meet in person, show QR code in a video call, or share the link.") Text("Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).") } + .frame(maxWidth: .infinity, alignment: .leading) .listRowBackground(Color.clear) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) } .modifier(ThemedBackground(grouped: true)) } diff --git a/apps/ios/Shared/Views/NewChat/AddGroupView.swift b/apps/ios/Shared/Views/NewChat/AddGroupView.swift index 113691abb3..0c7f6136ff 100644 --- a/apps/ios/Shared/Views/NewChat/AddGroupView.swift +++ b/apps/ios/Shared/Views/NewChat/AddGroupView.swift @@ -59,7 +59,7 @@ struct AddGroupView: View { .navigationBarTitle("Group link") } } else { - createGroupView().keyboardPadding() + createGroupView() } } @@ -137,10 +137,13 @@ struct AddGroupView: View { createInvalidNameAlert(mkValidName(profile.displayName), $profile.displayName) } .onChange(of: chosenImage) { image in - if let image = image { - profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) - } else { - profile.image = nil + Task { + let resized: String? = if let image { + await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) + } else { + nil + } + await MainActor.run { profile.image = resized } } } .modifier(ThemedBackground(grouped: true)) diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift index bcca763a75..6f973983bf 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift @@ -14,9 +14,10 @@ enum ContactType: Int { } struct NewChatMenuButton: View { + // do not use chatModel here because it prevents showing AddGroupMembersView after group creation and QR code after link creation on iOS 16 +// @EnvironmentObject var chatModel: ChatModel @State private var showNewChatSheet = false @State private var alert: SomeAlert? = nil - @State private var globalAlert: SomeAlert? = nil var body: some View { Button { @@ -28,22 +29,10 @@ struct NewChatMenuButton: View { .frame(width: 24, height: 24) } .appSheet(isPresented: $showNewChatSheet) { - NewChatSheet(alert: $alert) + NewChatSheet() .environment(\EnvironmentValues.refresh as! WritableKeyPath, nil) - .alert(item: $alert) { a in - return a.alert - } } - // This is a workaround to show "Keep unused invitation" alert in both following cases: - // - on going back from NewChatView to NewChatSheet, - // - on dismissing NewChatMenuButton sheet while on NewChatView (skipping NewChatSheet) - .onChange(of: alert?.id) { a in - if !showNewChatSheet && alert != nil { - globalAlert = alert - alert = nil - } - } - .alert(item: $globalAlert) { a in + .alert(item: $alert) { a in return a.alert } } @@ -60,7 +49,7 @@ struct NewChatSheet: View { @State private var searchText = "" @State private var searchShowingSimplexLink = false @State private var searchChatFilteredBySimplexLink: String? = nil - @Binding var alert: SomeAlert? + @State private var alert: SomeAlert? // Sheet height management @State private var isAddContactActive = false @@ -78,6 +67,9 @@ struct NewChatSheet: View { .navigationBarTitleDisplayMode(.large) .navigationBarHidden(searchMode) .modifier(ThemedBackground(grouped: true)) + .alert(item: $alert) { a in + return a.alert + } } if #available(iOS 16.0, *), oneHandUI { let sheetHeight: CGFloat = showArchive ? 575 : 500 @@ -112,17 +104,17 @@ struct NewChatSheet: View { if (searchText.isEmpty) { Section { NavigationLink(isActive: $isAddContactActive) { - NewChatView(selection: .invite, parentAlert: $alert) + NewChatView(selection: .invite) .navigationTitle("New chat") .modifier(ThemedBackground(grouped: true)) .navigationBarTitleDisplayMode(.large) } label: { - navigateOnTap(Label("Add contact", systemImage: "link.badge.plus")) { + navigateOnTap(Label("Create 1-time link", systemImage: "link.badge.plus")) { isAddContactActive = true } } NavigationLink(isActive: $isScanPasteLinkActive) { - NewChatView(selection: .connect, showQRCodeScanner: true, parentAlert: $alert) + NewChatView(selection: .connect, showQRCodeScanner: true) .navigationTitle("New chat") .modifier(ThemedBackground(grouped: true)) .navigationBarTitleDisplayMode(.large) @@ -199,7 +191,7 @@ func chatContactType(chat: Chat) -> ContactType { case .contactRequest: return .request case let .direct(contact): - if contact.activeConn == nil && contact.profile.contactLink != nil { + if contact.activeConn == nil && contact.profile.contactLink != nil && contact.active { return .card } else if contact.chatDeleted { return .chatDeleted diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift index 6cbc65e7c9..e18d932278 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatView.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -45,29 +45,63 @@ enum NewChatOption: Identifiable { var id: Self { self } } +func showKeepInvitationAlert() { + if let showingInvitation = ChatModel.shared.showingInvitation, + !showingInvitation.connChatUsed { + showAlert( + NSLocalizedString("Keep unused invitation?", comment: "alert title"), + message: NSLocalizedString("You can view invitation link again in connection details.", comment: "alert message"), + actions: {[ + UIAlertAction( + title: NSLocalizedString("Keep", comment: "alert action"), + style: .default + ), + UIAlertAction( + title: NSLocalizedString("Delete", comment: "alert action"), + style: .destructive, + handler: { _ in + Task { + await deleteChat(Chat( + chatInfo: .contactConnection(contactConnection: showingInvitation.pcc), + chatItems: [] + )) + } + } + ) + ]} + ) + } + ChatModel.shared.showingInvitation = nil +} + struct NewChatView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme @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 var choosingProfile = false @State private var pastedLink: String = "" @State private var alert: NewChatViewAlert? - @Binding var parentAlert: SomeAlert? + @State private var contactConnection: PendingContactConnection? = nil var body: some View { VStack(alignment: .leading) { Picker("New chat", selection: $selection) { - Label("Add contact", systemImage: "link") + Label("1-time link", systemImage: "link") .tag(NewChatOption.invite) Label("Connect via link", systemImage: "qrcode") .tag(NewChatOption.connect) } .pickerStyle(.segmented) .padding() + .onChange(of: $selection.wrappedValue) { opt in + if opt == NewChatOption.connect { + showQRCodeScanner = true + } + } VStack { // it seems there's a bug in iOS 15 if several views in switch (or if-else) statement have different transitions @@ -122,26 +156,10 @@ struct NewChatView: View { } } .onDisappear { - if !(m.showingInvitation?.connChatUsed ?? true), - let conn = contactConnection { - parentAlert = SomeAlert( - alert: 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: [] - )) - } - } - ), - id: "keepUnusedInvitation" - ) + if !choosingProfile { + showKeepInvitationAlert() + contactConnection = nil } - m.showingInvitation = nil } .alert(item: $alert) { a in switch(a) { @@ -159,7 +177,8 @@ struct NewChatView: View { InviteView( invitationUsed: $invitationUsed, contactConnection: $contactConnection, - connReqInvitation: connReqInvitation + connReqInvitation: $connReqInvitation, + choosingProfile: $choosingProfile ) } else if creatingConnReq { creatingLinkProgressView() @@ -178,7 +197,7 @@ struct NewChatView: View { if let (connReq, pcc) = r { await MainActor.run { m.updateContactConnection(pcc) - m.showingInvitation = ShowingInvitation(connId: pcc.id, connChatUsed: false) + m.showingInvitation = ShowingInvitation(pcc: pcc, connChatUsed: false) connReqInvitation = connReq contactConnection = pcc } @@ -210,12 +229,22 @@ struct NewChatView: View { } } +private func incognitoProfileImage() -> some View { + Image(systemName: "theatermasks.fill") + .resizable() + .scaledToFit() + .frame(width: 30) + .foregroundColor(.indigo) +} + private struct InviteView: View { @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var theme: AppTheme @Binding var invitationUsed: Bool @Binding var contactConnection: PendingContactConnection? - var connReqInvitation: String + @Binding var connReqInvitation: String + @Binding var choosingProfile: Bool + @AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false var body: some View { @@ -226,28 +255,40 @@ private struct InviteView: View { .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 10)) qrCodeView() - - Section { - IncognitoToggle(incognitoEnabled: $incognitoDefault) - } footer: { - sharedProfileInfo(incognitoDefault) - .foregroundColor(theme.colors.secondary) + if let selectedProfile = chatModel.currentUser { + Section { + NavigationLink { + ActiveProfilePicker( + contactConnection: $contactConnection, + connReqInvitation: $connReqInvitation, + incognitoEnabled: $incognitoDefault, + choosingProfile: $choosingProfile, + selectedProfile: selectedProfile + ) + } label: { + HStack { + if incognitoDefault { + incognitoProfileImage() + Text("Incognito") + } else { + ProfileImage(imageStr: chatModel.currentUser?.image, size: 30) + Text(chatModel.currentUser?.chatViewName ?? "") + } + } + } + } header: { + Text("Share profile").foregroundColor(theme.colors.secondary) + } footer: { + if incognitoDefault { + Text("A new random profile will be shared.") + } + } } } .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() + } + .onChange(of: chatModel.currentUser) { u in setInvitationUsed() } } @@ -270,6 +311,7 @@ private struct InviteView: View { private func qrCodeView() -> some View { Section(header: Text("Or show this code").foregroundColor(theme.colors.secondary)) { SimpleXLinkQRCode(uri: connReqInvitation, onShare: setInvitationUsed) + .id("simplex-qrcode-view-for-\(connReqInvitation)") .padding() .background( RoundedRectangle(cornerRadius: 12, style: .continuous) @@ -289,6 +331,257 @@ private struct InviteView: View { } } +private enum ProfileSwitchStatus { + case switchingUser + case switchingIncognito + case idle +} + +private struct ActiveProfilePicker: View { + @Environment(\.dismiss) var dismiss + @EnvironmentObject var chatModel: ChatModel + @EnvironmentObject var theme: AppTheme + @Binding var contactConnection: PendingContactConnection? + @Binding var connReqInvitation: String + @Binding var incognitoEnabled: Bool + @Binding var choosingProfile: Bool + @State private var alert: SomeAlert? + @State private var profileSwitchStatus: ProfileSwitchStatus = .idle + @State private var switchingProfileByTimeout = false + @State private var lastSwitchingProfileByTimeoutCall: Double? + @State private var profiles: [User] = [] + @State private var searchTextOrPassword = "" + @State private var showIncognitoSheet = false + @State private var incognitoFirst: Bool = false + @State var selectedProfile: User + var trimmedSearchTextOrPassword: String { searchTextOrPassword.trimmingCharacters(in: .whitespaces)} + + var body: some View { + viewBody() + .navigationTitle("Select chat profile") + .searchable(text: $searchTextOrPassword, placement: .navigationBarDrawer(displayMode: .always)) + .autocorrectionDisabled(true) + .navigationBarTitleDisplayMode(.large) + .onAppear { + profiles = chatModel.users + .map { $0.user } + .sorted { u, _ in u.activeUser } + } + .onChange(of: incognitoEnabled) { incognito in + if profileSwitchStatus != .switchingIncognito { + return + } + + Task { + do { + if let contactConn = contactConnection, + let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) { + await MainActor.run { + contactConnection = conn + chatModel.updateContactConnection(conn) + profileSwitchStatus = .idle + dismiss() + } + } + } catch { + profileSwitchStatus = .idle + incognitoEnabled = !incognito + logger.error("apiSetConnectionIncognito error: \(responseError(error))") + let err = getErrorAlert(error, "Error changing to incognito!") + + alert = SomeAlert( + alert: Alert( + title: Text(err.title), + message: Text(err.message ?? "Error: \(responseError(error))") + ), + id: "setConnectionIncognitoError" + ) + } + } + } + .onChange(of: profileSwitchStatus) { sp in + if sp != .idle { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + switchingProfileByTimeout = profileSwitchStatus != .idle + } + } else { + switchingProfileByTimeout = false + } + } + .onChange(of: selectedProfile) { profile in + if (profileSwitchStatus != .switchingUser) { + return + } + Task { + do { + if let contactConn = contactConnection, + let conn = try await apiChangeConnectionUser(connId: contactConn.pccConnId, userId: profile.userId) { + + await MainActor.run { + contactConnection = conn + connReqInvitation = conn.connReqInv ?? "" + incognitoEnabled = false + chatModel.updateContactConnection(conn) + } + do { + try await changeActiveUserAsync_(profile.userId, viewPwd: profile.hidden ? trimmedSearchTextOrPassword : nil ) + await MainActor.run { + profileSwitchStatus = .idle + dismiss() + } + } catch { + await MainActor.run { + profileSwitchStatus = .idle + alert = SomeAlert( + alert: Alert( + title: Text("Error switching profile"), + message: Text("Your connection was moved to \(profile.chatViewName) but an unexpected error occurred while redirecting you to the profile.") + ), + id: "switchingProfileError" + ) + } + } + } + } catch { + await MainActor.run { + profileSwitchStatus = .idle + if let currentUser = chatModel.currentUser { + selectedProfile = currentUser + } + let err = getErrorAlert(error, "Error changing connection profile") + alert = SomeAlert( + alert: Alert( + title: Text(err.title), + message: Text(err.message ?? "Error: \(responseError(error))") + ), + id: "changeConnectionUserError" + ) + } + } + } + } + .alert(item: $alert) { a in + a.alert + } + .onAppear { + incognitoFirst = incognitoEnabled + choosingProfile = true + } + .onDisappear { + choosingProfile = false + } + .sheet(isPresented: $showIncognitoSheet) { + IncognitoHelp() + } + } + + + @ViewBuilder private func viewBody() -> some View { + profilePicker() + .allowsHitTesting(!switchingProfileByTimeout) + .modifier(ThemedBackground(grouped: true)) + .overlay { + if switchingProfileByTimeout { + ProgressView() + .scaleEffect(2) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } + } + + private func filteredProfiles() -> [User] { + let s = trimmedSearchTextOrPassword + let lower = s.localizedLowercase + + return profiles.filter { u in + if (u.activeUser || !u.hidden) && (s == "" || u.chatViewName.localizedLowercase.contains(lower)) { + return true + } + return correctPassword(u, s) + } + } + + @ViewBuilder private func profilerPickerUserOption(_ user: User) -> some View { + Button { + if selectedProfile == user && incognitoEnabled { + incognitoEnabled = false + profileSwitchStatus = .switchingIncognito + } else if selectedProfile != user { + selectedProfile = user + profileSwitchStatus = .switchingUser + } + } label: { + HStack { + ProfileImage(imageStr: user.image, size: 30) + .padding(.trailing, 2) + Text(user.chatViewName) + .foregroundColor(theme.colors.onBackground) + .lineLimit(1) + Spacer() + if selectedProfile == user, !incognitoEnabled { + Image(systemName: "checkmark") + .resizable().scaledToFit().frame(width: 16) + .foregroundColor(theme.colors.primary) + } + } + } + } + + @ViewBuilder private func profilePicker() -> some View { + let incognitoOption = Button { + if !incognitoEnabled { + incognitoEnabled = true + profileSwitchStatus = .switchingIncognito + } + } label : { + HStack { + incognitoProfileImage() + Text("Incognito") + .foregroundColor(theme.colors.onBackground) + Image(systemName: "info.circle") + .foregroundColor(theme.colors.primary) + .font(.system(size: 14)) + .onTapGesture { + showIncognitoSheet = true + } + Spacer() + if incognitoEnabled { + Image(systemName: "checkmark") + .resizable().scaledToFit().frame(width: 16) + .foregroundColor(theme.colors.primary) + } + } + } + + List { + let filteredProfiles = filteredProfiles() + let activeProfile = filteredProfiles.first { u in u.activeUser } + + if let selectedProfile = activeProfile { + let otherProfiles = filteredProfiles.filter { u in u.userId != activeProfile?.userId } + + if incognitoFirst { + incognitoOption + profilerPickerUserOption(selectedProfile) + } else { + profilerPickerUserOption(selectedProfile) + incognitoOption + } + + ForEach(otherProfiles) { p in + profilerPickerUserOption(p) + } + } else { + incognitoOption + ForEach(filteredProfiles) { p in + profilerPickerUserOption(p) + } + } + } + .opacity(switchingProfileByTimeout ? 0.4 : 1) + } +} + private struct ConnectView: View { @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject var theme: AppTheme @@ -296,6 +589,7 @@ private struct ConnectView: View { @Binding var pastedLink: String @Binding var alert: NewChatViewAlert? @State private var sheet: PlanAndConnectActionSheet? + @State private var pasteboardHasStrings = UIPasteboard.general.hasStrings var body: some View { List { @@ -332,7 +626,7 @@ private struct ConnectView: View { } label: { Text("Tap to paste link") } - .disabled(!ChatModel.shared.pasteboardHasStrings) + .disabled(!pasteboardHasStrings) .frame(maxWidth: .infinity, alignment: .center) } else { linkTextView(pastedLink) @@ -403,6 +697,7 @@ struct ScannerInView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) .foregroundColor(Color.clear) switch cameraAuthorizationStatus { + case .authorized, nil: EmptyView() case .restricted: Text("Camera not available") case .denied: Label("Enable camera access", systemImage: "camera") default: Label("Tap to scan", systemImage: "qrcode") @@ -422,21 +717,26 @@ struct ScannerInView: View { .disabled(cameraAuthorizationStatus == .restricted) } } - .onAppear { + .task { let status = AVCaptureDevice.authorizationStatus(for: .video) cameraAuthorizationStatus = status if showQRCodeScanner { switch status { - case .notDetermined: askCameraAuthorization() + case .notDetermined: await askCameraAuthorizationAsync() case .restricted: showQRCodeScanner = false case .denied: showQRCodeScanner = false case .authorized: () - @unknown default: askCameraAuthorization() + @unknown default: await askCameraAuthorizationAsync() } } } } + func askCameraAuthorizationAsync() async { + await AVCaptureDevice.requestAccess(for: .video) + cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) + } + func askCameraAuthorization(_ cb: (() -> Void)? = nil) { AVCaptureDevice.requestAccess(for: .video) { allowed in cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video) @@ -616,11 +916,17 @@ func planAndConnectAlert(_ alert: PlanAndConnectAlert, dismiss: Bool, cleanup: ( ) case let .groupLinkConnecting(_, groupInfo): if let groupInfo = groupInfo { - return Alert( + return groupInfo.businessChat == nil + ? Alert( title: Text("Group already exists!"), message: Text("You are already joining the group \(groupInfo.displayName)."), dismissButton: .default(Text("OK")) { cleanup?() } ) + : Alert( + title: Text("Chat already exists!"), + message: Text("You are already connecting to \(groupInfo.displayName)."), + dismissButton: .default(Text("OK")) { cleanup?() } + ) } else { return Alert( title: Text("Already joining the group!"), @@ -937,10 +1243,15 @@ func contactAlreadyConnectingAlert(_ contact: Contact) -> Alert { } func groupAlreadyExistsAlert(_ groupInfo: GroupInfo) -> Alert { - mkAlert( + groupInfo.businessChat == nil + ? mkAlert( title: "Group already exists", message: "You are already in group \(groupInfo.displayName)." ) + : mkAlert( + title: "Chat already exists", + message: "You are already connected with \(groupInfo.displayName)." + ) } enum ConnReqType: Equatable { @@ -975,10 +1286,10 @@ func connReqSentAlert(_ type: ConnReqType) -> Alert { struct NewChatView_Previews: PreviewProvider { static var previews: some View { @State var parentAlert: SomeAlert? + @State var contactConnection: PendingContactConnection? = nil NewChatView( - selection: .invite, - parentAlert: $parentAlert + selection: .invite ) } } diff --git a/apps/ios/Shared/Views/NewChat/QRCode.swift b/apps/ios/Shared/Views/NewChat/QRCode.swift index e3bae9287a..bc1dc4b5bc 100644 --- a/apps/ios/Shared/Views/NewChat/QRCode.swift +++ b/apps/ios/Shared/Views/NewChat/QRCode.swift @@ -49,34 +49,34 @@ struct QRCode: View { ZStack { if let image = image { qrCodeImage(image) - } - GeometryReader { geo in - ZStack { - if withLogo { - let w = geo.size.width - Image("icon-light") - .resizable() - .scaledToFit() - .frame(width: w * 0.16, height: w * 0.16) - .frame(width: w * 0.165, height: w * 0.165) - .background(.white) - .clipShape(Circle()) + GeometryReader { geo in + ZStack { + if withLogo { + let w = geo.size.width + Image("icon-light") + .resizable() + .scaledToFit() + .frame(width: w * 0.16, height: w * 0.16) + .frame(width: w * 0.165, height: w * 0.165) + .background(.white) + .clipShape(Circle()) + } } - } - .onAppear { - makeScreenshotFunc = { - let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale) - showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)]) - onShare?() + .onAppear { + 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) } - .frame(width: geo.size.width, height: geo.size.height) + } else { + Color.clear.aspectRatio(1, contentMode: .fit) } } .onTapGesture(perform: makeScreenshotFunc) - .onAppear { - image = image ?? generateImage(uri, tintColor: tintColor) - } + .task { image = await generateImage(uri, tintColor: tintColor) } .frame(maxWidth: .infinity, maxHeight: .infinity) } } @@ -89,7 +89,7 @@ private func qrCodeImage(_ image: UIImage) -> some View { .textSelection(.enabled) } -private func generateImage(_ uri: String, tintColor: UIColor) -> UIImage? { +private func generateImage(_ uri: String, tintColor: UIColor) async -> UIImage? { let context = CIContext() let filter = CIFilter.qrCodeGenerator() filter.message = Data(uri.utf8) diff --git a/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift b/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift new file mode 100644 index 0000000000..2069ca9487 --- /dev/null +++ b/apps/ios/Shared/Views/Onboarding/AddressCreationCard.swift @@ -0,0 +1,109 @@ +// +// AddressCreationCard.swift +// SimpleX (iOS) +// +// Created by Diogo Cunha on 13/11/2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +struct AddressCreationCard: View { + @EnvironmentObject var theme: AppTheme + @EnvironmentObject private var chatModel: ChatModel + @Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize + @AppStorage(DEFAULT_ADDRESS_CREATION_CARD_SHOWN) private var addressCreationCardShown = false + @State private var showAddressCreationAlert = false + @State private var showAddressSheet = false + @State private var showAddressInfoSheet = false + + var body: some View { + let addressExists = chatModel.userAddress != nil + let chats = chatModel.chats.filter { chat in + !chat.chatInfo.chatDeleted && chatContactType(chat: chat) != ContactType.card + } + ZStack(alignment: .topTrailing) { + HStack(alignment: .top, spacing: 16) { + let envelopeSize = dynamicSize(userFont).profileImageSize + Image(systemName: "envelope.circle.fill") + .resizable() + .frame(width: envelopeSize, height: envelopeSize) + .foregroundColor(.accentColor) + VStack(alignment: .leading) { + Text("Your SimpleX address") + .font(.title3) + Spacer() + Text("How to use it") + textSpace + Text(Image(systemName: "info.circle")).foregroundColor(theme.colors.secondary) + } + } + .frame(maxWidth: .infinity, alignment: .leading) + VStack(alignment: .trailing) { + Image(systemName: "multiply") + .foregroundColor(theme.colors.secondary) + .onTapGesture { + showAddressCreationAlert = true + } + Spacer() + Text("Create") + .foregroundColor(.accentColor) + .onTapGesture { + showAddressSheet = true + } + } + } + .onTapGesture { + showAddressInfoSheet = true + } + .padding() + .background(theme.appColors.sentMessage) + .cornerRadius(12) + .frame(height: dynamicSize(userFont).rowHeight) + .alert(isPresented: $showAddressCreationAlert) { + Alert( + title: Text("SimpleX address"), + message: Text("Tap Create SimpleX address in the menu to create it later."), + dismissButton: .default(Text("Ok")) { + withAnimation { + addressCreationCardShown = true + } + } + ) + } + .sheet(isPresented: $showAddressSheet) { + NavigationView { + UserAddressView(autoCreate: true) + .navigationTitle("SimpleX address") + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } + } + .sheet(isPresented: $showAddressInfoSheet) { + NavigationView { + UserAddressLearnMore(showCreateAddressButton: true) + .navigationTitle("Address or 1-time link?") + .navigationBarTitleDisplayMode(.inline) + .modifier(ThemedBackground(grouped: true)) + } + } + .onChange(of: addressExists) { exists in + if exists, !addressCreationCardShown { + addressCreationCardShown = true + } + } + .onChange(of: chats.count) { size in + if size >= 3, !addressCreationCardShown { + addressCreationCardShown = true + } + } + .onAppear { + if addressExists, !addressCreationCardShown { + addressCreationCardShown = true + } + } + } +} + +#Preview { + AddressCreationCard() +} diff --git a/apps/ios/Shared/Views/Onboarding/ChooseServerOperators.swift b/apps/ios/Shared/Views/Onboarding/ChooseServerOperators.swift new file mode 100644 index 0000000000..1a0a736acd --- /dev/null +++ b/apps/ios/Shared/Views/Onboarding/ChooseServerOperators.swift @@ -0,0 +1,451 @@ +// +// ChooseServerOperators.swift +// SimpleX (iOS) +// +// Created by spaced4ndy on 31.10.2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +let conditionsURL = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/PRIVACY.md")! + +struct OnboardingButtonStyle: ButtonStyle { + @EnvironmentObject var theme: AppTheme + var isDisabled: Bool = false + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(.system(size: 17, weight: .semibold)) + .padding() + .frame(maxWidth: .infinity) + .background( + isDisabled + ? ( + theme.colors.isLight + ? .gray.opacity(0.17) + : .gray.opacity(0.27) + ) + : theme.colors.primary + ) + .foregroundColor( + isDisabled + ? ( + theme.colors.isLight + ? .gray.opacity(0.4) + : .white.opacity(0.2) + ) + : .white + ) + .cornerRadius(16) + .scaleEffect(configuration.isPressed ? 0.95 : 1.0) + } +} + +private enum ChooseServerOperatorsSheet: Identifiable { + case showInfo + case showConditions + + var id: String { + switch self { + case .showInfo: return "showInfo" + case .showConditions: return "showConditions" + } + } +} + +struct ChooseServerOperators: View { + @Environment(\.dismiss) var dismiss: DismissAction + @Environment(\.colorScheme) var colorScheme: ColorScheme + @EnvironmentObject var theme: AppTheme + var onboarding: Bool + @State private var serverOperators: [ServerOperator] = [] + @State private var selectedOperatorIds = Set() + @State private var sheetItem: ChooseServerOperatorsSheet? = nil + @State private var notificationsModeNavLinkActive = false + @State private var justOpened = true + + var selectedOperators: [ServerOperator] { serverOperators.filter { selectedOperatorIds.contains($0.operatorId) } } + + var body: some View { + GeometryReader { g in + ScrollView { + VStack(alignment: .leading, spacing: 20) { + let title = Text("Server operators") + .font(.largeTitle) + .bold() + .frame(maxWidth: .infinity, alignment: .center) + + if onboarding { + title.padding(.top, 25) + } else { + title + } + + infoText() + .frame(maxWidth: .infinity, alignment: .center) + + Spacer() + + ForEach(serverOperators) { srvOperator in + operatorCheckView(srvOperator) + } + VStack { + Text("SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app.").padding(.bottom, 8) + Text("You can configure servers via settings.") + } + .font(.footnote) + .multilineTextAlignment(.center) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.horizontal, 16) + + Spacer() + + let reviewForOperators = selectedOperators.filter { !$0.conditionsAcceptance.conditionsAccepted } + let canReviewLater = reviewForOperators.allSatisfy { $0.conditionsAcceptance.usageAllowed } + let currEnabledOperatorIds = Set(serverOperators.filter { $0.enabled }.map { $0.operatorId }) + + VStack(spacing: 8) { + if !reviewForOperators.isEmpty { + reviewConditionsButton() + } else if selectedOperatorIds != currEnabledOperatorIds && !selectedOperatorIds.isEmpty { + setOperatorsButton() + } else { + continueButton() + } + if onboarding { + Group { + if reviewForOperators.isEmpty { + Button("Conditions of use") { + sheetItem = .showConditions + } + } else { + Text("Conditions of use") + .foregroundColor(.clear) + } + } + .font(.system(size: 17, weight: .semibold)) + .frame(minHeight: 40) + } + } + + if !onboarding && !reviewForOperators.isEmpty { + VStack(spacing: 8) { + reviewLaterButton() + ( + Text("Conditions will be accepted for enabled operators after 30 days.") + + textSpace + + Text("You can configure operators in Network & servers settings.") + ) + .multilineTextAlignment(.center) + .font(.footnote) + .padding(.horizontal, 32) + } + .frame(maxWidth: .infinity) + .disabled(!canReviewLater) + .padding(.bottom) + } + } + .frame(minHeight: g.size.height) + } + .onAppear { + if justOpened { + serverOperators = ChatModel.shared.conditions.serverOperators + selectedOperatorIds = Set(serverOperators.filter { $0.enabled }.map { $0.operatorId }) + justOpened = false + } + } + .sheet(item: $sheetItem) { item in + switch item { + case .showInfo: + ChooseServerOperatorsInfoView() + case .showConditions: + UsageConditionsView( + currUserServers: Binding.constant([]), + userServers: Binding.constant([]) + ) + .modifier(ThemedBackground(grouped: true)) + } + } + .frame(maxHeight: .infinity, alignment: .top) + } + .frame(maxHeight: .infinity, alignment: .top) + .padding(onboarding ? 25 : 16) + } + + private func infoText() -> some View { + Button { + sheetItem = .showInfo + } label: { + Label("How it helps privacy", systemImage: "info.circle") + .font(.headline) + } + } + + @ViewBuilder private func operatorCheckView(_ serverOperator: ServerOperator) -> some View { + let checked = selectedOperatorIds.contains(serverOperator.operatorId) + let icon = checked ? "checkmark.circle.fill" : "circle" + let iconColor = checked ? theme.colors.primary : Color(uiColor: .tertiaryLabel).asAnotherColorFromSecondary(theme) + HStack(spacing: 10) { + Image(serverOperator.largeLogo(colorScheme)) + .resizable() + .scaledToFit() + .frame(height: 48) + Spacer() + Image(systemName: icon) + .resizable() + .scaledToFit() + .frame(width: 26, height: 26) + .foregroundColor(iconColor) + } + .background(theme.colors.background) + .padding() + .clipShape(RoundedRectangle(cornerRadius: 18)) + .overlay( + RoundedRectangle(cornerRadius: 18) + .stroke(Color(uiColor: .secondarySystemFill), lineWidth: 2) + ) + .padding(.horizontal, 2) + .onTapGesture { + if checked { + selectedOperatorIds.remove(serverOperator.operatorId) + } else { + selectedOperatorIds.insert(serverOperator.operatorId) + } + } + } + + private func reviewConditionsButton() -> some View { + NavigationLink("Review conditions") { + reviewConditionsView() + .navigationTitle("Conditions of use") + .navigationBarTitleDisplayMode(.large) + .toolbar { ToolbarItem(placement: .navigationBarTrailing, content: conditionsLinkButton) } + .modifier(ThemedBackground(grouped: true)) + } + .buttonStyle(OnboardingButtonStyle(isDisabled: selectedOperatorIds.isEmpty)) + .disabled(selectedOperatorIds.isEmpty) + } + + private func setOperatorsButton() -> some View { + notificationsModeNavLinkButton { + Button { + Task { + if let enabledOperators = enabledOperators(serverOperators) { + let r = try await setServerOperators(operators: enabledOperators) + await MainActor.run { + ChatModel.shared.conditions = r + continueToNextStep() + } + } else { + await MainActor.run { + continueToNextStep() + } + } + } + } label: { + Text("Update") + } + .buttonStyle(OnboardingButtonStyle(isDisabled: selectedOperatorIds.isEmpty)) + .disabled(selectedOperatorIds.isEmpty) + } + } + + private func continueButton() -> some View { + notificationsModeNavLinkButton { + Button { + continueToNextStep() + } label: { + Text("Continue") + } + .buttonStyle(OnboardingButtonStyle(isDisabled: selectedOperatorIds.isEmpty)) + .disabled(selectedOperatorIds.isEmpty) + } + } + + private func reviewLaterButton() -> some View { + notificationsModeNavLinkButton { + Button { + continueToNextStep() + } label: { + Text("Review later") + } + .buttonStyle(.borderless) + } + } + + private func continueToNextStep() { + if onboarding { + onboardingStageDefault.set(.step4_SetNotificationsMode) + notificationsModeNavLinkActive = true + } else { + dismiss() + } + } + + func notificationsModeNavLinkButton(_ button: @escaping (() -> some View)) -> some View { + ZStack { + button() + + NavigationLink(isActive: $notificationsModeNavLinkActive) { + notificationsModeDestinationView() + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() + } + } + + private func notificationsModeDestinationView() -> some View { + SetNotificationsMode() + .navigationBarBackButtonHidden(true) + .modifier(ThemedBackground()) + } + + @ViewBuilder private func reviewConditionsView() -> some View { + let operatorsWithConditionsAccepted = ChatModel.shared.conditions.serverOperators.filter { $0.conditionsAcceptance.conditionsAccepted } + let acceptForOperators = selectedOperators.filter { !$0.conditionsAcceptance.conditionsAccepted } + VStack(alignment: .leading, spacing: 20) { + if !operatorsWithConditionsAccepted.isEmpty { + Text("Conditions are already accepted for these operator(s): **\(operatorsWithConditionsAccepted.map { $0.legalName_ }.joined(separator: ", "))**.") + Text("The same conditions will apply to operator(s): **\(acceptForOperators.map { $0.legalName_ }.joined(separator: ", "))**.") + } else { + Text("Conditions will be accepted for operator(s): **\(acceptForOperators.map { $0.legalName_ }.joined(separator: ", "))**.") + } + ConditionsTextView() + .frame(maxHeight: .infinity) + acceptConditionsButton() + .padding(.bottom) + .padding(.bottom) + } + .padding(.horizontal, 25) + } + + private func acceptConditionsButton() -> some View { + notificationsModeNavLinkButton { + Button { + Task { + do { + let conditionsId = ChatModel.shared.conditions.currentConditions.conditionsId + let acceptForOperators = selectedOperators.filter { !$0.conditionsAcceptance.conditionsAccepted } + let operatorIds = acceptForOperators.map { $0.operatorId } + let r = try await acceptConditions(conditionsId: conditionsId, operatorIds: operatorIds) + await MainActor.run { + ChatModel.shared.conditions = r + } + if let enabledOperators = enabledOperators(r.serverOperators) { + let r2 = try await setServerOperators(operators: enabledOperators) + await MainActor.run { + ChatModel.shared.conditions = r2 + continueToNextStep() + } + } else { + await MainActor.run { + continueToNextStep() + } + } + } catch let error { + await MainActor.run { + showAlert( + NSLocalizedString("Error accepting conditions", comment: "alert title"), + message: responseError(error) + ) + } + } + } + } label: { + Text("Accept conditions") + } + .buttonStyle(OnboardingButtonStyle()) + } + } + + private func enabledOperators(_ operators: [ServerOperator]) -> [ServerOperator]? { + var ops = operators + if !ops.isEmpty { + for i in 0.. some View { + NavigationLink() { + OperatorInfoView(serverOperator: op) + .navigationBarTitle("Network operator") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + HStack { + Image(op.logo(colorScheme)) + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + Text(op.tradeName) + } + } + } +} + +#Preview { + ChooseServerOperators(onboarding: true) +} diff --git a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift index a62f609833..14ad9dfb08 100644 --- a/apps/ios/Shared/Views/Onboarding/CreateProfile.swift +++ b/apps/ios/Shared/Views/Onboarding/CreateProfile.swift @@ -38,7 +38,7 @@ struct CreateProfile: View { TextField("Enter your name…", text: $displayName) .focused($focusDisplayName) Button { - createProfile(displayName, showAlert: { alert = $0 }, dismiss: dismiss) + createProfile() } label: { Label("Create profile", systemImage: "checkmark") } @@ -77,7 +77,35 @@ struct CreateProfile: View { focusDisplayName = true } } - .keyboardPadding() + } + + private func createProfile() { + hideKeyboard() + let profile = Profile( + displayName: displayName.trimmingCharacters(in: .whitespaces), + fullName: "" + ) + let m = ChatModel.shared + do { + AppChatState.shared.set(.active) + m.currentUser = try apiCreateActiveUser(profile) + // .isEmpty check is redundant here, but it makes it clearer what is going on + if m.users.isEmpty || m.users.allSatisfy({ $0.user.hidden }) { + try startChat() + withAnimation { + onboardingStageDefault.set(.step3_ChooseServerOperators) + m.onboardingStage = .step3_ChooseServerOperators + } + } else { + onboardingStageDefault.set(.onboardingComplete) + m.onboardingStage = .onboardingComplete + dismiss() + m.users = try listUsers() + try getUserChatData() + } + } catch let error { + showCreateProfileAlert(showAlert: { alert = $0 }, error) + } } } @@ -87,132 +115,150 @@ struct CreateFirstProfile: View { @Environment(\.dismiss) var dismiss @State private var displayName: String = "" @FocusState private var focusDisplayName + @State private var nextStepNavLinkActive = false var body: some View { - VStack(alignment: .leading) { - Group { + VStack(alignment: .leading, spacing: 20) { + VStack(alignment: .center, spacing: 20) { Text("Create your profile") .font(.largeTitle) .bold() + .multilineTextAlignment(.center) + Text("Your profile, contacts and delivered messages are stored on your device.") + .font(.callout) .foregroundColor(theme.colors.secondary) + .multilineTextAlignment(.center) + Text("The profile is only shared with your contacts.") + .font(.callout) .foregroundColor(theme.colors.secondary) - .padding(.bottom) + .multilineTextAlignment(.center) } - .padding(.bottom) + .frame(maxWidth: .infinity) // Ensures it takes up the full width + .padding(.horizontal, 10) - ZStack(alignment: .topLeading) { + HStack { let name = displayName.trimmingCharacters(in: .whitespaces) let validName = mkValidName(name) - if name != validName { - Button { - showAlert(.invalidNameError(validName: validName)) - } label: { - Image(systemName: "exclamationmark.circle").foregroundColor(.red) + ZStack(alignment: .trailing) { + TextField("Enter your name…", text: $displayName) + .focused($focusDisplayName) + .padding(.horizontal) + .padding(.vertical, 10) + .background( + RoundedRectangle(cornerRadius: 10, style: .continuous) + .fill(Color(uiColor: .tertiarySystemFill)) + ) + if name != validName { + Button { + showAlert(.invalidNameError(validName: validName)) + } label: { + Image(systemName: "exclamationmark.circle") + .foregroundColor(.red) + .padding(.horizontal, 10) + } } - } else { - Image(systemName: "exclamationmark.circle").foregroundColor(.clear) } - TextField("Enter your name…", text: $displayName) - .focused($focusDisplayName) - .padding(.leading, 32) } - .padding(.bottom) + .padding(.top) + Spacer() - onboardingButtons() + + VStack(spacing: 10) { + createProfileButton() + if !focusDisplayName { + onboardingButtonPlaceholder() + } + } } .onAppear() { focusDisplayName = true setLastVersionDefault() } - .padding() + .padding(.horizontal, 25) + .padding(.top, 10) + .padding(.bottom, 25) .frame(maxWidth: .infinity, alignment: .leading) - .keyboardPadding() } - func onboardingButtons() -> some View { - HStack { + func createProfileButton() -> some View { + ZStack { Button { - hideKeyboard() - withAnimation { - m.onboardingStage = .step1_SimpleXInfo - } + createProfile() } label: { - HStack { - Image(systemName: "lessthan") - Text("About SimpleX") - } - } - - Spacer() - - Button { - createProfile(displayName, showAlert: showAlert, dismiss: dismiss) - } label: { - HStack { - Text("Create") - Image(systemName: "greaterthan") - } + Text("Create profile") } + .buttonStyle(OnboardingButtonStyle(isDisabled: !canCreateProfile(displayName))) .disabled(!canCreateProfile(displayName)) + + NavigationLink(isActive: $nextStepNavLinkActive) { + nextStepDestinationView() + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() } } private func showAlert(_ alert: UserProfileAlert) { AlertManager.shared.showAlert(userProfileAlert(alert, $displayName)) } + + private func nextStepDestinationView() -> some View { + ChooseServerOperators(onboarding: true) + .navigationBarBackButtonHidden(true) + .modifier(ThemedBackground()) + } + + private func createProfile() { + hideKeyboard() + let profile = Profile( + displayName: displayName.trimmingCharacters(in: .whitespaces), + fullName: "" + ) + let m = ChatModel.shared + do { + AppChatState.shared.set(.active) + m.currentUser = try apiCreateActiveUser(profile) + try startChat(onboarding: true) + onboardingStageDefault.set(.step3_ChooseServerOperators) + nextStepNavLinkActive = true + } catch let error { + showCreateProfileAlert(showAlert: showAlert, error) + } + } } -private func createProfile(_ displayName: String, showAlert: (UserProfileAlert) -> Void, dismiss: DismissAction) { - hideKeyboard() - let profile = Profile( - displayName: displayName.trimmingCharacters(in: .whitespaces), - fullName: "" - ) +private func showCreateProfileAlert( + showAlert: (UserProfileAlert) -> Void, + _ error: Error +) { let m = ChatModel.shared - do { - AppChatState.shared.set(.active) - m.currentUser = try apiCreateActiveUser(profile) - // .isEmpty check is redundant here, but it makes it clearer what is going on - if m.users.isEmpty || m.users.allSatisfy({ $0.user.hidden }) { - try startChat() - withAnimation { - onboardingStageDefault.set(.step3_CreateSimpleXAddress) - m.onboardingStage = .step3_CreateSimpleXAddress - } + switch error as? ChatResponse { + case .chatCmdError(_, .errorStore(.duplicateName)), + .chatCmdError(_, .error(.userExists)): + if m.currentUser == nil { + AlertManager.shared.showAlert(duplicateUserAlert) } else { - onboardingStageDefault.set(.onboardingComplete) - m.onboardingStage = .onboardingComplete - dismiss() - m.users = try listUsers() - try getUserChatData() + showAlert(.duplicateUserError) } - } catch let error { - switch error as? ChatResponse { - case .chatCmdError(_, .errorStore(.duplicateName)), - .chatCmdError(_, .error(.userExists)): - if m.currentUser == nil { - AlertManager.shared.showAlert(duplicateUserAlert) - } 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 { - AlertManager.shared.showAlert(creatUserErrorAlert(err)) - } else { - showAlert(.createUserError(error: err)) - } + 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 { + AlertManager.shared.showAlert(creatUserErrorAlert(err)) + } else { + showAlert(.createUserError(error: err)) } - logger.error("Failed to create user or start chat: \(responseError(error))") } + logger.error("Failed to create user or start chat: \(responseError(error))") } private func canCreateProfile(_ displayName: String) -> Bool { diff --git a/apps/ios/Shared/Views/Onboarding/HowItWorks.swift b/apps/ios/Shared/Views/Onboarding/HowItWorks.swift index c1975765d2..7452d74e91 100644 --- a/apps/ios/Shared/Views/Onboarding/HowItWorks.swift +++ b/apps/ios/Shared/Views/Onboarding/HowItWorks.swift @@ -9,24 +9,24 @@ import SwiftUI struct HowItWorks: View { + @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject var m: ChatModel var onboarding: Bool + @Binding var createProfileNavLinkActive: Bool var body: some View { VStack(alignment: .leading) { Text("How SimpleX works") .font(.largeTitle) + .bold() .padding(.vertical) ScrollView { VStack(alignment: .leading) { Group { - Text("Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*") - Text("To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts.") - Text("You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them.") - Text("Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**.") - if onboarding { - Text("Read more in our GitHub repository.") - } else { + Text("To protect your privacy, SimpleX uses separate IDs for each of your contacts.") + Text("Only client devices store user profiles, contacts, groups, and messages.") + Text("All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages.") + if !onboarding { Text("Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme).") } } @@ -37,19 +37,34 @@ struct HowItWorks: View { Spacer() if onboarding { - OnboardingActionButton() - .padding(.bottom, 8) + VStack(spacing: 10) { + createFirstProfileButton() + onboardingButtonPlaceholder() + } } } .lineLimit(10) - .padding() + .padding(onboarding ? 25 : 16) .frame(maxHeight: .infinity, alignment: .top) .modifier(ThemedBackground()) } + + private func createFirstProfileButton() -> some View { + Button { + dismiss() + createProfileNavLinkActive = true + } label: { + Text("Create your profile") + } + .buttonStyle(OnboardingButtonStyle(isDisabled: false)) + } } struct HowItWorks_Previews: PreviewProvider { static var previews: some View { - HowItWorks(onboarding: true) + HowItWorks( + onboarding: true, + createProfileNavLinkActive: Binding.constant(false) + ) } } diff --git a/apps/ios/Shared/Views/Onboarding/OnboardingView.swift b/apps/ios/Shared/Views/Onboarding/OnboardingView.swift index 438491b5f1..b2b1b8fa68 100644 --- a/apps/ios/Shared/Views/Onboarding/OnboardingView.swift +++ b/apps/ios/Shared/Views/Onboarding/OnboardingView.swift @@ -12,20 +12,39 @@ struct OnboardingView: View { var onboarding: OnboardingStage var body: some View { - switch onboarding { - case .step1_SimpleXInfo: SimpleXInfo(onboarding: true) - case .step2_CreateProfile: CreateFirstProfile() - case .step3_CreateSimpleXAddress: CreateSimpleXAddress() - case .step4_SetNotificationsMode: SetNotificationsMode() - case .onboardingComplete: EmptyView() + NavigationView { + switch onboarding { + case .step1_SimpleXInfo: + SimpleXInfo(onboarding: true) + .modifier(ThemedBackground()) + case .step2_CreateProfile: // deprecated + CreateFirstProfile() + .modifier(ThemedBackground()) + case .step3_CreateSimpleXAddress: // deprecated + CreateSimpleXAddress() + case .step3_ChooseServerOperators: + ChooseServerOperators(onboarding: true) + .navigationBarBackButtonHidden(true) + .modifier(ThemedBackground()) + case .step4_SetNotificationsMode: + SetNotificationsMode() + .navigationBarBackButtonHidden(true) + .modifier(ThemedBackground()) + case .onboardingComplete: EmptyView() + } } } } +func onboardingButtonPlaceholder() -> some View { + Spacer().frame(height: 40) +} + enum OnboardingStage: String, Identifiable { case step1_SimpleXInfo - case step2_CreateProfile - case step3_CreateSimpleXAddress + case step2_CreateProfile // deprecated + case step3_CreateSimpleXAddress // deprecated + case step3_ChooseServerOperators case step4_SetNotificationsMode case onboardingComplete diff --git a/apps/ios/Shared/Views/Onboarding/SetNotificationsMode.swift b/apps/ios/Shared/Views/Onboarding/SetNotificationsMode.swift index 7681a42a77..97e1f49382 100644 --- a/apps/ios/Shared/Views/Onboarding/SetNotificationsMode.swift +++ b/apps/ios/Shared/Views/Onboarding/SetNotificationsMode.swift @@ -13,42 +13,54 @@ struct SetNotificationsMode: View { @EnvironmentObject var m: ChatModel @State private var notificationMode = NotificationsMode.instant @State private var showAlert: NotificationAlert? + @State private var showInfo: Bool = false var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - Text("Push notifications") - .font(.largeTitle) - .bold() - .frame(maxWidth: .infinity) + GeometryReader { g in + ScrollView { + VStack(alignment: .center, spacing: 20) { + Text("Push notifications") + .font(.largeTitle) + .bold() + .padding(.top, 25) + + infoText() + + Spacer() - Text("Send notifications:") - ForEach(NotificationsMode.values) { mode in - NtfModeSelector(mode: mode, selection: $notificationMode) - } - - Spacer() - - Button { - if let token = m.deviceToken { - setNotificationsMode(token, notificationMode) - } else { - AlertManager.shared.showAlertMsg(title: "No device token!") + ForEach(NotificationsMode.values) { mode in + NtfModeSelector(mode: mode, selection: $notificationMode) } - onboardingStageDefault.set(.onboardingComplete) - m.onboardingStage = .onboardingComplete - } label: { - if case .off = notificationMode { - Text("Use chat") - } else { - Text("Enable notifications") + + Spacer() + + VStack(spacing: 10) { + Button { + if let token = m.deviceToken { + setNotificationsMode(token, notificationMode) + } else { + AlertManager.shared.showAlertMsg(title: "No device token!") + } + onboardingStageDefault.set(.onboardingComplete) + m.onboardingStage = .onboardingComplete + } label: { + if case .off = notificationMode { + Text("Use chat") + } else { + Text("Enable notifications") + } + } + .buttonStyle(OnboardingButtonStyle()) + onboardingButtonPlaceholder() } } - .font(.title) - .frame(maxWidth: .infinity) + .padding(25) + .frame(minHeight: g.size.height) } - .padding() - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom) + } + .frame(maxHeight: .infinity) + .sheet(isPresented: $showInfo) { + NotificationsInfoView() } } @@ -75,6 +87,15 @@ struct SetNotificationsMode: View { } } } + + private func infoText() -> some View { + Button { + showInfo = true + } label: { + Label("How it affects privacy", systemImage: "info.circle") + .font(.headline) + } + } } struct NtfModeSelector: View { @@ -85,15 +106,25 @@ struct NtfModeSelector: View { var body: some View { ZStack { - VStack(alignment: .leading, spacing: 4) { - Text(mode.label) - .font(.headline) + HStack(spacing: 16) { + Image(systemName: mode.icon) + .resizable() + .scaledToFill() + .frame(width: mode.icon == "bolt" ? 14 : 18, height: 18) .foregroundColor(selection == mode ? theme.colors.primary : theme.colors.secondary) - Text(ntfModeDescription(mode)) - .lineLimit(10) - .font(.subheadline) + VStack(alignment: .leading, spacing: 4) { + Text(mode.label) + .font(.headline) + .foregroundColor(selection == mode ? theme.colors.primary : theme.colors.secondary) + Text(ntfModeShortDescription(mode)) + .lineLimit(2) + .font(.callout) + .fixedSize(horizontal: false, vertical: true) + } } - .padding(12) + .padding(.vertical, 12) + .padding(.trailing, 12) + .padding(.leading, 16) } .frame(maxWidth: .infinity, alignment: .leading) .background(tapped ? Color(uiColor: .secondarySystemFill) : theme.colors.background) @@ -109,6 +140,37 @@ struct NtfModeSelector: View { } } +struct NotificationsInfoView: View { + var body: some View { + VStack(alignment: .leading) { + Text("Notifications privacy") + .font(.largeTitle) + .bold() + .padding(.vertical) + ScrollView { + VStack(alignment: .leading) { + Group { + ForEach(NotificationsMode.values) { mode in + VStack(alignment: .leading, spacing: 4) { + (Text(Image(systemName: mode.icon)) + textSpace + Text(mode.label)) + .font(.headline) + .foregroundColor(.secondary) + Text(ntfModeDescription(mode)) + .lineLimit(10) + .font(.callout) + } + } + } + .padding(.bottom) + } + } + } + .padding() + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .modifier(ThemedBackground()) + } +} + struct NotificationsModeView_Previews: PreviewProvider { static var previews: some View { SetNotificationsMode() diff --git a/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift b/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift index ee5a618e68..a8704e964b 100644 --- a/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift +++ b/apps/ios/Shared/Views/Onboarding/SimpleXInfo.swift @@ -13,58 +13,58 @@ struct SimpleXInfo: View { @EnvironmentObject var m: ChatModel @Environment(\.colorScheme) var colorScheme: ColorScheme @State private var showHowItWorks = false + @State private var createProfileNavLinkActive = false var onboarding: Bool var body: some View { GeometryReader { g in ScrollView { VStack(alignment: .leading) { - Image(colorScheme == .light ? "logo" : "logo-light") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: g.size.width * 0.67) - .padding(.bottom, 8) - .frame(maxWidth: .infinity, minHeight: 48, alignment: .top) + VStack(alignment: .center, spacing: 10) { + Image(colorScheme == .light ? "logo" : "logo-light") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: g.size.width * 0.67) + .padding(.bottom, 8) + .padding(.leading, 4) + .frame(maxWidth: .infinity, minHeight: 48, alignment: .top) + + Button { + showHowItWorks = true + } label: { + Label("The future of messaging", systemImage: "info.circle") + .font(.headline) + } + } + + Spacer() VStack(alignment: .leading) { - Text("The next generation of private messaging") - .font(.title2) - .padding(.bottom, 30) - .padding(.horizontal, 40) - .frame(maxWidth: .infinity) - .multilineTextAlignment(.center) - infoRow("privacy", "Privacy redefined", - "The 1st platform without any user identifiers – private by design.", width: 48) - infoRow("shield", "Immune to spam and abuse", - "People can connect to you only via the links you share.", width: 46) - infoRow(colorScheme == .light ? "decentralized" : "decentralized-light", "Decentralized", - "Open-source protocol and code – anybody can run the servers.", width: 44) + onboardingInfoRow("privacy", "Privacy redefined", + "No user identifiers.", width: 48) + onboardingInfoRow("shield", "Immune to spam", + "You decide who can connect.", width: 46) + onboardingInfoRow(colorScheme == .light ? "decentralized" : "decentralized-light", "Decentralized", + "Anybody can host servers.", width: 46) } + .padding(.leading, 16) Spacer() + if onboarding { - OnboardingActionButton() - Spacer() + VStack(spacing: 10) { + createFirstProfileButton() - Button { - m.migrationState = .pasteOrScanLink - } label: { - Label("Migrate from another device", systemImage: "tray.and.arrow.down") - .font(.subheadline) + Button { + m.migrationState = .pasteOrScanLink + } label: { + Label("Migrate from another device", systemImage: "tray.and.arrow.down") + .font(.system(size: 17, weight: .semibold)) + .frame(minHeight: 40) + } + .frame(maxWidth: .infinity) } - .padding(.bottom, 8) - .frame(maxWidth: .infinity) } - - Button { - showHowItWorks = true - } label: { - Label("How it works", systemImage: "info.circle") - .font(.subheadline) - } - .padding(.bottom, 8) - .frame(maxWidth: .infinity) - } .frame(minHeight: g.size.height) } @@ -83,76 +83,59 @@ struct SimpleXInfo: View { } } .sheet(isPresented: $showHowItWorks) { - HowItWorks(onboarding: onboarding) + HowItWorks( + onboarding: onboarding, + createProfileNavLinkActive: $createProfileNavLinkActive + ) } } .frame(maxHeight: .infinity) - .padding() + .padding(.horizontal, 25) + .padding(.top, 75) + .padding(.bottom, 25) } - private func infoRow(_ image: String, _ title: LocalizedStringKey, _ text: LocalizedStringKey, width: CGFloat) -> some View { + private func onboardingInfoRow(_ image: String, _ title: LocalizedStringKey, _ text: LocalizedStringKey, width: CGFloat) -> some View { HStack(alignment: .top) { Image(image) .resizable() .scaledToFit() .frame(width: width, height: 54) .frame(width: 54) - .padding(.top, 4) - .padding(.leading, 4) .padding(.trailing, 10) VStack(alignment: .leading, spacing: 4) { Text(title).font(.headline) Text(text).frame(minHeight: 40, alignment: .top) + .font(.callout) + .lineLimit(3) + .fixedSize(horizontal: false, vertical: true) } + .padding(.top, 4) + } + .padding(.bottom, 12) + } + + private func createFirstProfileButton() -> some View { + ZStack { + Button { + createProfileNavLinkActive = true + } label: { + Text("Create your profile") + } + .buttonStyle(OnboardingButtonStyle(isDisabled: false)) + + NavigationLink(isActive: $createProfileNavLinkActive) { + CreateFirstProfile() + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() } - .padding(.bottom, 20) - .padding(.trailing, 6) } } -struct OnboardingActionButton: View { - @EnvironmentObject var m: ChatModel - @Environment(\.colorScheme) var colorScheme - - var body: some View { - if m.currentUser == nil { - actionButton("Create your profile", onboarding: .step2_CreateProfile) - } else { - actionButton("Make a private connection", onboarding: .onboardingComplete) - } - } - - private func actionButton(_ label: LocalizedStringKey, onboarding: OnboardingStage) -> some View { - Button { - withAnimation { - onboardingStageDefault.set(onboarding) - m.onboardingStage = onboarding - } - } label: { - HStack { - Text(label).font(.title2) - Image(systemName: "greaterthan") - } - } - .frame(maxWidth: .infinity) - .padding(.bottom) - } - - private func actionButton(_ label: LocalizedStringKey, action: @escaping () -> Void) -> some View { - Button { - withAnimation { - action() - } - } label: { - HStack { - Text(label).font(.title2) - Image(systemName: "greaterthan") - } - } - .frame(maxWidth: .infinity) - .padding(.bottom) - } -} +let textSpace = Text(verbatim: " ") struct SimpleXInfo_Previews: PreviewProvider { static var previews: some View { diff --git a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift index ed3adcfe7d..182c5652d7 100644 --- a/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift +++ b/apps/ios/Shared/Views/Onboarding/WhatsNewView.swift @@ -7,190 +7,209 @@ // import SwiftUI +import SimpleXChat private struct VersionDescription { var version: String var post: URL? - var features: [FeatureDescription] + var features: [Feature] } -private struct FeatureDescription { - var icon: String? - var title: LocalizedStringKey - var description: LocalizedStringKey? +private enum Feature: Identifiable { + case feature(Description) + case view(FeatureView) + + var id: LocalizedStringKey { + switch self { + case let .feature(d): d.title + case let .view(v): v.title + } + } +} + +private struct Description { + let icon: String? + let title: LocalizedStringKey + let description: LocalizedStringKey? var subfeatures: [(icon: String, description: LocalizedStringKey)] = [] } +private struct FeatureView { + let icon: String? + let title: LocalizedStringKey + let view: () -> any View +} + private let versionDescriptions: [VersionDescription] = [ VersionDescription( version: "v4.2", post: URL(string: "https://simplex.chat/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html"), features: [ - FeatureDescription( + .feature(Description( icon: "checkmark.shield", title: "Security assessment", description: "SimpleX Chat security was audited by Trail of Bits." - ), - FeatureDescription( + )), + .feature(Description( icon: "person.2", title: "Group links", description: "Admins can create the links to join groups." - ), - FeatureDescription( + )), + .feature(Description( icon: "checkmark", title: "Auto-accept contact requests", description: "With optional welcome message." - ), + )), ] ), VersionDescription( version: "v4.3", post: URL(string: "https://simplex.chat/blog/20221206-simplex-chat-v4.3-voice-messages.html"), features: [ - FeatureDescription( + .feature(Description( icon: "mic", title: "Voice messages", description: "Max 30 seconds, received instantly." - ), - FeatureDescription( + )), + .feature(Description( icon: "trash.slash", title: "Irreversible message deletion", description: "Your contacts can allow full message deletion." - ), - FeatureDescription( + )), + .feature(Description( icon: "externaldrive.connected.to.line.below", title: "Improved server configuration", description: "Add servers by scanning QR codes." - ), - FeatureDescription( + )), + .feature(Description( icon: "eye.slash", title: "Improved privacy and security", description: "Hide app screen in the recent apps." - ), + )), ] ), VersionDescription( version: "v4.4", post: URL(string: "https://simplex.chat/blog/20230103-simplex-chat-v4.4-disappearing-messages.html"), features: [ - FeatureDescription( + .feature(Description( icon: "stopwatch", title: "Disappearing messages", description: "Sent messages will be deleted after set time." - ), - FeatureDescription( + )), + .feature(Description( icon: "ellipsis.circle", title: "Live messages", description: "Recipients see updates as you type them." - ), - FeatureDescription( + )), + .feature(Description( icon: "checkmark.shield", title: "Verify connection security", description: "Compare security codes with your contacts." - ), - FeatureDescription( + )), + .feature(Description( icon: "camera", title: "GIFs and stickers", description: "Send them from gallery or custom keyboards." - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "French interface", description: "Thanks to the users – contribute via Weblate!" - ) + )), ] ), VersionDescription( version: "v4.5", post: URL(string: "https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html"), features: [ - FeatureDescription( + .feature(Description( icon: "person.crop.rectangle.stack", title: "Multiple chat profiles", description: "Different names, avatars and transport isolation." - ), - FeatureDescription( + )), + .feature(Description( icon: "rectangle.and.pencil.and.ellipsis", title: "Message draft", description: "Preserve the last message draft, with attachments." - ), - FeatureDescription( + )), + .feature(Description( icon: "network.badge.shield.half.filled", title: "Transport isolation", description: "By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)." - ), - FeatureDescription( + )), + .feature(Description( icon: "lock.doc", title: "Private filenames", description: "To protect timezone, image/voice files use UTC." - ), - FeatureDescription( + )), + .feature(Description( icon: "battery.25", title: "Reduced battery usage", description: "More improvements are coming soon!" - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "Italian interface", description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ) + )), ] ), VersionDescription( version: "v4.6", post: URL(string: "https://simplex.chat/blog/20230328-simplex-chat-v4-6-hidden-profiles.html"), features: [ - FeatureDescription( + .feature(Description( icon: "lock", title: "Hidden chat profiles", description: "Protect your chat profiles with a password!" - ), - FeatureDescription( + )), + .feature(Description( icon: "phone.arrow.up.right", title: "Audio and video calls", description: "Fully re-implemented - work in background!" - ), - FeatureDescription( + )), + .feature(Description( icon: "flag", title: "Group moderation", description: "Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" - ), - FeatureDescription( + )), + .feature(Description( icon: "plus.message", title: "Group welcome message", description: "Set the message shown to new members!" - ), - FeatureDescription( + )), + .feature(Description( icon: "battery.50", title: "Further reduced battery usage", description: "More improvements are coming soon!" - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "Chinese and Spanish interface", description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ), + )), ] ), VersionDescription( version: "v5.0", post: URL(string: "https://simplex.chat/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html"), features: [ - FeatureDescription( + .feature(Description( icon: "arrow.up.doc", title: "Videos and files up to 1gb", description: "Fast and no wait until the sender is online!" - ), - FeatureDescription( + )), + .feature(Description( icon: "lock", title: "App passcode", description: "Set it instead of system authentication." - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "Polish interface", description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ), + )), ] ), // Also @@ -200,240 +219,240 @@ private let versionDescriptions: [VersionDescription] = [ version: "v5.1", post: URL(string: "https://simplex.chat/blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.html"), features: [ - FeatureDescription( + .feature(Description( icon: "face.smiling", title: "Message reactions", description: "Finally, we have them! 🚀" - ), - FeatureDescription( + )), + .feature(Description( icon: "arrow.up.message", title: "Better messages", description: "- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." - ), - FeatureDescription( + )), + .feature(Description( icon: "lock", title: "Self-destruct passcode", description: "All data is erased when it is entered." - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "Japanese interface", description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ), + )), ] ), VersionDescription( version: "v5.2", post: URL(string: "https://simplex.chat/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.html"), features: [ - FeatureDescription( + .feature(Description( icon: "checkmark", title: "Message delivery receipts!", description: "The second tick we missed! ✅" - ), - FeatureDescription( + )), + .feature(Description( icon: "star", title: "Find chats faster", description: "Filter unread and favorite chats." - ), - FeatureDescription( + )), + .feature(Description( icon: "exclamationmark.arrow.triangle.2.circlepath", title: "Keep your connections", description: "Fix encryption after restoring backups." - ), - FeatureDescription( + )), + .feature(Description( icon: "stopwatch", title: "Make one message disappear", description: "Even when disabled in the conversation." - ), - FeatureDescription( + )), + .feature(Description( icon: "gift", title: "A few more things", description: "- more stable message delivery.\n- a bit better groups.\n- and more!" - ), + )), ] ), VersionDescription( version: "v5.3", post: URL(string: "https://simplex.chat/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.html"), features: [ - FeatureDescription( + .feature(Description( icon: "desktopcomputer", title: "New desktop app!", description: "Create new profile in [desktop app](https://simplex.chat/downloads/). 💻" - ), - FeatureDescription( + )), + .feature(Description( icon: "lock", title: "Encrypt stored files & media", description: "App encrypts new local files (except videos)." - ), - FeatureDescription( + )), + .feature(Description( icon: "magnifyingglass", title: "Discover and join groups", description: "- 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." - ), - FeatureDescription( + )), + .feature(Description( icon: "theatermasks", title: "Simplified incognito mode", description: "Toggle incognito when connecting." - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "\(4) new interface languages", description: "Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ), + )), ] ), VersionDescription( version: "v5.4", post: URL(string: "https://simplex.chat/blog/20231125-simplex-chat-v5-4-link-mobile-desktop-quantum-resistant-better-groups.html"), features: [ - FeatureDescription( + .feature(Description( icon: "desktopcomputer", title: "Link mobile and desktop apps! 🔗", description: "Via secure quantum resistant protocol." - ), - FeatureDescription( + )), + .feature(Description( icon: "person.2", title: "Better groups", description: "Faster joining and more reliable messages." - ), - FeatureDescription( + )), + .feature(Description( icon: "theatermasks", title: "Incognito groups", description: "Create a group using a random profile." - ), - FeatureDescription( + )), + .feature(Description( icon: "hand.raised", title: "Block group members", description: "To hide unwanted messages." - ), - FeatureDescription( + )), + .feature(Description( icon: "gift", title: "A few more things", description: "- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" - ), + )), ] ), 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( + .feature(Description( icon: "folder", title: "Private notes", description: "With encrypted files and media." - ), - FeatureDescription( + )), + .feature(Description( icon: "link", title: "Paste link to connect!", description: "Search bar accepts invitation links." - ), - FeatureDescription( + )), + .feature(Description( 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( + )), + .feature(Description( icon: "battery.50", title: "Improved message delivery", description: "With reduced battery usage." - ), - FeatureDescription( + )), + .feature(Description( 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)!" - ), + )), ] ), VersionDescription( version: "v5.6", post: URL(string: "https://simplex.chat/blog/20240323-simplex-network-privacy-non-profit-v5-6-quantum-resistant-e2e-encryption-simple-migration.html"), features: [ - FeatureDescription( + .feature(Description( icon: "key", title: "Quantum resistant encryption", description: "Enable in direct chats (BETA)!" - ), - FeatureDescription( + )), + .feature(Description( icon: "tray.and.arrow.up", title: "App data migration", description: "Migrate to another device via QR code." - ), - FeatureDescription( + )), + .feature(Description( icon: "phone", title: "Picture-in-picture calls", description: "Use the app while in the call." - ), - FeatureDescription( + )), + .feature(Description( icon: "hand.raised", title: "Safer groups", description: "Admins can block a member for all." - ), - FeatureDescription( + )), + .feature(Description( icon: "character", title: "Hungarian interface", description: "Thanks to the users – [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" - ), + )), ] ), VersionDescription( version: "v5.7", post: URL(string: "https://simplex.chat/blog/20240426-simplex-legally-binding-transparency-v5-7-better-user-experience.html"), features: [ - FeatureDescription( + .feature(Description( icon: "key", title: "Quantum resistant encryption", description: "Will be enabled in direct chats!" - ), - FeatureDescription( + )), + .feature(Description( icon: "arrowshape.turn.up.forward", title: "Forward and save messages", description: "Message source remains private." - ), - FeatureDescription( + )), + .feature(Description( icon: "music.note", title: "In-call sounds", description: "When connecting audio and video calls." - ), - FeatureDescription( + )), + .feature(Description( icon: "person.crop.square", title: "Shape profile images", description: "Square, circle, or anything in between." - ), - FeatureDescription( + )), + .feature(Description( icon: "antenna.radiowaves.left.and.right", title: "Network management", description: "More reliable network connection." - ) + )), ] ), VersionDescription( version: "v5.8", post: URL(string: "https://simplex.chat/blog/20240604-simplex-chat-v5.8-private-message-routing-chat-themes.html"), features: [ - FeatureDescription( + .feature(Description( icon: "arrow.forward", title: "Private message routing 🚀", description: "Protect your IP address from the messaging relays chosen by your contacts.\nEnable in *Network & servers* settings." - ), - FeatureDescription( + )), + .feature(Description( icon: "network.badge.shield.half.filled", title: "Safely receive files", description: "Confirm files from unknown servers." - ), - FeatureDescription( + )), + .feature(Description( icon: "battery.50", title: "Improved message delivery", description: "With reduced battery usage." - ) + )), ] ), VersionDescription( version: "v6.0", post: URL(string: "https://simplex.chat/blog/20240814-simplex-chat-vision-funding-v6-private-routing-new-user-experience.html"), features: [ - FeatureDescription( + .feature(Description( icon: nil, title: "New chat experience 🎉", description: nil, @@ -444,8 +463,8 @@ private let versionDescriptions: [VersionDescription] = [ ("platter.filled.bottom.and.arrow.down.iphone", "Use the app with one hand."), ("paintpalette", "Color chats with the new themes."), ] - ), - FeatureDescription( + )), + .feature(Description( icon: nil, title: "New media options", description: nil, @@ -454,19 +473,73 @@ private let versionDescriptions: [VersionDescription] = [ ("play.circle", "Play from the chat list."), ("circle.filled.pattern.diagonalline.rectangle", "Blur for better privacy.") ] - ), - FeatureDescription( + )), + .feature(Description( icon: "arrow.forward", title: "Private message routing 🚀", description: "It protects your IP address and connections." - ), - FeatureDescription( + )), + .feature(Description( icon: "network", title: "Better networking", description: "Connection and servers status." - ) + )), ] ), + VersionDescription( + version: "v6.1", + post: URL(string: "https://simplex.chat/blog/20241014-simplex-network-v6-1-security-review-better-calls-user-experience.html"), + features: [ + .feature(Description( + icon: "checkmark.shield", + title: "Better security ✅", + description: "SimpleX protocols reviewed by Trail of Bits." + )), + .feature(Description( + icon: "video", + title: "Better calls", + description: "Switch audio and video during the call." + )), + .feature(Description( + icon: "bolt", + title: "Better notifications", + description: "Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" + )), + .feature(Description( + icon: nil, + title: "Better user experience", + description: nil, + subfeatures: [ + ("link", "Switch chat profile for 1-time invitations."), + ("message", "Customizable message shape."), + ("calendar", "Better message dates."), + ("arrowshape.turn.up.right", "Forward up to 20 messages at once."), + ("flag", "Delete or moderate up to 200 messages.") + ] + )), + ] + ), + VersionDescription( + version: "v6.2", + post: URL(string: "https://simplex.chat/blog/20241210-simplex-network-v6-2-servers-by-flux-business-chats.html"), + features: [ + .view(FeatureView( + icon: nil, + title: "Network decentralization", + view: { NewOperatorsView() } + )), + .feature(Description( + icon: "briefcase", + title: "Business chats", + description: "Privacy for your customers." + )), + .feature(Description( + icon: "bolt", + title: "More reliable notifications", + description: "Delivered even when Apple drops them." + )), + ] + ) ] private let lastVersion = versionDescriptions.last!.version @@ -481,14 +554,68 @@ func shouldShowWhatsNew() -> Bool { return v != lastVersion } +fileprivate struct NewOperatorsView: View { + @State private var showOperatorsSheet = false + + var body: some View { + VStack(alignment: .leading) { + Image((operatorsInfo[.flux] ?? ServerOperator.dummyOperatorInfo).largeLogo) + .resizable() + .scaledToFit() + .frame(height: 48) + Text("The second preset operator in the app!") + .multilineTextAlignment(.leading) + .lineLimit(10) + HStack { + Button("Enable Flux") { + showOperatorsSheet = true + } + Text("for better metadata privacy.") + } + } + .sheet(isPresented: $showOperatorsSheet) { + NavigationView { + ChooseServerOperators(onboarding: false) + .modifier(ThemedBackground()) + } + } + } +} + +private enum WhatsNewViewSheet: Identifiable { + case showConditions + + var id: String { + switch self { + case .showConditions: return "showConditions" + } + } +} + struct WhatsNewView: View { @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject var theme: AppTheme @State var currentVersion = versionDescriptions.count - 1 @State var currentVersionNav = versionDescriptions.count - 1 var viaSettings = false + var updatedConditions: Bool + @State private var sheetItem: WhatsNewViewSheet? = nil var body: some View { + whatsNewView() + .sheet(item: $sheetItem) { item in + switch item { + case .showConditions: + UsageConditionsView( + currUserServers: Binding.constant([]), + userServers: Binding.constant([]) + ) + .modifier(ThemedBackground(grouped: true)) + } + } + } + + private func whatsNewView() -> some View { VStack { TabView(selection: $currentVersion) { ForEach(Array(versionDescriptions.enumerated()), id: \.0) { (i, v) in @@ -499,9 +626,11 @@ struct WhatsNewView: View { .foregroundColor(theme.colors.secondary) .frame(maxWidth: .infinity) .padding(.vertical) - ForEach(v.features, id: \.title) { f in - featureDescription(f) - .padding(.bottom, 8) + ForEach(v.features) { f in + switch f { + case let .feature(d): featureDescription(d).padding(.bottom, 8) + case let .view(v): AnyView(v.view()).padding(.bottom, 8) + } } if let post = v.post { Link(destination: post) { @@ -511,13 +640,20 @@ struct WhatsNewView: View { } } } + if updatedConditions { + Button("View updated conditions") { + sheetItem = .showConditions + } + } if !viaSettings { Spacer() + Button("Ok") { dismiss() } .font(.title3) .frame(maxWidth: .infinity, alignment: .center) + Spacer() } } @@ -535,20 +671,24 @@ struct WhatsNewView: View { currentVersionNav = currentVersion } } - - private func featureDescription(_ f: FeatureDescription) -> some View { - VStack(alignment: .leading, spacing: 4) { - if let icon = f.icon { - HStack(alignment: .center, spacing: 4) { - Image(systemName: icon) - .symbolRenderingMode(.monochrome) - .foregroundColor(theme.colors.secondary) - .frame(minWidth: 30, alignment: .center) - Text(f.title).font(.title3).bold() - } - } else { - Text(f.title).font(.title3).bold() + + @ViewBuilder private func featureHeader(_ icon: String?, _ title: LocalizedStringKey) -> some View { + if let icon { + HStack(alignment: .center, spacing: 4) { + Image(systemName: icon) + .symbolRenderingMode(.monochrome) + .foregroundColor(theme.colors.secondary) + .frame(minWidth: 30, alignment: .center) + Text(title).font(.title3).bold() } + } else { + Text(title).font(.title3).bold() + } + } + + private func featureDescription(_ f: Description) -> some View { + VStack(alignment: .leading, spacing: 4) { + featureHeader(f.icon, f.title) if let d = f.description { Text(d) .multilineTextAlignment(.leading) @@ -603,6 +743,6 @@ struct WhatsNewView: View { struct NewFeaturesView_Previews: PreviewProvider { static var previews: some View { - WhatsNewView() + WhatsNewView(updatedConditions: false) } } diff --git a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift index be063334d3..67020e09e7 100644 --- a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift +++ b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift @@ -14,7 +14,6 @@ struct ConnectDesktopView: View { @EnvironmentObject var m: ChatModel @EnvironmentObject var theme: AppTheme @Environment(\.dismiss) var dismiss: DismissAction - var viaSettings = false @AppStorage(DEFAULT_DEVICE_NAME_FOR_REMOTE_ACCESS) private var deviceName = UIDevice.current.name @AppStorage(DEFAULT_CONFIRM_REMOTE_SESSIONS) private var confirmRemoteSessions = false @AppStorage(DEFAULT_CONNECT_REMOTE_VIA_MULTICAST) private var connectRemoteViaMulticast = true @@ -57,23 +56,6 @@ struct ConnectDesktopView: View { } var body: some View { - if viaSettings { - viewBody - .modifier(BackButton(label: "Back", disabled: Binding.constant(false)) { - if m.activeRemoteCtrl { - alert = .disconnectDesktop(action: .back) - } else { - dismiss() - } - }) - } else { - NavigationView { - viewBody - } - } - } - - var viewBody: some View { Group { let discovery = m.remoteCtrlSession?.discovery if discovery == true || (discovery == nil && !showConnectScreen) { @@ -286,7 +268,7 @@ struct ConnectDesktopView: View { private func ctrlDeviceNameText(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?) -> Text { var t = Text(rc?.deviceViewName ?? session.ctrlAppInfo?.deviceName ?? "") if (rc == nil) { - t = t + Text(" ") + Text("(new)").italic() + t = t + textSpace + Text("(new)").italic() } return t } @@ -295,7 +277,7 @@ struct ConnectDesktopView: View { let v = session.ctrlAppInfo?.appVersionRange.maxVersion var t = Text("v\(v ?? "")") if v != session.appVersion { - t = t + Text(" ") + Text("(this device v\(session.appVersion))").italic() + t = t + textSpace + Text("(this device v\(session.appVersion))").italic() } return t } diff --git a/apps/ios/Shared/Views/TerminalView.swift b/apps/ios/Shared/Views/TerminalView.swift index d209ced128..23e1f783f7 100644 --- a/apps/ios/Shared/Views/TerminalView.swift +++ b/apps/ios/Shared/Views/TerminalView.swift @@ -105,7 +105,12 @@ struct TerminalView: View { } } .navigationViewStyle(.stack) - .navigationTitle("Chat console") + .toolbar { + // Redaction broken for `.navigationTitle` - using a toolbar item instead. + ToolbarItem(placement: .principal) { + Text("Chat console").font(.headline) + } + } .modifier(ThemedBackground()) } @@ -160,7 +165,7 @@ struct TerminalView_Previews: PreviewProvider { let chatModel = ChatModel() chatModel.terminalItems = [ .resp(.now, ChatResponse.response(type: "contactSubscribed", json: "{}")), - .resp(.now, ChatResponse.response(type: "newChatItem", json: "{}")) + .resp(.now, ChatResponse.response(type: "newChatItems", json: "{}")) ] return NavigationView { TerminalView() diff --git a/apps/ios/Shared/Views/UserSettings/AppSettings.swift b/apps/ios/Shared/Views/UserSettings/AppSettings.swift index 6247777bf2..44e0b20958 100644 --- a/apps/ios/Shared/Views/UserSettings/AppSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/AppSettings.swift @@ -19,9 +19,15 @@ extension AppSettings { val.hostMode = .publicHost val.requiredHostMode = true } - val.socksProxy = nil - setNetCfg(val) + if val.socksProxy != nil { + val.socksProxy = networkProxy?.toProxyString() + setNetCfg(val, networkProxy: networkProxy) + } else { + val.socksProxy = nil + setNetCfg(val, networkProxy: nil) + } } + if let val = networkProxy { networkProxyDefault.set(val) } if let val = privacyEncryptLocalFiles { privacyEncryptLocalFilesGroupDefault.set(val) } if let val = privacyAskToApproveRelays { privacyAskToApproveRelaysGroupDefault.set(val) } if let val = privacyAcceptImages { @@ -52,17 +58,21 @@ extension AppSettings { profileImageCornerRadiusGroupDefault.set(val) def.setValue(val, forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) } - if let val = uiColorScheme { def.setValue(val, forKey: DEFAULT_CURRENT_THEME) } - if let val = uiDarkColorScheme { def.setValue(val, forKey: DEFAULT_SYSTEM_DARK_THEME) } - if let val = uiCurrentThemeIds { def.setValue(val, forKey: DEFAULT_CURRENT_THEME_IDS) } - if let val = uiThemes { def.setValue(val.skipDuplicates(), forKey: DEFAULT_THEME_OVERRIDES) } + if let val = uiChatItemRoundness { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_ROUNDNESS)} + if let val = uiChatItemTail { def.setValue(val, forKey: DEFAULT_CHAT_ITEM_TAIL)} + if let val = uiColorScheme { currentThemeDefault.set(val) } + if let val = uiDarkColorScheme { systemDarkThemeDefault.set(val) } + if let val = uiCurrentThemeIds { currentThemeIdsDefault.set(val) } + if let val = uiThemes { themeOverridesDefault.set(val.skipDuplicates()) } if let val = oneHandUI { groupDefaults.setValue(val, forKey: GROUP_DEFAULT_ONE_HAND_UI) } + if let val = chatBottomBar { groupDefaults.setValue(val, forKey: GROUP_DEFAULT_CHAT_BOTTOM_BAR) } } public static var current: AppSettings { let def = UserDefaults.standard var c = AppSettings.defaults c.networkConfig = getNetCfg() + c.networkProxy = networkProxyDefault.get() c.privacyEncryptLocalFiles = privacyEncryptLocalFilesGroupDefault.get() c.privacyAskToApproveRelays = privacyAskToApproveRelaysGroupDefault.get() c.privacyAcceptImages = privacyAcceptImagesGroupDefault.get() @@ -84,11 +94,14 @@ extension AppSettings { c.iosCallKitEnabled = callKitEnabledGroupDefault.get() c.iosCallKitCallsInRecents = def.bool(forKey: DEFAULT_CALL_KIT_CALLS_IN_RECENTS) c.uiProfileImageCornerRadius = def.double(forKey: DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) + c.uiChatItemRoundness = def.double(forKey: DEFAULT_CHAT_ITEM_ROUNDNESS) + c.uiChatItemTail = def.bool(forKey: DEFAULT_CHAT_ITEM_TAIL) c.uiColorScheme = currentThemeDefault.get() c.uiDarkColorScheme = systemDarkThemeDefault.get() c.uiCurrentThemeIds = currentThemeIdsDefault.get() c.uiThemes = themeOverridesDefault.get() c.oneHandUI = groupDefaults.bool(forKey: GROUP_DEFAULT_ONE_HAND_UI) + c.chatBottomBar = groupDefaults.bool(forKey: GROUP_DEFAULT_CHAT_BOTTOM_BAR) return c } } diff --git a/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift b/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift index 73a789f108..4c61d592ac 100644 --- a/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/AppearanceSettings.swift @@ -33,6 +33,8 @@ struct AppearanceSettings: View { }() @State private var darkModeTheme: String = UserDefaults.standard.string(forKey: DEFAULT_SYSTEM_DARK_THEME) ?? DefaultTheme.DARK.themeName @AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var profileImageCornerRadius = defaultProfileImageCorner + @AppStorage(DEFAULT_CHAT_ITEM_ROUNDNESS) private var chatItemRoundness = defaultChatItemRoundness + @AppStorage(DEFAULT_CHAT_ITEM_TAIL) private var chatItemTail = true @AppStorage(GROUP_DEFAULT_ONE_HAND_UI, store: groupDefaults) private var oneHandUI = true @AppStorage(DEFAULT_TOOLBAR_MATERIAL) private var toolbarMaterial = ToolbarMaterial.defaultMaterial @@ -179,6 +181,14 @@ struct AppearanceSettings: View { } } + Section(header: Text("Message shape").foregroundColor(theme.colors.secondary)) { + HStack { + Text("Corner") + Slider(value: $chatItemRoundness, in: 0...1, step: 0.05) + } + Toggle("Tail", isOn: $chatItemTail) + } + Section(header: Text("Profile images").foregroundColor(theme.colors.secondary)) { HStack(spacing: 16) { if let img = m.currentUser?.image, img != "" { @@ -357,21 +367,22 @@ struct ChatThemePreview: View { let alice = ChatItem.getSample(1, CIDirection.directRcv, Date.now, NSLocalizedString("Good afternoon!", comment: "message preview")) let bob = ChatItem.getSample(2, CIDirection.directSnd, Date.now, NSLocalizedString("Good morning!", comment: "message preview"), quotedItem: CIQuote.getSample(alice.id, alice.meta.itemTs, alice.content.text, chatDir: alice.chatDir)) HStack { - ChatItemView(chat: Chat.sampleData, chatItem: alice, revealed: Binding.constant(false)) - .modifier(ChatItemClipped()) + ChatItemView(chat: Chat.sampleData, chatItem: alice) + .modifier(ChatItemClipped(alice, tailVisible: true)) Spacer() } HStack { Spacer() - ChatItemView(chat: Chat.sampleData, chatItem: bob, revealed: Binding.constant(false)) - .modifier(ChatItemClipped()) + ChatItemView(chat: Chat.sampleData, chatItem: bob) + .modifier(ChatItemClipped(bob, tailVisible: true)) .frame(alignment: .trailing) } } else { Rectangle().fill(.clear) } } - .padding(10) + .padding(.vertical, 10) + .padding(.horizontal, 16) .frame(maxWidth: .infinity) if let wallpaperType, let wallpaperImage = wallpaperType.image, let backgroundColor, let tintColor { @@ -572,11 +583,14 @@ struct CustomizeThemeView: View { } } - ImportExportThemeSection(perChat: nil, perUser: nil, save: { theme in + ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: nil) + } + .modifier( + ThemeImporter(isPresented: $showFileImporter) { theme in ThemeManager.saveAndApplyThemeOverrides(theme) saveThemeToDatabase(nil) - }) - } + } + ) /// When changing app theme, user overrides are hidden. User overrides will be returned back after closing Appearance screen, see ThemeDestinationPicker() .interactiveDismissDisabled(true) } @@ -584,10 +598,9 @@ struct CustomizeThemeView: View { struct ImportExportThemeSection: View { @EnvironmentObject var theme: AppTheme + @Binding var showFileImporter: Bool var perChat: ThemeModeOverride? var perUser: ThemeModeOverrides? - var save: (ThemeOverrides) -> Void - @State private var showFileImporter = false var body: some View { Section { @@ -615,39 +628,47 @@ struct ImportExportThemeSection: View { } label: { Text("Import theme").foregroundColor(theme.colors.primary) } - .fileImporter( - isPresented: $showFileImporter, - allowedContentTypes: [.data/*.plainText*/], - allowsMultipleSelection: false - ) { result in - if case let .success(files) = result, let fileURL = files.first { - do { - var fileSize: Int? = nil - if fileURL.startAccessingSecurityScopedResource() { - let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey]) - fileSize = resourceValues.fileSize - } - if let fileSize = fileSize, - // Same as Android/desktop - fileSize <= 5_500_000 { - if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) { - save(theme) - logger.error("Saved theme from file") - } else { - logger.error("Error decoding theme file") - } - fileURL.stopAccessingSecurityScopedResource() - } else { - fileURL.stopAccessingSecurityScopedResource() - let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary) - AlertManager.shared.showAlertMsg( - title: "Large file!", - message: "Currently maximum supported file size is \(prettyMaxFileSize)." - ) - } - } catch { - logger.error("Appearance fileImporter error \(error.localizedDescription)") + } + } +} + +struct ThemeImporter: ViewModifier { + @Binding var isPresented: Bool + var save: (ThemeOverrides) -> Void + + func body(content: Content) -> some View { + content.fileImporter( + isPresented: $isPresented, + allowedContentTypes: [.data/*.plainText*/], + allowsMultipleSelection: false + ) { result in + if case let .success(files) = result, let fileURL = files.first { + do { + var fileSize: Int? = nil + if fileURL.startAccessingSecurityScopedResource() { + let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey]) + fileSize = resourceValues.fileSize } + if let fileSize = fileSize, + // Same as Android/desktop + fileSize <= 5_500_000 { + if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) { + save(theme) + logger.error("Saved theme from file") + } else { + logger.error("Error decoding theme file") + } + fileURL.stopAccessingSecurityScopedResource() + } else { + fileURL.stopAccessingSecurityScopedResource() + let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary) + AlertManager.shared.showAlertMsg( + title: "Large file!", + message: "Currently maximum supported file size is \(prettyMaxFileSize)." + ) + } + } catch { + logger.error("Appearance fileImporter error \(error.localizedDescription)") } } } @@ -797,7 +818,7 @@ struct ThemeDestinationPicker: View { @Binding var customizeThemeIsOpen: Bool var body: some View { - let values = [(nil, "All profiles")] + m.users.filter { $0.user.activeUser }.map { ($0.user.userId, $0.user.chatViewName)} + let values = [(nil, NSLocalizedString("All profiles", comment: "profile dropdown"))] + m.users.filter { $0.user.activeUser }.map { ($0.user.userId, $0.user.chatViewName)} if values.contains(where: { (userId, text) in userId == themeUserDestination?.0 }) { Picker("Apply to", selection: $themeUserDest) { diff --git a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift index 4ef05bd998..513a6c2708 100644 --- a/apps/ios/Shared/Views/UserSettings/DeveloperView.swift +++ b/apps/ios/Shared/Views/UserSettings/DeveloperView.swift @@ -45,7 +45,7 @@ struct DeveloperView: View { } header: { Text("") } footer: { - ((developerTools ? Text("Show:") : Text("Hide:")) + Text(" ") + Text("Database IDs and Transport isolation option.")) + ((developerTools ? Text("Show:") : Text("Hide:")) + textSpace + Text("Database IDs and Transport isolation option.")) .foregroundColor(theme.colors.secondary) } diff --git a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift index a0250afddf..d9862aaac8 100644 --- a/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift +++ b/apps/ios/Shared/Views/UserSettings/IncognitoHelp.swift @@ -26,6 +26,7 @@ struct IncognitoHelp: View { Text("Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode).") } .listRowBackground(Color.clear) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) } .modifier(ThemedBackground()) } diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift deleted file mode 100644 index 155a3956be..0000000000 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// NetworkServersView.swift -// SimpleX (iOS) -// -// Created by Evgeny on 02/08/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -private enum NetworkAlert: Identifiable { - case error(err: String) - - var id: String { - switch self { - case let .error(err): return "error \(err)" - } - } -} - -struct NetworkAndServers: View { - @EnvironmentObject var m: ChatModel - @EnvironmentObject var theme: AppTheme - - var body: some View { - VStack { - List { - Section { - NavigationLink { - ProtocolServersView(serverProtocol: .smp) - .navigationTitle("Your SMP servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("Message servers") - } - - NavigationLink { - ProtocolServersView(serverProtocol: .xftp) - .navigationTitle("Your XFTP servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("Media & file servers") - } - - NavigationLink { - AdvancedNetworkSettings() - .navigationTitle("Advanced settings") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("Advanced network settings") - } - } header: { - Text("Messages & files") - .foregroundColor(theme.colors.secondary) - } - - Section(header: Text("Calls").foregroundColor(theme.colors.secondary)) { - NavigationLink { - RTCServers() - .navigationTitle("Your ICE servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("WebRTC ICE servers") - } - } - - Section(header: Text("Network connection").foregroundColor(theme.colors.secondary)) { - HStack { - Text(m.networkInfo.networkType.text) - Spacer() - Image(systemName: "circle.fill").foregroundColor(m.networkInfo.online ? .green : .red) - } - } - } - } - } -} - -struct NetworkServersView_Previews: PreviewProvider { - static var previews: some View { - NetworkAndServers() - } -} diff --git a/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/AdvancedNetworkSettings.swift similarity index 69% rename from apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift rename to apps/ios/Shared/Views/UserSettings/NetworkAndServers/AdvancedNetworkSettings.swift index 99c0a588eb..754ca3cf6b 100644 --- a/apps/ios/Shared/Views/UserSettings/AdvancedNetworkSettings.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/AdvancedNetworkSettings.swift @@ -36,6 +36,10 @@ struct AdvancedNetworkSettings: View { @State private var showSettingsAlert: NetworkSettingsAlert? @State private var onionHosts: OnionHosts = .no @State private var showSaveDialog = false + @State private var netProxy = networkProxyDefault.get() + @State private var currentNetProxy = networkProxyDefault.get() + @State private var useNetProxy = false + @State private var netProxyAuth = false var body: some View { VStack { @@ -102,6 +106,76 @@ struct AdvancedNetworkSettings: View { .foregroundColor(theme.colors.secondary) } + Section { + Toggle("Use SOCKS proxy", isOn: $useNetProxy) + Group { + TextField("IP address", text: $netProxy.host) + TextField( + "Port", + text: Binding( + get: { netProxy.port > 0 ? "\(netProxy.port)" : "" }, + set: { s in + netProxy.port = if let port = Int(s), port > 0 { + port + } else { + 0 + } + } + ) + ) + Toggle("Proxy requires password", isOn: $netProxyAuth) + if netProxyAuth { + TextField("Username", text: $netProxy.username) + PassphraseField( + key: $netProxy.password, + placeholder: "Password", + valid: NetworkProxy.validCredential(netProxy.password) + ) + } + } + .if(!useNetProxy) { $0.foregroundColor(theme.colors.secondary) } + .disabled(!useNetProxy) + } header: { + HStack { + Text("SOCKS proxy").foregroundColor(theme.colors.secondary) + if useNetProxy && !netProxy.valid { + Spacer() + Image(systemName: "exclamationmark.circle.fill").foregroundColor(.red) + } + } + } footer: { + if netProxyAuth { + Text("Your credentials may be sent unencrypted.") + .foregroundColor(theme.colors.secondary) + } else { + Text("Do not use credentials with proxy.") + .foregroundColor(theme.colors.secondary) + } + } + .onChange(of: useNetProxy) { useNetProxy in + netCfg.socksProxy = useNetProxy && currentNetProxy.valid + ? currentNetProxy.toProxyString() + : nil + netProxy = currentNetProxy + netProxyAuth = netProxy.username != "" || netProxy.password != "" + } + .onChange(of: netProxyAuth) { netProxyAuth in + if netProxyAuth { + netProxy.auth = currentNetProxy.auth + netProxy.username = currentNetProxy.username + netProxy.password = currentNetProxy.password + } else { + netProxy.auth = .username + netProxy.username = "" + netProxy.password = "" + } + } + .onChange(of: netProxy) { netProxy in + netCfg.socksProxy = useNetProxy && netProxy.valid + ? netProxy.toProxyString() + : nil + } + Section { Picker("Use .onion hosts", selection: $onionHosts) { ForEach(OnionHosts.values, id: \.self) { Text($0.text) } @@ -122,11 +196,14 @@ struct AdvancedNetworkSettings: View { if developerTools { Section { Picker("Transport isolation", selection: $netCfg.sessionMode) { - ForEach(TransportSessionMode.values, id: \.self) { Text($0.text) } + let modes = TransportSessionMode.values.contains(netCfg.sessionMode) + ? TransportSessionMode.values + : TransportSessionMode.values + [netCfg.sessionMode] + ForEach(modes, id: \.self) { Text($0.text) } } .frame(height: 36) } footer: { - Text(sessionModeInfo(netCfg.sessionMode)) + sessionModeInfo(netCfg.sessionMode) .foregroundColor(theme.colors.secondary) } } @@ -156,19 +233,19 @@ struct AdvancedNetworkSettings: View { Section { Button("Reset to defaults") { - updateNetCfgView(NetCfg.defaults) + updateNetCfgView(NetCfg.defaults, NetworkProxy.def) } .disabled(netCfg == NetCfg.defaults) Button("Set timeouts for proxy/VPN") { - updateNetCfgView(netCfg.withProxyTimeouts) + updateNetCfgView(netCfg.withProxyTimeouts, netProxy) } .disabled(netCfg.hasProxyTimeouts) Button("Save and reconnect") { showSettingsAlert = .update } - .disabled(netCfg == currentNetCfg) + .disabled(netCfg == currentNetCfg || (useNetProxy && !netProxy.valid)) } } } @@ -182,7 +259,8 @@ struct AdvancedNetworkSettings: View { if cfgLoaded { return } cfgLoaded = true currentNetCfg = getNetCfg() - updateNetCfgView(currentNetCfg) + currentNetProxy = networkProxyDefault.get() + updateNetCfgView(currentNetCfg, currentNetProxy) } .alert(item: $showSettingsAlert) { a in switch a { @@ -206,7 +284,7 @@ struct AdvancedNetworkSettings: View { if netCfg == currentNetCfg { dismiss() cfgLoaded = false - } else { + } else if !useNetProxy || netProxy.valid { showSaveDialog = true } }) @@ -221,18 +299,26 @@ struct AdvancedNetworkSettings: View { } } - private func updateNetCfgView(_ cfg: NetCfg) { + private func updateNetCfgView(_ cfg: NetCfg, _ proxy: NetworkProxy) { netCfg = cfg + netProxy = proxy onionHosts = OnionHosts(netCfg: netCfg) enableKeepAlive = netCfg.enableKeepAlive keepAliveOpts = netCfg.tcpKeepAlive ?? KeepAliveOpts.defaults + useNetProxy = netCfg.socksProxy != nil + netProxyAuth = switch netProxy.auth { + case .username: netProxy.username != "" || netProxy.password != "" + case .isolate: false + } } private func saveNetCfg() -> Bool { do { try setNetworkConfig(netCfg) currentNetCfg = netCfg - setNetCfg(netCfg) + setNetCfg(netCfg, networkProxy: useNetProxy ? netProxy : nil) + currentNetProxy = netProxy + networkProxyDefault.set(netProxy) return true } catch let error { let err = responseError(error) @@ -270,10 +356,13 @@ struct AdvancedNetworkSettings: View { } } - private func sessionModeInfo(_ mode: TransportSessionMode) -> LocalizedStringKey { - switch mode { - case .user: return "A separate TCP connection will be used **for each chat profile you have in the app**." - case .entity: return "A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." + private func sessionModeInfo(_ mode: TransportSessionMode) -> Text { + let userMode = Text("A separate TCP connection will be used **for each chat profile you have in the app**.") + return switch mode { + case .user: userMode + case .session: userMode + Text("\n") + Text("New SOCKS credentials will be used every time you start the app.") + case .server: userMode + Text("\n") + Text("New SOCKS credentials will be used for each server.") + case .entity: Text("A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.") } } diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ConditionsWebView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ConditionsWebView.swift new file mode 100644 index 0000000000..1e38b7d5ec --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ConditionsWebView.swift @@ -0,0 +1,83 @@ +// +// ConditionsWebView.swift +// SimpleX (iOS) +// +// Created by Stanislav Dmitrenko on 26.11.2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import WebKit + +struct ConditionsWebView: UIViewRepresentable { + @State var html: String + @EnvironmentObject var theme: AppTheme + @State var pageLoaded = false + + func makeUIView(context: Context) -> WKWebView { + let view = WKWebView() + view.backgroundColor = .clear + view.isOpaque = false + view.navigationDelegate = context.coordinator + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + // just to make sure that even if updateUIView will not be called for any reason, the page + // will be rendered anyway + if !pageLoaded { + loadPage(view) + } + } + return view + } + + func updateUIView(_ view: WKWebView, context: Context) { + loadPage(view) + } + + private func loadPage(_ webView: WKWebView) { + let styles = """ + + """ + let head = "\(styles)" + webView.loadHTMLString(head + html, baseURL: nil) + DispatchQueue.main.async { + pageLoaded = true + } + } + + func makeCoordinator() -> Cordinator { + Cordinator() + } + + class Cordinator: NSObject, WKNavigationDelegate { + func webView(_ webView: WKWebView, + decidePolicyFor navigationAction: WKNavigationAction, + decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + + guard let url = navigationAction.request.url else { return decisionHandler(.allow) } + + switch navigationAction.navigationType { + case .linkActivated: + decisionHandler(.cancel) + if url.absoluteString.starts(with: "https://simplex.chat/contact#") { + ChatModel.shared.appOpenUrl = url + } else { + UIApplication.shared.open(url) + } + default: + decisionHandler(.allow) + } + } + } +} diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift new file mode 100644 index 0000000000..16aa98bc5f --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift @@ -0,0 +1,435 @@ +// +// NetworkServersView.swift +// SimpleX (iOS) +// +// Created by Evgeny on 02/08/2022. +// Copyright © 2022 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +private enum NetworkAlert: Identifiable { + case error(err: String) + + var id: String { + switch self { + case let .error(err): return "error \(err)" + } + } +} + +private enum NetworkAndServersSheet: Identifiable { + case showConditions + + var id: String { + switch self { + case .showConditions: return "showConditions" + } + } +} + +struct NetworkAndServers: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var m: ChatModel + @Environment(\.colorScheme) var colorScheme: ColorScheme + @EnvironmentObject var theme: AppTheme + @EnvironmentObject var ss: SaveableSettings + @State private var sheetItem: NetworkAndServersSheet? = nil + @State private var justOpened = true + @State private var showSaveDialog = false + + var body: some View { + VStack { + List { + let conditionsAction = m.conditions.conditionsAction + let anyOperatorEnabled = ss.servers.userServers.contains(where: { $0.operator?.enabled ?? false }) + Section { + ForEach(ss.servers.userServers.enumerated().map { $0 }, id: \.element.id) { idx, userOperatorServers in + if let serverOperator = userOperatorServers.operator { + serverOperatorView(idx, serverOperator) + } else { + EmptyView() + } + } + + if let conditionsAction = conditionsAction, anyOperatorEnabled { + conditionsButton(conditionsAction) + } + } header: { + Text("Preset servers") + .foregroundColor(theme.colors.secondary) + } footer: { + switch conditionsAction { + case let .review(_, deadline, _): + if let deadline = deadline, anyOperatorEnabled { + Text("Conditions will be accepted on: \(conditionsTimestamp(deadline)).") + .foregroundColor(theme.colors.secondary) + } + default: + EmptyView() + } + } + + Section { + if let idx = ss.servers.userServers.firstIndex(where: { $0.operator == nil }) { + NavigationLink { + YourServersView( + userServers: $ss.servers.userServers, + serverErrors: $ss.servers.serverErrors, + operatorIndex: idx + ) + .navigationTitle("Your servers") + .modifier(ThemedBackground(grouped: true)) + } label: { + HStack { + Text("Your servers") + + if ss.servers.userServers[idx] != ss.servers.currUserServers[idx] { + Spacer() + unsavedChangesIndicator() + } + } + } + } + + NavigationLink { + AdvancedNetworkSettings() + .navigationTitle("Advanced settings") + .modifier(ThemedBackground(grouped: true)) + } label: { + Text("Advanced network settings") + } + } header: { + Text("Messages & files") + .foregroundColor(theme.colors.secondary) + } + + Section { + Button("Save servers", action: { saveServers($ss.servers.currUserServers, $ss.servers.userServers) }) + .disabled(!serversCanBeSaved(ss.servers.currUserServers, ss.servers.userServers, ss.servers.serverErrors)) + } footer: { + if let errStr = globalServersError(ss.servers.serverErrors) { + ServersErrorView(errStr: errStr) + } else if !ss.servers.serverErrors.isEmpty { + ServersErrorView(errStr: NSLocalizedString("Errors in servers configuration.", comment: "servers error")) + } + } + + Section(header: Text("Calls").foregroundColor(theme.colors.secondary)) { + NavigationLink { + RTCServers() + .navigationTitle("Your ICE servers") + .modifier(ThemedBackground(grouped: true)) + } label: { + Text("WebRTC ICE servers") + } + } + + Section(header: Text("Network connection").foregroundColor(theme.colors.secondary)) { + HStack { + Text(m.networkInfo.networkType.text) + Spacer() + Image(systemName: "circle.fill").foregroundColor(m.networkInfo.online ? .green : .red) + } + } + } + } + .task { + // this condition is needed to prevent re-setting the servers when exiting single server view + if justOpened { + do { + ss.servers.currUserServers = try await getUserServers() + ss.servers.userServers = ss.servers.currUserServers + ss.servers.serverErrors = [] + } catch let error { + await MainActor.run { + showAlert( + NSLocalizedString("Error loading servers", comment: "alert title"), + message: responseError(error) + ) + } + } + justOpened = false + } + } + .modifier(BackButton(disabled: Binding.constant(false)) { + if serversCanBeSaved(ss.servers.currUserServers, ss.servers.userServers, ss.servers.serverErrors) { + showSaveDialog = true + } else { + dismiss() + } + }) + .confirmationDialog("Save servers?", isPresented: $showSaveDialog, titleVisibility: .visible) { + Button("Save") { + saveServers($ss.servers.currUserServers, $ss.servers.userServers) + dismiss() + } + Button("Exit without saving") { dismiss() } + } + .sheet(item: $sheetItem) { item in + switch item { + case .showConditions: + UsageConditionsView( + currUserServers: $ss.servers.currUserServers, + userServers: $ss.servers.userServers + ) + .modifier(ThemedBackground(grouped: true)) + } + } + } + + private func serverOperatorView(_ operatorIndex: Int, _ serverOperator: ServerOperator) -> some View { + NavigationLink() { + OperatorView( + currUserServers: $ss.servers.currUserServers, + userServers: $ss.servers.userServers, + serverErrors: $ss.servers.serverErrors, + operatorIndex: operatorIndex, + useOperator: serverOperator.enabled + ) + .navigationBarTitle("\(serverOperator.tradeName) servers") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + HStack { + Image(serverOperator.logo(colorScheme)) + .resizable() + .scaledToFit() + .grayscale(serverOperator.enabled ? 0.0 : 1.0) + .frame(width: 24, height: 24) + Text(serverOperator.tradeName) + .foregroundColor(serverOperator.enabled ? theme.colors.onBackground : theme.colors.secondary) + + if ss.servers.userServers[operatorIndex] != ss.servers.currUserServers[operatorIndex] { + Spacer() + unsavedChangesIndicator() + } + } + } + } + + private func unsavedChangesIndicator() -> some View { + Image(systemName: "pencil") + .foregroundColor(theme.colors.secondary) + .symbolRenderingMode(.monochrome) + .frame(maxWidth: 24, maxHeight: 24, alignment: .center) + } + + private func conditionsButton(_ conditionsAction: UsageConditionsAction) -> some View { + Button { + sheetItem = .showConditions + } label: { + switch conditionsAction { + case .review: + Text("Review conditions") + case .accepted: + Text("Accepted conditions") + } + } + } +} + +struct UsageConditionsView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var theme: AppTheme + @Binding var currUserServers: [UserOperatorServers] + @Binding var userServers: [UserOperatorServers] + + var body: some View { + VStack(alignment: .leading, spacing: 20) { + HStack { + Text("Conditions of use").font(.largeTitle).bold() + Spacer() + conditionsLinkButton() + } + .padding(.top) + .padding(.top) + + switch ChatModel.shared.conditions.conditionsAction { + + case .none: + ConditionsTextView() + .padding(.bottom) + .padding(.bottom) + + case let .review(operators, deadline, _): + Text("Conditions will be accepted for the operator(s): **\(operators.map { $0.legalName_ }.joined(separator: ", "))**.") + ConditionsTextView() + VStack(spacing: 8) { + acceptConditionsButton(operators.map { $0.operatorId }) + if let deadline = deadline { + Text("Conditions will be automatically accepted for enabled operators on: \(conditionsTimestamp(deadline)).") + .foregroundColor(theme.colors.secondary) + .font(.footnote) + .multilineTextAlignment(.center) + .frame(maxWidth: .infinity, alignment: .center) + .padding(.horizontal, 32) + } + } + .padding(.bottom) + .padding(.bottom) + + + case let .accepted(operators): + Text("Conditions are accepted for the operator(s): **\(operators.map { $0.legalName_ }.joined(separator: ", "))**.") + ConditionsTextView() + .padding(.bottom) + .padding(.bottom) + } + } + .padding(.horizontal, 25) + .frame(maxHeight: .infinity) + } + + private func acceptConditionsButton(_ operatorIds: [Int64]) -> some View { + Button { + acceptForOperators(operatorIds) + } label: { + Text("Accept conditions") + } + .buttonStyle(OnboardingButtonStyle()) + } + + func acceptForOperators(_ operatorIds: [Int64]) { + Task { + do { + let conditionsId = ChatModel.shared.conditions.currentConditions.conditionsId + let r = try await acceptConditions(conditionsId: conditionsId, operatorIds: operatorIds) + await MainActor.run { + ChatModel.shared.conditions = r + updateOperatorsConditionsAcceptance($currUserServers, r.serverOperators) + updateOperatorsConditionsAcceptance($userServers, r.serverOperators) + dismiss() + } + } catch let error { + await MainActor.run { + showAlert( + NSLocalizedString("Error accepting conditions", comment: "alert title"), + message: responseError(error) + ) + } + } + } + } +} + +func validateServers_(_ userServers: Binding<[UserOperatorServers]>, _ serverErrors: Binding<[UserServersError]>) { + let userServersToValidate = userServers.wrappedValue + Task { + do { + let errs = try await validateServers(userServers: userServersToValidate) + await MainActor.run { + serverErrors.wrappedValue = errs + } + } catch let error { + logger.error("validateServers error: \(responseError(error))") + } + } +} + +func serversCanBeSaved( + _ currUserServers: [UserOperatorServers], + _ userServers: [UserOperatorServers], + _ serverErrors: [UserServersError] +) -> Bool { + return userServers != currUserServers && serverErrors.isEmpty +} + +struct ServersErrorView: View { + @EnvironmentObject var theme: AppTheme + var errStr: String + + var body: some View { + HStack { + Image(systemName: "exclamationmark.circle") + .foregroundColor(.red) + Text(errStr) + .foregroundColor(theme.colors.secondary) + } + } +} + +func globalServersError(_ serverErrors: [UserServersError]) -> String? { + for err in serverErrors { + if let errStr = err.globalError { + return errStr + } + } + return nil +} + +func globalSMPServersError(_ serverErrors: [UserServersError]) -> String? { + for err in serverErrors { + if let errStr = err.globalSMPError { + return errStr + } + } + return nil +} + +func globalXFTPServersError(_ serverErrors: [UserServersError]) -> String? { + for err in serverErrors { + if let errStr = err.globalXFTPError { + return errStr + } + } + return nil +} + +func findDuplicateHosts(_ serverErrors: [UserServersError]) -> Set { + let duplicateHostsList = serverErrors.compactMap { err in + if case let .duplicateServer(_, _, duplicateHost) = err { + return duplicateHost + } else { + return nil + } + } + return Set(duplicateHostsList) +} + +func saveServers(_ currUserServers: Binding<[UserOperatorServers]>, _ userServers: Binding<[UserOperatorServers]>) { + let userServersToSave = userServers.wrappedValue + Task { + do { + try await setUserServers(userServers: userServersToSave) + // Get updated servers to learn new server ids (otherwise it messes up delete of newly added and saved servers) + do { + let updatedServers = try await getUserServers() + let updatedOperators = try await getServerOperators() + await MainActor.run { + ChatModel.shared.conditions = updatedOperators + currUserServers.wrappedValue = updatedServers + userServers.wrappedValue = updatedServers + } + } catch let error { + logger.error("saveServers getUserServers error: \(responseError(error))") + await MainActor.run { + currUserServers.wrappedValue = userServersToSave + } + } + } catch let error { + logger.error("saveServers setUserServers error: \(responseError(error))") + await MainActor.run { + showAlert( + NSLocalizedString("Error saving servers", comment: "alert title"), + message: responseError(error) + ) + } + } + } +} + +func updateOperatorsConditionsAcceptance(_ usvs: Binding<[UserOperatorServers]>, _ updatedOperators: [ServerOperator]) { + for i in 0.. some View { + VStack { + let serverAddress = parseServerAddress(serverToEdit.server) + let valid = serverAddress?.valid == true + List { + Section { + TextEditor(text: $serverToEdit.server) + .multilineTextAlignment(.leading) + .autocorrectionDisabled(true) + .autocapitalization(.none) + .allowsTightening(true) + .lineLimit(10) + .frame(height: 144) + .padding(-6) + } header: { + HStack { + Text("Your server address") + .foregroundColor(theme.colors.secondary) + if !valid { + Spacer() + Image(systemName: "exclamationmark.circle").foregroundColor(.red) + } + } + } + useServerSection(valid) + if valid { + Section(header: Text("Add to another device").foregroundColor(theme.colors.secondary)) { + MutableQRCode(uri: $serverToEdit.server) + .listRowInsets(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)) + } + } + } + } + } + + private func useServerSection(_ valid: Bool) -> some View { + Section(header: Text("Use server").foregroundColor(theme.colors.secondary)) { + HStack { + Button("Test server") { + testing = true + serverToEdit.tested = nil + Task { + if let f = await testServerConnection(server: $serverToEdit) { + showTestFailure = true + testFailure = f + } + await MainActor.run { testing = false } + } + } + .disabled(!valid || testing) + Spacer() + showTestStatus(server: serverToEdit) + } + Toggle("Use for new connections", isOn: $serverToEdit.enabled) + } + } +} + +func serverProtocolAndOperator(_ server: UserServer, _ userServers: [UserOperatorServers]) -> (ServerProtocol, ServerOperator?)? { + if let serverAddress = parseServerAddress(server.server) { + let serverProtocol = serverAddress.serverProtocol + let hostnames = serverAddress.hostnames + let matchingOperator = userServers.compactMap { $0.operator }.first { op in + op.serverDomains.contains { domain in + hostnames.contains { hostname in + hostname.hasSuffix(domain) + } + } + } + return (serverProtocol, matchingOperator) + } else { + return nil + } +} + +func addServer( + _ server: UserServer, + _ userServers: Binding<[UserOperatorServers]>, + _ serverErrors: Binding<[UserServersError]>, + _ dismiss: DismissAction +) { + if let (serverProtocol, matchingOperator) = serverProtocolAndOperator(server, userServers.wrappedValue) { + if let i = userServers.wrappedValue.firstIndex(where: { $0.operator?.operatorId == matchingOperator?.operatorId }) { + switch serverProtocol { + case .smp: userServers[i].wrappedValue.smpServers.append(server) + case .xftp: userServers[i].wrappedValue.xftpServers.append(server) + } + validateServers_(userServers, serverErrors) + dismiss() + if let op = matchingOperator { + showAlert( + NSLocalizedString("Operator server", comment: "alert title"), + message: String.localizedStringWithFormat(NSLocalizedString("Server added to operator %@.", comment: "alert message"), op.tradeName) + ) + } + } else { // Shouldn't happen + dismiss() + showAlert(NSLocalizedString("Error adding server", comment: "alert title")) + } + } else { + dismiss() + if server.server.trimmingCharacters(in: .whitespaces) != "" { + showAlert( + NSLocalizedString("Invalid server address!", comment: "alert title"), + message: NSLocalizedString("Check server address and try again.", comment: "alert title") + ) + } + } +} + +#Preview { + NewServerView( + userServers: Binding.constant([UserOperatorServers.sampleDataNilOperator]), + serverErrors: Binding.constant([]) + ) +} diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift new file mode 100644 index 0000000000..cea9dd0635 --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/OperatorView.swift @@ -0,0 +1,586 @@ +// +// OperatorView.swift +// SimpleX (iOS) +// +// Created by spaced4ndy on 28.10.2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat +import Ink + +struct OperatorView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @Environment(\.colorScheme) var colorScheme: ColorScheme + @EnvironmentObject var theme: AppTheme + @Environment(\.editMode) private var editMode + @Binding var currUserServers: [UserOperatorServers] + @Binding var userServers: [UserOperatorServers] + @Binding var serverErrors: [UserServersError] + var operatorIndex: Int + @State var useOperator: Bool + @State private var useOperatorToggleReset: Bool = false + @State private var showConditionsSheet: Bool = false + @State private var selectedServer: String? = nil + @State private var testing = false + + var body: some View { + operatorView() + .opacity(testing ? 0.4 : 1) + .overlay { + if testing { + ProgressView() + .scaleEffect(2) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } + .allowsHitTesting(!testing) + } + + @ViewBuilder private func operatorView() -> some View { + let duplicateHosts = findDuplicateHosts(serverErrors) + VStack { + List { + Section { + infoViewLink() + useOperatorToggle() + } header: { + Text("Operator") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } else { + switch (userServers[operatorIndex].operator_.conditionsAcceptance) { + case let .accepted(acceptedAt): + if let acceptedAt = acceptedAt { + Text("Conditions accepted on: \(conditionsTimestamp(acceptedAt)).") + .foregroundColor(theme.colors.secondary) + } + case let .required(deadline): + if userServers[operatorIndex].operator_.enabled, let deadline = deadline { + Text("Conditions will be accepted on: \(conditionsTimestamp(deadline)).") + .foregroundColor(theme.colors.secondary) + } + } + } + } + + if userServers[operatorIndex].operator_.enabled { + if !userServers[operatorIndex].smpServers.filter({ !$0.deleted }).isEmpty { + Section { + Toggle("To receive", isOn: $userServers[operatorIndex].operator_.smpRoles.storage) + .onChange(of: userServers[operatorIndex].operator_.smpRoles.storage) { _ in + validateServers_($userServers, $serverErrors) + } + Toggle("For private routing", isOn: $userServers[operatorIndex].operator_.smpRoles.proxy) + .onChange(of: userServers[operatorIndex].operator_.smpRoles.proxy) { _ in + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Use for messages") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalSMPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } + } + } + + // Preset servers can't be deleted + if !userServers[operatorIndex].smpServers.filter({ $0.preset }).isEmpty { + Section { + ForEach($userServers[operatorIndex].smpServers) { srv in + if srv.wrappedValue.preset { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .smp, + backLabel: "\(userServers[operatorIndex].operator_.tradeName) servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + } header: { + Text("Message servers") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalSMPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } else { + Text("The servers for new connections of your current chat profile **\(ChatModel.shared.currentUser?.displayName ?? "")**.") + .foregroundColor(theme.colors.secondary) + .lineLimit(10) + } + } + } + + if !userServers[operatorIndex].smpServers.filter({ !$0.preset && !$0.deleted }).isEmpty { + Section { + ForEach($userServers[operatorIndex].smpServers) { srv in + if !srv.wrappedValue.preset && !srv.wrappedValue.deleted { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .smp, + backLabel: "\(userServers[operatorIndex].operator_.tradeName) servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + .onDelete { indexSet in + deleteSMPServer($userServers, operatorIndex, indexSet) + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Added message servers") + .foregroundColor(theme.colors.secondary) + } + } + + if !userServers[operatorIndex].xftpServers.filter({ !$0.deleted }).isEmpty { + Section { + Toggle("To send", isOn: $userServers[operatorIndex].operator_.xftpRoles.storage) + .onChange(of: userServers[operatorIndex].operator_.xftpRoles.storage) { _ in + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Use for files") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalXFTPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } + } + } + + // Preset servers can't be deleted + if !userServers[operatorIndex].xftpServers.filter({ $0.preset }).isEmpty { + Section { + ForEach($userServers[operatorIndex].xftpServers) { srv in + if srv.wrappedValue.preset { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .xftp, + backLabel: "\(userServers[operatorIndex].operator_.tradeName) servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + } header: { + Text("Media & file servers") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalXFTPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } else { + Text("The servers for new files of your current chat profile **\(ChatModel.shared.currentUser?.displayName ?? "")**.") + .foregroundColor(theme.colors.secondary) + .lineLimit(10) + } + } + } + + if !userServers[operatorIndex].xftpServers.filter({ !$0.preset && !$0.deleted }).isEmpty { + Section { + ForEach($userServers[operatorIndex].xftpServers) { srv in + if !srv.wrappedValue.preset && !srv.wrappedValue.deleted { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .xftp, + backLabel: "\(userServers[operatorIndex].operator_.tradeName) servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + .onDelete { indexSet in + deleteXFTPServer($userServers, operatorIndex, indexSet) + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Added media & file servers") + .foregroundColor(theme.colors.secondary) + } + } + + Section { + TestServersButton( + smpServers: $userServers[operatorIndex].smpServers, + xftpServers: $userServers[operatorIndex].xftpServers, + testing: $testing + ) + } + } + } + } + .toolbar { + if ( + !userServers[operatorIndex].smpServers.filter({ !$0.preset && !$0.deleted }).isEmpty || + !userServers[operatorIndex].xftpServers.filter({ !$0.preset && !$0.deleted }).isEmpty + ) { + EditButton() + } + } + .sheet(isPresented: $showConditionsSheet, onDismiss: onUseToggleSheetDismissed) { + SingleOperatorUsageConditionsView( + currUserServers: $currUserServers, + userServers: $userServers, + serverErrors: $serverErrors, + operatorIndex: operatorIndex + ) + .modifier(ThemedBackground(grouped: true)) + } + } + + private func infoViewLink() -> some View { + NavigationLink() { + OperatorInfoView(serverOperator: userServers[operatorIndex].operator_) + .navigationBarTitle("Network operator") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + Image(userServers[operatorIndex].operator_.largeLogo(colorScheme)) + .resizable() + .scaledToFit() + .grayscale(userServers[operatorIndex].operator_.enabled ? 0.0 : 1.0) + .frame(height: 40) + } + } + + private func useOperatorToggle() -> some View { + Toggle("Use servers", isOn: $useOperator) + .onChange(of: useOperator) { useOperatorToggle in + if useOperatorToggleReset { + useOperatorToggleReset = false + } else if useOperatorToggle { + switch userServers[operatorIndex].operator_.conditionsAcceptance { + case .accepted: + userServers[operatorIndex].operator_.enabled = true + validateServers_($userServers, $serverErrors) + case let .required(deadline): + if deadline == nil { + showConditionsSheet = true + } else { + userServers[operatorIndex].operator_.enabled = true + validateServers_($userServers, $serverErrors) + } + } + } else { + userServers[operatorIndex].operator_.enabled = false + validateServers_($userServers, $serverErrors) + } + } + } + + private func onUseToggleSheetDismissed() { + if useOperator && !userServers[operatorIndex].operator_.conditionsAcceptance.usageAllowed { + useOperatorToggleReset = true + useOperator = false + } + } +} + +func conditionsTimestamp(_ date: Date) -> String { + let localDateFormatter = DateFormatter() + localDateFormatter.dateStyle = .medium + localDateFormatter.timeStyle = .none + return localDateFormatter.string(from: date) +} + +struct OperatorInfoView: View { + @EnvironmentObject var theme: AppTheme + @Environment(\.colorScheme) var colorScheme: ColorScheme + var serverOperator: ServerOperator + + var body: some View { + VStack { + List { + Section { + VStack(alignment: .leading) { + Image(serverOperator.largeLogo(colorScheme)) + .resizable() + .scaledToFit() + .frame(height: 48) + if let legalName = serverOperator.legalName { + Text(legalName) + } + } + } + Section { + VStack(alignment: .leading, spacing: 12) { + ForEach(serverOperator.info.description, id: \.self) { d in + Text(d) + } + } + Link(serverOperator.info.website.absoluteString, destination: serverOperator.info.website) + } + if let selfhost = serverOperator.info.selfhost { + Section { + Link(selfhost.text, destination: selfhost.link) + } + } + } + } + } +} + +struct ConditionsTextView: View { + @State private var conditionsData: (UsageConditions, String?, UsageConditions?)? + @State private var failedToLoad: Bool = false + @State private var conditionsHTML: String? = nil + + let defaultConditionsLink = "https://github.com/simplex-chat/simplex-chat/blob/stable/PRIVACY.md" + + var body: some View { + viewBody() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .task { + do { + let conditions = try await getUsageConditions() + let conditionsText = conditions.1 + let parentLink = "https://github.com/simplex-chat/simplex-chat/blob/\(conditions.0.conditionsCommit)" + let preparedText: String? + if let conditionsText { + let prepared = prepareMarkdown(conditionsText.trimmingCharacters(in: .whitespacesAndNewlines), parentLink) + conditionsHTML = MarkdownParser().html(from: prepared) + preparedText = prepared + } else { + preparedText = nil + } + conditionsData = (conditions.0, preparedText, conditions.2) + } catch let error { + logger.error("ConditionsTextView getUsageConditions error: \(responseError(error))") + failedToLoad = true + } + } + } + + // TODO Diff rendering + @ViewBuilder private func viewBody() -> some View { + if let (usageConditions, _, _) = conditionsData { + if let conditionsHTML { + ConditionsWebView(html: conditionsHTML) + .padding(6) + .background( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .fill(Color(uiColor: .secondarySystemGroupedBackground)) + ) + } else { + let conditionsLink = "https://github.com/simplex-chat/simplex-chat/blob/\(usageConditions.conditionsCommit)/PRIVACY.md" + conditionsLinkView(conditionsLink) + } + } else if failedToLoad { + conditionsLinkView(defaultConditionsLink) + } else { + ProgressView() + .scaleEffect(2) + } + } + + private func conditionsLinkView(_ conditionsLink: String) -> some View { + VStack(alignment: .leading, spacing: 20) { + Text("Current conditions text couldn't be loaded, you can review conditions via this link:") + Link(destination: URL(string: conditionsLink)!) { + Text(conditionsLink) + .multilineTextAlignment(.leading) + } + } + } + + private func prepareMarkdown(_ text: String, _ parentLink: String) -> String { + let localLinkRegex = try! NSRegularExpression(pattern: "\\[([^\\(]*)\\]\\(#.*\\)") + let h1Regex = try! NSRegularExpression(pattern: "^# ") + var text = localLinkRegex.stringByReplacingMatches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count), withTemplate: "$1") + text = h1Regex.stringByReplacingMatches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count), withTemplate: "") + return text + .replacingOccurrences(of: "](/", with: "](\(parentLink)/") + .replacingOccurrences(of: "](./", with: "](\(parentLink)/") + } +} + +struct SingleOperatorUsageConditionsView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var theme: AppTheme + @Binding var currUserServers: [UserOperatorServers] + @Binding var userServers: [UserOperatorServers] + @Binding var serverErrors: [UserServersError] + var operatorIndex: Int + + var body: some View { + viewBody() + } + + @ViewBuilder private func viewBody() -> some View { + let operatorsWithConditionsAccepted = ChatModel.shared.conditions.serverOperators.filter { $0.conditionsAcceptance.conditionsAccepted } + if case .accepted = userServers[operatorIndex].operator_.conditionsAcceptance { + + // In current UI implementation this branch doesn't get shown - as conditions can't be opened from inside operator once accepted + VStack(alignment: .leading, spacing: 20) { + viewHeader() + ConditionsTextView() + } + .padding(.bottom) + .padding(.bottom) + .padding(.horizontal) + .frame(maxHeight: .infinity) + + } else if !operatorsWithConditionsAccepted.isEmpty { + + NavigationView { + VStack(alignment: .leading, spacing: 20) { + viewHeader() + Text("Conditions are already accepted for these operator(s): **\(operatorsWithConditionsAccepted.map { $0.legalName_ }.joined(separator: ", "))**.") + Text("The same conditions will apply to operator **\(userServers[operatorIndex].operator_.legalName_)**.") + conditionsAppliedToOtherOperatorsText() + Spacer() + + acceptConditionsButton() + usageConditionsNavLinkButton() + } + .padding(.bottom) + .padding(.bottom) + .padding(.horizontal) + .frame(maxHeight: .infinity) + } + + } else { + + VStack(alignment: .leading, spacing: 20) { + viewHeader() + Text("To use the servers of **\(userServers[operatorIndex].operator_.legalName_)**, accept conditions of use.") + conditionsAppliedToOtherOperatorsText() + ConditionsTextView() + acceptConditionsButton() + .padding(.bottom) + .padding(.bottom) + } + .padding(.horizontal) + .frame(maxHeight: .infinity) + + } + } + + private func viewHeader() -> some View { + HStack { + Text("Use \(userServers[operatorIndex].operator_.tradeName)").font(.largeTitle).bold() + Spacer() + conditionsLinkButton() + } + .padding(.top) + .padding(.top) + } + + @ViewBuilder private func conditionsAppliedToOtherOperatorsText() -> some View { + let otherOperatorsToApply = ChatModel.shared.conditions.serverOperators.filter { + $0.enabled && + !$0.conditionsAcceptance.conditionsAccepted && + $0.operatorId != userServers[operatorIndex].operator_.operatorId + } + if !otherOperatorsToApply.isEmpty { + Text("These conditions will also apply for: **\(otherOperatorsToApply.map { $0.legalName_ }.joined(separator: ", "))**.") + } + } + + @ViewBuilder private func acceptConditionsButton() -> some View { + let operatorIds = ChatModel.shared.conditions.serverOperators + .filter { + $0.operatorId == userServers[operatorIndex].operator_.operatorId || // Opened operator + ($0.enabled && !$0.conditionsAcceptance.conditionsAccepted) // Other enabled operators with conditions not accepted + } + .map { $0.operatorId } + Button { + acceptForOperators(operatorIds, operatorIndex) + } label: { + Text("Accept conditions") + } + .buttonStyle(OnboardingButtonStyle()) + } + + func acceptForOperators(_ operatorIds: [Int64], _ operatorIndexToEnable: Int) { + Task { + do { + let conditionsId = ChatModel.shared.conditions.currentConditions.conditionsId + let r = try await acceptConditions(conditionsId: conditionsId, operatorIds: operatorIds) + await MainActor.run { + ChatModel.shared.conditions = r + updateOperatorsConditionsAcceptance($currUserServers, r.serverOperators) + updateOperatorsConditionsAcceptance($userServers, r.serverOperators) + userServers[operatorIndexToEnable].operator?.enabled = true + validateServers_($userServers, $serverErrors) + dismiss() + } + } catch let error { + await MainActor.run { + showAlert( + NSLocalizedString("Error accepting conditions", comment: "alert title"), + message: responseError(error) + ) + } + } + } + } + + private func usageConditionsNavLinkButton() -> some View { + NavigationLink("View conditions") { + ConditionsTextView() + .padding() + .navigationTitle("Conditions of use") + .navigationBarTitleDisplayMode(.large) + .toolbar { ToolbarItem(placement: .navigationBarTrailing, content: conditionsLinkButton) } + .modifier(ThemedBackground(grouped: true)) + } + .font(.callout) + .frame(maxWidth: .infinity, alignment: .center) + } +} + +func conditionsLinkButton() -> some View { + let commit = ChatModel.shared.conditions.currentConditions.conditionsCommit + let mdUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/\(commit)/PRIVACY.md") ?? conditionsURL + return Menu { + Link(destination: mdUrl) { + Label("Open conditions", systemImage: "doc") + } + if let commitUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/commit/\(commit)") { + Link(destination: commitUrl) { + Label("Open changes", systemImage: "ellipsis") + } + } + } label: { + Image(systemName: "arrow.up.right.circle") + .resizable() + .scaledToFit() + .frame(width: 20) + .padding(2) + .contentShape(Circle()) + } +} + +#Preview { + OperatorView( + currUserServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]), + userServers: Binding.constant([UserOperatorServers.sampleData1, UserOperatorServers.sampleDataNilOperator]), + serverErrors: Binding.constant([]), + operatorIndex: 1, + useOperator: ServerOperator.sampleData1.enabled + ) +} diff --git a/apps/ios/Shared/Views/UserSettings/ProtocolServerView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServerView.swift similarity index 70% rename from apps/ios/Shared/Views/UserSettings/ProtocolServerView.swift rename to apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServerView.swift index da29dfac29..13d01874ed 100644 --- a/apps/ios/Shared/Views/UserSettings/ProtocolServerView.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServerView.swift @@ -12,15 +12,15 @@ import SimpleXChat struct ProtocolServerView: View { @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject var theme: AppTheme - let serverProtocol: ServerProtocol - @Binding var server: ServerCfg - @State var serverToEdit: ServerCfg + @Binding var userServers: [UserOperatorServers] + @Binding var serverErrors: [UserServersError] + @Binding var server: UserServer + @State var serverToEdit: UserServer + var backLabel: LocalizedStringKey @State private var showTestFailure = false @State private var testing = false @State private var testFailure: ProtocolTestFailure? - var proto: String { serverProtocol.rawValue.uppercased() } - var body: some View { ZStack { if server.preset { @@ -32,9 +32,33 @@ struct ProtocolServerView: View { ProgressView().scaleEffect(2) } } - .modifier(BackButton(label: "Your \(proto) servers", disabled: Binding.constant(false)) { - server = serverToEdit - dismiss() + .modifier(BackButton(label: backLabel, disabled: Binding.constant(false)) { + if let (serverToEditProtocol, serverToEditOperator) = serverProtocolAndOperator(serverToEdit, userServers), + let (serverProtocol, serverOperator) = serverProtocolAndOperator(server, userServers) { + if serverToEditProtocol != serverProtocol { + dismiss() + showAlert( + NSLocalizedString("Error updating server", comment: "alert title"), + message: NSLocalizedString("Server protocol changed.", comment: "alert title") + ) + } else if serverToEditOperator != serverOperator { + dismiss() + showAlert( + NSLocalizedString("Error updating server", comment: "alert title"), + message: NSLocalizedString("Server operator changed.", comment: "alert title") + ) + } else { + server = serverToEdit + validateServers_($userServers, $serverErrors) + dismiss() + } + } else { + dismiss() + showAlert( + NSLocalizedString("Invalid server address!", comment: "alert title"), + message: NSLocalizedString("Check server address and try again.", comment: "alert title") + ) + } }) .alert(isPresented: $showTestFailure) { Alert( @@ -62,7 +86,7 @@ struct ProtocolServerView: View { private func customServer() -> some View { VStack { let serverAddress = parseServerAddress(serverToEdit.server) - let valid = serverAddress?.valid == true && serverAddress?.serverProtocol == serverProtocol + let valid = serverAddress?.valid == true List { Section { TextEditor(text: $serverToEdit.server) @@ -112,10 +136,7 @@ struct ProtocolServerView: View { Spacer() showTestStatus(server: serverToEdit) } - let useForNewDisabled = serverToEdit.tested != true && !serverToEdit.preset Toggle("Use for new connections", isOn: $serverToEdit.enabled) - .disabled(useForNewDisabled) - .foregroundColor(useForNewDisabled ? theme.colors.secondary : theme.colors.onBackground) } } } @@ -142,7 +163,7 @@ struct BackButton: ViewModifier { } } -@ViewBuilder func showTestStatus(server: ServerCfg) -> some View { +@ViewBuilder func showTestStatus(server: UserServer) -> some View { switch server.tested { case .some(true): Image(systemName: "checkmark") @@ -155,7 +176,7 @@ struct BackButton: ViewModifier { } } -func testServerConnection(server: Binding) async -> ProtocolTestFailure? { +func testServerConnection(server: Binding) async -> ProtocolTestFailure? { do { let r = try await testProtoServer(server: server.wrappedValue.server) switch r { @@ -178,9 +199,11 @@ func testServerConnection(server: Binding) async -> ProtocolTestFailu struct ProtocolServerView_Previews: PreviewProvider { static var previews: some View { ProtocolServerView( - serverProtocol: .smp, - server: Binding.constant(ServerCfg.sampleData.custom), - serverToEdit: ServerCfg.sampleData.custom + userServers: Binding.constant([UserOperatorServers.sampleDataNilOperator]), + serverErrors: Binding.constant([]), + server: Binding.constant(UserServer.sampleData.custom), + serverToEdit: UserServer.sampleData.custom, + backLabel: "Your SMP servers" ) } } diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift new file mode 100644 index 0000000000..ed3c5c773c --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ProtocolServersView.swift @@ -0,0 +1,359 @@ +// +// ProtocolServersView.swift +// SimpleX (iOS) +// +// Created by Evgeny on 15/11/2022. +// Copyright © 2022 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +private let howToUrl = URL(string: "https://simplex.chat/docs/server.html")! + +struct YourServersView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject private var m: ChatModel + @EnvironmentObject var theme: AppTheme + @Environment(\.editMode) private var editMode + @Binding var userServers: [UserOperatorServers] + @Binding var serverErrors: [UserServersError] + var operatorIndex: Int + @State private var selectedServer: String? = nil + @State private var showAddServer = false + @State private var newServerNavLinkActive = false + @State private var showScanProtoServer = false + @State private var testing = false + + var body: some View { + yourServersView() + .opacity(testing ? 0.4 : 1) + .overlay { + if testing { + ProgressView() + .scaleEffect(2) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } + .allowsHitTesting(!testing) + } + + @ViewBuilder private func yourServersView() -> some View { + let duplicateHosts = findDuplicateHosts(serverErrors) + List { + if !userServers[operatorIndex].smpServers.filter({ !$0.deleted }).isEmpty { + Section { + ForEach($userServers[operatorIndex].smpServers) { srv in + if !srv.wrappedValue.deleted { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .smp, + backLabel: "Your servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + .onDelete { indexSet in + deleteSMPServer($userServers, operatorIndex, indexSet) + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Message servers") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalSMPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } else { + Text("The servers for new connections of your current chat profile **\(m.currentUser?.displayName ?? "")**.") + .foregroundColor(theme.colors.secondary) + .lineLimit(10) + } + } + } + + if !userServers[operatorIndex].xftpServers.filter({ !$0.deleted }).isEmpty { + Section { + ForEach($userServers[operatorIndex].xftpServers) { srv in + if !srv.wrappedValue.deleted { + ProtocolServerViewLink( + userServers: $userServers, + serverErrors: $serverErrors, + duplicateHosts: duplicateHosts, + server: srv, + serverProtocol: .xftp, + backLabel: "Your servers", + selectedServer: $selectedServer + ) + } else { + EmptyView() + } + } + .onDelete { indexSet in + deleteXFTPServer($userServers, operatorIndex, indexSet) + validateServers_($userServers, $serverErrors) + } + } header: { + Text("Media & file servers") + .foregroundColor(theme.colors.secondary) + } footer: { + if let errStr = globalXFTPServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } else { + Text("The servers for new files of your current chat profile **\(m.currentUser?.displayName ?? "")**.") + .foregroundColor(theme.colors.secondary) + .lineLimit(10) + } + } + } + + Section { + ZStack { + Button("Add server") { + showAddServer = true + } + + NavigationLink(isActive: $newServerNavLinkActive) { + newServerDestinationView() + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() + } + } footer: { + if let errStr = globalServersError(serverErrors) { + ServersErrorView(errStr: errStr) + } + } + + Section { + TestServersButton( + smpServers: $userServers[operatorIndex].smpServers, + xftpServers: $userServers[operatorIndex].xftpServers, + testing: $testing + ) + howToButton() + } + } + .toolbar { + if ( + !userServers[operatorIndex].smpServers.filter({ !$0.deleted }).isEmpty || + !userServers[operatorIndex].xftpServers.filter({ !$0.deleted }).isEmpty + ) { + EditButton() + } + } + .confirmationDialog("Add server", isPresented: $showAddServer, titleVisibility: .hidden) { + Button("Enter server manually") { newServerNavLinkActive = true } + Button("Scan server QR code") { showScanProtoServer = true } + } + .sheet(isPresented: $showScanProtoServer) { + ScanProtocolServer( + userServers: $userServers, + serverErrors: $serverErrors + ) + .modifier(ThemedBackground(grouped: true)) + } + } + + private func newServerDestinationView() -> some View { + NewServerView( + userServers: $userServers, + serverErrors: $serverErrors + ) + .navigationTitle("New server") + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } + + func howToButton() -> some View { + Button { + DispatchQueue.main.async { + UIApplication.shared.open(howToUrl) + } + } label: { + HStack { + Text("How to use your servers") + Image(systemName: "arrow.up.right.circle") + } + } + } +} + +struct ProtocolServerViewLink: View { + @EnvironmentObject var theme: AppTheme + @Binding var userServers: [UserOperatorServers] + @Binding var serverErrors: [UserServersError] + var duplicateHosts: Set + @Binding var server: UserServer + var serverProtocol: ServerProtocol + var backLabel: LocalizedStringKey + @Binding var selectedServer: String? + + var body: some View { + let proto = serverProtocol.rawValue.uppercased() + + NavigationLink(tag: server.id, selection: $selectedServer) { + ProtocolServerView( + userServers: $userServers, + serverErrors: $serverErrors, + server: $server, + serverToEdit: server, + backLabel: backLabel + ) + .navigationBarTitle("\(proto) server") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + let address = parseServerAddress(server.server) + HStack { + Group { + if let address = address { + if !address.valid || address.serverProtocol != serverProtocol { + invalidServer() + } else if address.hostnames.contains(where: duplicateHosts.contains) { + Image(systemName: "exclamationmark.circle").foregroundColor(.red) + } else if !server.enabled { + Image(systemName: "slash.circle").foregroundColor(theme.colors.secondary) + } else { + showTestStatus(server: server) + } + } else { + invalidServer() + } + } + .frame(width: 16, alignment: .center) + .padding(.trailing, 4) + + let v = Text(address?.hostnames.first ?? server.server).lineLimit(1) + if server.enabled { + v + } else { + v.foregroundColor(theme.colors.secondary) + } + } + } + } + + private func invalidServer() -> some View { + Image(systemName: "exclamationmark.circle").foregroundColor(.red) + } +} + +func deleteSMPServer( + _ userServers: Binding<[UserOperatorServers]>, + _ operatorServersIndex: Int, + _ serverIndexSet: IndexSet +) { + if let idx = serverIndexSet.first { + let server = userServers[operatorServersIndex].wrappedValue.smpServers[idx] + if server.serverId == nil { + userServers[operatorServersIndex].wrappedValue.smpServers.remove(at: idx) + } else { + var updatedServer = server + updatedServer.deleted = true + userServers[operatorServersIndex].wrappedValue.smpServers[idx] = updatedServer + } + } +} + +func deleteXFTPServer( + _ userServers: Binding<[UserOperatorServers]>, + _ operatorServersIndex: Int, + _ serverIndexSet: IndexSet +) { + if let idx = serverIndexSet.first { + let server = userServers[operatorServersIndex].wrappedValue.xftpServers[idx] + if server.serverId == nil { + userServers[operatorServersIndex].wrappedValue.xftpServers.remove(at: idx) + } else { + var updatedServer = server + updatedServer.deleted = true + userServers[operatorServersIndex].wrappedValue.xftpServers[idx] = updatedServer + } + } +} + +struct TestServersButton: View { + @Binding var smpServers: [UserServer] + @Binding var xftpServers: [UserServer] + @Binding var testing: Bool + + var body: some View { + Button("Test servers", action: testServers) + .disabled(testing || allServersDisabled) + } + + private var allServersDisabled: Bool { + smpServers.allSatisfy { !$0.enabled } && xftpServers.allSatisfy { !$0.enabled } + } + + private func testServers() { + resetTestStatus() + testing = true + Task { + let fs = await runServersTest() + await MainActor.run { + testing = false + if !fs.isEmpty { + let msg = fs.map { (srv, f) in + "\(srv): \(f.localizedDescription)" + }.joined(separator: "\n") + showAlert( + NSLocalizedString("Tests failed!", comment: "alert title"), + message: String.localizedStringWithFormat(NSLocalizedString("Some servers failed the test:\n%@", comment: "alert message"), msg) + ) + } + } + } + } + + private func resetTestStatus() { + for i in 0.. [String: ProtocolTestFailure] { + var fs: [String: ProtocolTestFailure] = [:] + for i in 0..) { switch resp { case let .success(r): - if parseServerAddress(r.string) != nil { - servers.append(ServerCfg(server: r.string, preset: false, tested: nil, enabled: false)) - dismiss() - } else { - showAddressError = true - } + var server: UserServer = .empty + server.server = r.string + addServer(server, $userServers, $serverErrors, dismiss) case let .failure(e): logger.error("ScanProtocolServer.processQRCode QR code error: \(e.localizedDescription)") dismiss() @@ -54,6 +45,9 @@ struct ScanProtocolServer: View { struct ScanProtocolServer_Previews: PreviewProvider { static var previews: some View { - ScanProtocolServer(servers: Binding.constant([])) + ScanProtocolServer( + userServers: Binding.constant([UserOperatorServers.sampleDataNilOperator]), + serverErrors: Binding.constant([]) + ) } } diff --git a/apps/ios/Shared/Views/UserSettings/NotificationsView.swift b/apps/ios/Shared/Views/UserSettings/NotificationsView.swift index b9c92c9919..4e7f826f4f 100644 --- a/apps/ios/Shared/Views/UserSettings/NotificationsView.swift +++ b/apps/ios/Shared/Views/UserSettings/NotificationsView.swift @@ -237,9 +237,17 @@ struct NotificationsView: View { func ntfModeDescription(_ mode: NotificationsMode) -> LocalizedStringKey { switch mode { - case .off: return "**Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app)." - case .periodic: return "**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." - case .instant: return "**Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from." + case .off: return "**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app." + case .periodic: return "**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." + case .instant: return "**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from." + } +} + +func ntfModeShortDescription(_ mode: NotificationsMode) -> LocalizedStringKey { + switch mode { + case .off: return "Check messages when allowed." + case .periodic: return "Check messages every 20 min." + case .instant: return "E2E encrypted notifications." } } diff --git a/apps/ios/Shared/Views/UserSettings/PreferencesView.swift b/apps/ios/Shared/Views/UserSettings/PreferencesView.swift index 0c10da2103..bd8171623a 100644 --- a/apps/ios/Shared/Views/UserSettings/PreferencesView.swift +++ b/apps/ios/Shared/Views/UserSettings/PreferencesView.swift @@ -32,6 +32,17 @@ struct PreferencesView: View { .disabled(currentPreferences == preferences) } } + .onDisappear { + if currentPreferences != preferences { + showAlert( + title: NSLocalizedString("Your chat preferences", comment: "alert title"), + message: NSLocalizedString("Chat preferences were changed.", comment: "alert message"), + buttonTitle: NSLocalizedString("Save", comment: "alert button"), + buttonAction: savePreferences, + cancelButton: true + ) + } + } } private func featureSection(_ feature: ChatFeature, _ allowFeature: Binding) -> some View { diff --git a/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift b/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift deleted file mode 100644 index 0fb37d5c49..0000000000 --- a/apps/ios/Shared/Views/UserSettings/ProtocolServersView.swift +++ /dev/null @@ -1,359 +0,0 @@ -// -// ProtocolServersView.swift -// SimpleX (iOS) -// -// Created by Evgeny on 15/11/2022. -// Copyright © 2022 SimpleX Chat. All rights reserved. -// - -import SwiftUI -import SimpleXChat - -private let howToUrl = URL(string: "https://simplex.chat/docs/server.html")! - -struct ProtocolServersView: View { - @Environment(\.dismiss) var dismiss: DismissAction - @EnvironmentObject private var m: ChatModel - @EnvironmentObject var theme: AppTheme - @Environment(\.editMode) private var editMode - let serverProtocol: ServerProtocol - @State private var currServers: [ServerCfg] = [] - @State private var presetServers: [ServerCfg] = [] - @State private var configuredServers: [ServerCfg] = [] - @State private var otherServers: [ServerCfg] = [] - @State private var selectedServer: String? = nil - @State private var showAddServer = false - @State private var showScanProtoServer = false - @State private var justOpened = true - @State private var testing = false - @State private var alert: ServerAlert? = nil - @State private var showSaveDialog = false - - var proto: String { serverProtocol.rawValue.uppercased() } - - var body: some View { - ZStack { - protocolServersView() - if testing { - ProgressView().scaleEffect(2) - } - } - } - - enum ServerAlert: Identifiable { - case testsFailed(failures: [String: ProtocolTestFailure]) - case error(title: LocalizedStringKey, error: LocalizedStringKey = "") - - var id: String { - switch self { - case .testsFailed: return "testsFailed" - case let .error(title, _): return "error \(title)" - } - } - } - - private func protocolServersView() -> some View { - List { - if !configuredServers.isEmpty { - Section { - ForEach($configuredServers) { srv in - protocolServerView(srv) - } - .onMove { indexSet, offset in - configuredServers.move(fromOffsets: indexSet, toOffset: offset) - } - .onDelete { indexSet in - configuredServers.remove(atOffsets: indexSet) - } - } header: { - Text("Configured \(proto) servers") - .foregroundColor(theme.colors.secondary) - } footer: { - Text("The servers for new connections of your current chat profile **\(m.currentUser?.displayName ?? "")**.") - .foregroundColor(theme.colors.secondary) - .lineLimit(10) - } - } - - if !otherServers.isEmpty { - Section { - ForEach($otherServers) { srv in - protocolServerView(srv) - } - .onMove { indexSet, offset in - otherServers.move(fromOffsets: indexSet, toOffset: offset) - } - .onDelete { indexSet in - otherServers.remove(atOffsets: indexSet) - } - } header: { - Text("Other \(proto) servers") - .foregroundColor(theme.colors.secondary) - } - } - - Section { - Button("Add server") { - showAddServer = true - } - } - - Section { - Button("Reset") { partitionServers(currServers) } - .disabled(Set(allServers) == Set(currServers) || testing) - Button("Test servers", action: testServers) - .disabled(testing || allServersDisabled) - Button("Save servers", action: saveServers) - .disabled(saveDisabled) - howToButton() - } - } - .toolbar { EditButton() } - .confirmationDialog("Add server", isPresented: $showAddServer, titleVisibility: .hidden) { - Button("Enter server manually") { - otherServers.append(ServerCfg.empty) - selectedServer = allServers.last?.id - } - Button("Scan server QR code") { showScanProtoServer = true } - Button("Add preset servers", action: addAllPresets) - .disabled(hasAllPresets()) - } - .sheet(isPresented: $showScanProtoServer) { - ScanProtocolServer(servers: $otherServers) - .modifier(ThemedBackground(grouped: true)) - } - .modifier(BackButton(disabled: Binding.constant(false)) { - if saveDisabled { - dismiss() - justOpened = false - } else { - showSaveDialog = true - } - }) - .confirmationDialog("Save servers?", isPresented: $showSaveDialog, titleVisibility: .visible) { - Button("Save") { - saveServers() - dismiss() - justOpened = false - } - Button("Exit without saving") { dismiss() } - } - .alert(item: $alert) { a in - switch a { - case let .testsFailed(fs): - let msg = fs.map { (srv, f) in - "\(srv): \(f.localizedDescription)" - }.joined(separator: "\n") - return Alert( - title: Text("Tests failed!"), - message: Text("Some servers failed the test:\n" + msg) - ) - case .error: - return Alert( - title: Text("Error") - ) - } - } - .onAppear { - // this condition is needed to prevent re-setting the servers when exiting single server view - if justOpened { - do { - let r = try getUserProtoServers(serverProtocol) - currServers = r.protoServers - presetServers = r.presetServers - partitionServers(currServers) - } catch let error { - alert = .error( - title: "Error loading \(proto) servers", - error: "Error: \(responseError(error))" - ) - } - justOpened = false - } else { - partitionServers(allServers) - } - } - } - - private func partitionServers(_ servers: [ServerCfg]) { - configuredServers = servers.filter { $0.preset || $0.enabled } - otherServers = servers.filter { !($0.preset || $0.enabled) } - } - - private var allServers: [ServerCfg] { - configuredServers + otherServers - } - - private var saveDisabled: Bool { - allServers.isEmpty || - Set(allServers) == Set(currServers) || - testing || - !allServers.allSatisfy { srv in - if let address = parseServerAddress(srv.server) { - return uniqueAddress(srv, address) - } - return false - } || - allServersDisabled - } - - private var allServersDisabled: Bool { - allServers.allSatisfy { !$0.enabled } - } - - private func protocolServerView(_ server: Binding) -> some View { - let srv = server.wrappedValue - return NavigationLink(tag: srv.id, selection: $selectedServer) { - ProtocolServerView( - serverProtocol: serverProtocol, - server: server, - serverToEdit: srv - ) - .navigationBarTitle(srv.preset ? "Preset server" : "Your server") - .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.large) - } label: { - let address = parseServerAddress(srv.server) - HStack { - Group { - if let address = address { - if !address.valid || address.serverProtocol != serverProtocol { - invalidServer() - } else if !uniqueAddress(srv, address) { - Image(systemName: "exclamationmark.circle").foregroundColor(.red) - } else if !srv.enabled { - Image(systemName: "slash.circle").foregroundColor(theme.colors.secondary) - } else { - showTestStatus(server: srv) - } - } else { - invalidServer() - } - } - .frame(width: 16, alignment: .center) - .padding(.trailing, 4) - - let v = Text(address?.hostnames.first ?? srv.server).lineLimit(1) - if srv.enabled { - v - } else { - v.foregroundColor(theme.colors.secondary) - } - } - } - } - - func howToButton() -> some View { - Button { - DispatchQueue.main.async { - UIApplication.shared.open(howToUrl) - } - } label: { - HStack { - Text("How to use your servers") - Image(systemName: "arrow.up.right.circle") - } - } - } - - private func invalidServer() -> some View { - Image(systemName: "exclamationmark.circle").foregroundColor(.red) - } - - private func uniqueAddress(_ s: ServerCfg, _ address: ServerAddress) -> Bool { - allServers.allSatisfy { srv in - address.hostnames.allSatisfy { host in - srv.id == s.id || !srv.server.contains(host) - } - } - } - - private func hasAllPresets() -> Bool { - presetServers.allSatisfy { hasPreset($0) } - } - - private func addAllPresets() { - for srv in presetServers { - if !hasPreset(srv) { - configuredServers.append(srv) - } - } - } - - private func hasPreset(_ srv: ServerCfg) -> Bool { - allServers.contains(where: { $0.server == srv.server }) - } - - private func testServers() { - resetTestStatus() - testing = true - Task { - let fs = await runServersTest() - await MainActor.run { - testing = false - if !fs.isEmpty { - alert = .testsFailed(failures: fs) - } - } - } - } - - private func resetTestStatus() { - for i in 0.. [String: ProtocolTestFailure] { - var fs: [String: ProtocolTestFailure] = [:] - for i in 0..(defaults: UserDefaults.standard, forKey: DEFAULT_CURRENT_THEME_IDS, withDefault: [:] ) @@ -245,13 +259,14 @@ public class CodableDefault { } } +let networkProxyDefault: CodableDefault = CodableDefault(defaults: UserDefaults.standard, forKey: DEFAULT_NETWORK_PROXY, withDefault: NetworkProxy.def) struct SettingsView: View { @Environment(\.colorScheme) var colorScheme + @Environment(\.dismiss) var dismiss @EnvironmentObject var chatModel: ChatModel @EnvironmentObject var sceneDelegate: SceneDelegate @EnvironmentObject var theme: AppTheme - @Binding var showSettings: Bool @State private var showProgress: Bool = false var body: some View { @@ -260,71 +275,12 @@ struct SettingsView: View { if showProgress { progressView() } - if let la = chatModel.laRequest { - LocalAuthView(authRequest: la) - } } } @ViewBuilder func settingsView() -> some View { let user = chatModel.currentUser - NavigationView { List { - Section(header: Text("You").foregroundColor(theme.colors.secondary)) { - if let user = user { - NavigationLink { - UserProfile() - .navigationTitle("Your current profile") - .modifier(ThemedBackground()) - } label: { - ProfilePreview(profileOf: user) - .padding(.leading, -8) - } - } - - NavigationLink { - UserProfilesView(showSettings: $showSettings) - } label: { - settingsRow("person.crop.rectangle.stack", color: theme.colors.secondary) { Text("Your chat profiles") } - } - - - if let user = user { - NavigationLink { - UserAddressView(shareViaProfile: user.addressShared) - .navigationTitle("SimpleX address") - .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.large) - } label: { - settingsRow("qrcode", color: theme.colors.secondary) { Text("Your SimpleX address") } - } - - NavigationLink { - PreferencesView(profile: user.profile, preferences: user.fullPreferences, currentPreferences: user.fullPreferences) - .navigationTitle("Your preferences") - .modifier(ThemedBackground(grouped: true)) - } label: { - settingsRow("switch.2", color: theme.colors.secondary) { Text("Chat preferences") } - } - } - - NavigationLink { - ConnectDesktopView(viaSettings: true) - } label: { - settingsRow("desktopcomputer", color: theme.colors.secondary) { Text("Use from desktop") } - } - - NavigationLink { - MigrateFromDevice(showSettings: $showSettings, showProgressOnSettings: $showProgress) - .navigationTitle("Migrate device") - .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.large) - } label: { - settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") } - } - } - .disabled(chatModel.chatRunning != true) - Section(header: Text("Settings").foregroundColor(theme.colors.secondary)) { NavigationLink { NotificationsView() @@ -375,14 +331,29 @@ struct SettingsView: View { } .disabled(chatModel.chatRunning != true) } - - chatDatabaseRow() } + Section(header: Text("Chat database").foregroundColor(theme.colors.secondary)) { + chatDatabaseRow() + NavigationLink { + MigrateFromDevice(showProgressOnSettings: $showProgress) + .toolbar { + // Redaction broken for `.navigationTitle` - using a toolbar item instead. + ToolbarItem(placement: .principal) { + Text("Migrate device").font(.headline) + } + } + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.large) + } label: { + settingsRow("tray.and.arrow.up", color: theme.colors.secondary) { Text("Migrate to another device") } + } + } + Section(header: Text("Help").foregroundColor(theme.colors.secondary)) { if let user = user { NavigationLink { - ChatHelp(showSettings: $showSettings) + ChatHelp(dismissSettingsSheet: dismiss) .navigationTitle("Welcome \(user.displayName)!") .modifier(ThemedBackground()) .frame(maxHeight: .infinity, alignment: .top) @@ -391,7 +362,7 @@ struct SettingsView: View { } } NavigationLink { - WhatsNewView(viaSettings: true) + WhatsNewView(viaSettings: true, updatedConditions: false) .modifier(ThemedBackground()) .navigationBarTitleDisplayMode(.inline) } label: { @@ -407,7 +378,7 @@ struct SettingsView: View { } settingsRow("number", color: theme.colors.secondary) { Button("Send questions and ideas") { - showSettings = false + dismiss() DispatchQueue.main.async { UIApplication.shared.open(simplexTeamURL) } @@ -456,16 +427,15 @@ struct SettingsView: View { } .navigationTitle("Your settings") .modifier(ThemedBackground(grouped: true)) - } - .onDisappear { - chatModel.showingTerminal = false - chatModel.terminalItems = [] - } + .onDisappear { + chatModel.showingTerminal = false + chatModel.terminalItems = [] + } } private func chatDatabaseRow() -> some View { NavigationLink { - DatabaseView(showSettings: $showSettings, chatItemTTL: chatModel.chatItemTTL) + DatabaseView(dismissSettingsSheet: dismiss, chatItemTTL: chatModel.chatItemTTL) .navigationTitle("Your chat database") .modifier(ThemedBackground(grouped: true)) } label: { @@ -543,26 +513,25 @@ struct ProfilePreview: View { HStack { ProfileImage(imageStr: profileOf.image, size: 44, color: color) .padding(.trailing, 6) - .padding(.vertical, 6) - VStack(alignment: .leading) { - Text(profileOf.displayName) - .fontWeight(.bold) - .font(.title2) - if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName { - Text(profileOf.fullName) - } - } + profileName(profileOf).lineLimit(1) } } } +func profileName(_ profileOf: NamedChat) -> Text { + var t = Text(profileOf.displayName).fontWeight(.semibold).font(.title2) + if profileOf.fullName != "" && profileOf.fullName != profileOf.displayName { + t = t + Text(" (" + profileOf.fullName + ")") +// .font(.callout) + } + return t +} + struct SettingsView_Previews: PreviewProvider { static var previews: some View { let chatModel = ChatModel() chatModel.currentUser = User.sampleData - @State var showSettings = false - - return SettingsView(showSettings: $showSettings) + return SettingsView() .environmentObject(chatModel) } } diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift index 15f6a1c7d7..6c1ea8deb2 100644 --- a/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift +++ b/apps/ios/Shared/Views/UserSettings/UserAddressLearnMore.swift @@ -9,15 +9,94 @@ import SwiftUI struct UserAddressLearnMore: View { + @State var showCreateAddressButton = false + @State private var createAddressLinkActive = false + @State private var createOneTimeLinkActive = false + var body: some View { - List { - VStack(alignment: .leading, spacing: 18) { - Text("You can share your address as a link or QR code - anybody can connect to you.") - Text("You won't lose your contacts if you later delete your address.") - Text("When people request to connect, you can accept or reject it.") - Text("Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).") + VStack { + List { + VStack(alignment: .leading, spacing: 12) { + (Text(Image(systemName: "envelope")).foregroundColor(.secondary) + textSpace + Text("Share address publicly").bold().font(.title2)) + Text("Share SimpleX address on social media.") + Text("You won't lose your contacts if you later delete your address.") + + (Text(Image(systemName: "link.badge.plus")).foregroundColor(.secondary) + textSpace + Text("Share 1-time link with a friend").font(.title2).bold()) + .padding(.top) + Text("1-time link can be used *with one contact only* - share in person or via any messenger.") + Text("You can set connection name, to remember who the link was shared with.") + + if !showCreateAddressButton { + (Text(Image(systemName: "shield")).foregroundColor(.secondary) + textSpace + Text("Connection security").font(.title2).bold()) + .padding(.top) + Text("SimpleX address and 1-time links are safe to share via any messenger.") + Text("To protect against your link being replaced, you can compare contact security codes.") + Text("Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses).") + .padding(.top) + } + + } + .listRowBackground(Color.clear) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) } - .listRowBackground(Color.clear) + .frame(maxHeight: .infinity, alignment: .top) + + Spacer() + + if showCreateAddressButton { + VStack { + addressCreationButton() + .padding(.bottom) + + createOneTimeLinkButton() + } + .padding() + } + } + .frame(maxHeight: .infinity, alignment: .top) + } + + private func addressCreationButton() -> some View { + ZStack { + Button { + createAddressLinkActive = true + } label: { + Text("Create SimpleX address") + } + .buttonStyle(OnboardingButtonStyle()) + + NavigationLink(isActive: $createAddressLinkActive) { + UserAddressView(autoCreate: true) + .navigationTitle("SimpleX address") + .navigationBarTitleDisplayMode(.large) + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() + } + } + + private func createOneTimeLinkButton() -> some View { + ZStack { + Button { + createOneTimeLinkActive = true + } label: { + Text("Create 1-time link") + .font(.callout) + } + + NavigationLink(isActive: $createOneTimeLinkActive) { + NewChatView(selection: .invite) + .navigationTitle("New chat") + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } label: { + EmptyView() + } + .frame(width: 1, height: 1) + .hidden() } } } diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift index fa95c51d36..7965215b49 100644 --- a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift +++ b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift @@ -14,56 +14,33 @@ struct UserAddressView: View { @Environment(\.dismiss) var dismiss: DismissAction @EnvironmentObject private var chatModel: ChatModel @EnvironmentObject var theme: AppTheme - @State var viaCreateLinkView = false @State var shareViaProfile = false + @State var autoCreate = false @State private var aas = AutoAcceptState() @State private var savedAAS = AutoAcceptState() - @State private var ignoreShareViaProfileChange = false @State private var showMailView = false @State private var mailViewResult: Result? = nil @State private var alert: UserAddressAlert? - @State private var showSaveDialogue = false @State private var progressIndicator = false - @FocusState private var keyboardVisible: Bool private enum UserAddressAlert: Identifiable { case deleteAddress - case profileAddress(on: Bool) case shareOnCreate case error(title: LocalizedStringKey, error: LocalizedStringKey?) var id: String { switch self { case .deleteAddress: return "deleteAddress" - case let .profileAddress(on): return "profileAddress \(on)" case .shareOnCreate: return "shareOnCreate" case let .error(title, _): return "error \(title)" } } } - + var body: some View { ZStack { - if viaCreateLinkView { - userAddressScrollView() - } else { - userAddressScrollView() - .modifier(BackButton(disabled: Binding.constant(false)) { - if savedAAS == aas { - dismiss() - } else { - keyboardVisible = false - showSaveDialogue = true - } - }) - .confirmationDialog("Save settings?", isPresented: $showSaveDialogue) { - Button("Save auto-accept settings") { - saveAAS() - dismiss() - } - Button("Exit without saving") { dismiss() } - } - } + userAddressView() + if progressIndicator { ZStack { if chatModel.userAddress != nil { @@ -76,22 +53,10 @@ struct UserAddressView: View { } } } - } - - @Namespace private var bottomID - - private func userAddressScrollView() -> some View { - ScrollViewReader { proxy in - userAddressView() - .onChange(of: keyboardVisible) { _ in - if keyboardVisible { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - withAnimation { - proxy.scrollTo(bottomID, anchor: .top) - } - } - } - } + .onAppear { + if chatModel.userAddress == nil, autoCreate { + createAddress() + } } } @@ -103,14 +68,18 @@ struct UserAddressView: View { aas = AutoAcceptState(userAddress: userAddress) savedAAS = aas } - .onChange(of: aas.enable) { _ in - if !aas.enable { aas = AutoAcceptState() } - } } else { Section { createAddressButton() - } footer: { - Text("Create an address to let people connect with you.") + } header: { + Text("For social media") + .foregroundColor(theme.colors.secondary) + } + + Section { + createOneTimeLinkButton() + } header: { + Text("Or to share privately") .foregroundColor(theme.colors.secondary) } @@ -126,8 +95,8 @@ struct UserAddressView: View { title: Text("Delete address?"), message: shareViaProfile - ? Text("All your contacts will remain connected. Profile update will be sent to your contacts.") - : Text("All your contacts will remain connected."), + ? Text("All your contacts will remain connected. Profile update will be sent to your contacts.") + : Text("All your contacts will remain connected."), primaryButton: .destructive(Text("Delete")) { progressIndicator = true Task { @@ -137,7 +106,6 @@ struct UserAddressView: View { chatModel.userAddress = nil chatModel.updateUser(u) if shareViaProfile { - ignoreShareViaProfileChange = true shareViaProfile = false } } @@ -150,37 +118,12 @@ struct UserAddressView: View { } }, secondaryButton: .cancel() ) - case let .profileAddress(on): - if on { - return Alert( - title: Text("Share address with contacts?"), - message: Text("Profile update will be sent to your contacts."), - primaryButton: .default(Text("Share")) { - setProfileAddress(on) - }, secondaryButton: .cancel() { - ignoreShareViaProfileChange = true - shareViaProfile = !on - } - ) - } else { - return Alert( - title: Text("Stop sharing address?"), - message: Text("Profile update will be sent to your contacts."), - primaryButton: .default(Text("Stop sharing")) { - setProfileAddress(on) - }, secondaryButton: .cancel() { - ignoreShareViaProfileChange = true - shareViaProfile = !on - } - ) - } case .shareOnCreate: return Alert( title: Text("Share address with contacts?"), message: Text("Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts."), primaryButton: .default(Text("Share")) { - setProfileAddress(true) - ignoreShareViaProfileChange = true + setProfileAddress($progressIndicator, true) shareViaProfile = true }, secondaryButton: .cancel() ) @@ -195,19 +138,39 @@ struct UserAddressView: View { SimpleXLinkQRCode(uri: userAddress.connReqContact) .id("simplex-contact-address-qrcode-\(userAddress.connReqContact)") shareQRCodeButton(userAddress) - if MFMailComposeViewController.canSendMail() { - shareViaEmailButton(userAddress) + // if MFMailComposeViewController.canSendMail() { + // shareViaEmailButton(userAddress) + // } + settingsRow("briefcase", color: theme.colors.secondary) { + Toggle("Business address", isOn: $aas.business) + .onChange(of: aas.business) { ba in + if ba { + aas.enable = true + aas.incognito = false + } + saveAAS($aas, $savedAAS) + } } - shareWithContactsButton() - autoAcceptToggle() - learnMoreButton() + addressSettingsButton(userAddress) } header: { - Text("Address") + Text("For social media") + .foregroundColor(theme.colors.secondary) + } footer: { + if aas.business { + Text("Add your team members to the conversations.") + .foregroundColor(theme.colors.secondary) + } + } + + Section { + createOneTimeLinkButton() + } header: { + Text("Or to share privately") .foregroundColor(theme.colors.secondary) } - if aas.enable { - autoAcceptSection() + Section { + learnMoreButton() } Section { @@ -216,32 +179,47 @@ struct UserAddressView: View { Text("Your contacts will remain connected.") .foregroundColor(theme.colors.secondary) } - .id(bottomID) } private func createAddressButton() -> some View { Button { - progressIndicator = true - Task { - do { - let connReqContact = try await apiCreateUserAddress() - DispatchQueue.main.async { - chatModel.userAddress = UserContactLink(connReqContact: connReqContact) - alert = .shareOnCreate - progressIndicator = false - } - } catch let error { - logger.error("UserAddressView apiCreateUserAddress: \(responseError(error))") - let a = getErrorAlert(error, "Error creating address") - alert = .error(title: a.title, error: a.message) - await MainActor.run { progressIndicator = false } - } - } + createAddress() } label: { Label("Create SimpleX address", systemImage: "qrcode") } } + private func createAddress() { + progressIndicator = true + Task { + do { + let connReqContact = try await apiCreateUserAddress() + DispatchQueue.main.async { + chatModel.userAddress = UserContactLink(connReqContact: connReqContact) + alert = .shareOnCreate + progressIndicator = false + } + } catch let error { + logger.error("UserAddressView apiCreateUserAddress: \(responseError(error))") + let a = getErrorAlert(error, "Error creating address") + alert = .error(title: a.title, error: a.message) + await MainActor.run { progressIndicator = false } + } + } + } + + private func createOneTimeLinkButton() -> some View { + NavigationLink { + NewChatView(selection: .invite) + .navigationTitle("New chat") + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } label: { + Label("Create 1-time link", systemImage: "link.badge.plus") + .foregroundColor(theme.colors.primary) + } + } + private func deleteAddressButton() -> some View { Button(role: .destructive) { alert = .deleteAddress @@ -291,24 +269,140 @@ struct UserAddressView: View { } } - private func autoAcceptToggle() -> some View { - settingsRow("checkmark", color: theme.colors.secondary) { - Toggle("Auto-accept", isOn: $aas.enable) - .onChange(of: aas.enable) { _ in - saveAAS() - } + private func addressSettingsButton(_ userAddress: UserContactLink) -> some View { + NavigationLink { + UserAddressSettingsView(shareViaProfile: $shareViaProfile) + .navigationTitle("Address settings") + .navigationBarTitleDisplayMode(.large) + .modifier(ThemedBackground(grouped: true)) + } label: { + Text("Address settings") } } private func learnMoreButton() -> some View { NavigationLink { UserAddressLearnMore() - .navigationTitle("SimpleX address") + .navigationTitle("Address or 1-time link?") .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.large) + .navigationBarTitleDisplayMode(.inline) } label: { settingsRow("info.circle", color: theme.colors.secondary) { - Text("About SimpleX address") + Text("SimpleX address or 1-time link?") + } + } + } +} + +private struct AutoAcceptState: Equatable { + var enable = false + var incognito = false + var business = false + var welcomeText = "" + + init(enable: Bool = false, incognito: Bool = false, business: Bool = false, welcomeText: String = "") { + self.enable = enable + self.incognito = incognito + self.business = business + self.welcomeText = welcomeText + } + + init(userAddress: UserContactLink) { + if let aa = userAddress.autoAccept { + enable = true + incognito = aa.acceptIncognito + business = aa.businessAddress + if let msg = aa.autoReply { + welcomeText = msg.text + } else { + welcomeText = "" + } + } else { + enable = false + incognito = false + business = false + welcomeText = "" + } + } + + var autoAccept: AutoAccept? { + if enable { + var autoReply: MsgContent? = nil + let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines) + if s != "" { autoReply = .text(s) } + return AutoAccept(businessAddress: business, acceptIncognito: incognito, autoReply: autoReply) + } + return nil + } +} + +private func setProfileAddress(_ progressIndicator: Binding, _ on: Bool) { + progressIndicator.wrappedValue = true + Task { + do { + if let u = try await apiSetProfileAddress(on: on) { + DispatchQueue.main.async { + ChatModel.shared.updateUser(u) + } + } + await MainActor.run { progressIndicator.wrappedValue = false } + } catch let error { + logger.error("apiSetProfileAddress: \(responseError(error))") + await MainActor.run { progressIndicator.wrappedValue = false } + } + } +} + +struct UserAddressSettingsView: View { + @Environment(\.dismiss) var dismiss: DismissAction + @EnvironmentObject var theme: AppTheme + @Binding var shareViaProfile: Bool + @State private var aas = AutoAcceptState() + @State private var savedAAS = AutoAcceptState() + @State private var ignoreShareViaProfileChange = false + @State private var progressIndicator = false + @FocusState private var keyboardVisible: Bool + + var body: some View { + ZStack { + if let userAddress = ChatModel.shared.userAddress { + userAddressSettingsView() + .onAppear { + aas = AutoAcceptState(userAddress: userAddress) + savedAAS = aas + } + .onChange(of: aas.enable) { aasEnabled in + if !aasEnabled { aas = AutoAcceptState() } + } + .onDisappear { + if savedAAS != aas { + showAlert( + title: NSLocalizedString("Auto-accept settings", comment: "alert title"), + message: NSLocalizedString("Settings were changed.", comment: "alert message"), + buttonTitle: NSLocalizedString("Save", comment: "alert button"), + buttonAction: { saveAAS($aas, $savedAAS) }, + cancelButton: true + ) + } + } + } else { + Text(String("Error opening address settings")) + } + if progressIndicator { + ProgressView().scaleEffect(2) + } + } + } + + private func userAddressSettingsView() -> some View { + List { + Section { + shareWithContactsButton() + autoAcceptToggle().disabled(aas.business) + } + + if aas.enable { + autoAcceptSection() } } } @@ -320,70 +414,70 @@ struct UserAddressView: View { if ignoreShareViaProfileChange { ignoreShareViaProfileChange = false } else { - alert = .profileAddress(on: on) + if on { + showAlert( + NSLocalizedString("Share address with contacts?", comment: "alert title"), + message: NSLocalizedString("Profile update will be sent to your contacts.", comment: "alert message"), + actions: {[ + UIAlertAction( + title: NSLocalizedString("Cancel", comment: "alert action"), + style: .default, + handler: { _ in + ignoreShareViaProfileChange = true + shareViaProfile = !on + } + ), + UIAlertAction( + title: NSLocalizedString("Share", comment: "alert action"), + style: .default, + handler: { _ in + setProfileAddress($progressIndicator, on) + } + ) + ]} + ) + } else { + showAlert( + NSLocalizedString("Stop sharing address?", comment: "alert title"), + message: NSLocalizedString("Profile update will be sent to your contacts.", comment: "alert message"), + actions: {[ + UIAlertAction( + title: NSLocalizedString("Cancel", comment: "alert action"), + style: .default, + handler: { _ in + ignoreShareViaProfileChange = true + shareViaProfile = !on + } + ), + UIAlertAction( + title: NSLocalizedString("Stop sharing", comment: "alert action"), + style: .default, + handler: { _ in + setProfileAddress($progressIndicator, on) + } + ) + ]} + ) + } } } } } - private func setProfileAddress(_ on: Bool) { - progressIndicator = true - Task { - do { - if let u = try await apiSetProfileAddress(on: on) { - DispatchQueue.main.async { - chatModel.updateUser(u) - } + private func autoAcceptToggle() -> some View { + settingsRow("checkmark", color: theme.colors.secondary) { + Toggle("Auto-accept", isOn: $aas.enable) + .onChange(of: aas.enable) { _ in + saveAAS($aas, $savedAAS) } - await MainActor.run { progressIndicator = false } - } catch let error { - logger.error("UserAddressView apiSetProfileAddress: \(responseError(error))") - await MainActor.run { progressIndicator = false } - } } } - private struct AutoAcceptState: Equatable { - var enable = false - var incognito = false - var welcomeText = "" - - init(enable: Bool = false, incognito: Bool = false, welcomeText: String = "") { - self.enable = enable - self.incognito = incognito - self.welcomeText = welcomeText - } - - init(userAddress: UserContactLink) { - if let aa = userAddress.autoAccept { - enable = true - incognito = aa.acceptIncognito - if let msg = aa.autoReply { - welcomeText = msg.text - } else { - welcomeText = "" - } - } else { - enable = false - incognito = false - welcomeText = "" - } - } - - var autoAccept: AutoAccept? { - if enable { - var autoReply: MsgContent? = nil - let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines) - if s != "" { autoReply = .text(s) } - return AutoAccept(acceptIncognito: incognito, autoReply: autoReply) - } - return nil - } - } - - @ViewBuilder private func autoAcceptSection() -> some View { + private func autoAcceptSection() -> some View { Section { - acceptIncognitoToggle() + if !aas.business { + acceptIncognitoToggle() + } welcomeMessageEditor() saveAASButton() .disabled(aas == savedAAS) @@ -423,22 +517,24 @@ struct UserAddressView: View { private func saveAASButton() -> some View { Button { keyboardVisible = false - saveAAS() + saveAAS($aas, $savedAAS) } label: { Text("Save") } } +} - private func saveAAS() { - Task { - do { - if let address = try await userAddressAutoAccept(aas.autoAccept) { - chatModel.userAddress = address - savedAAS = aas +private func saveAAS(_ aas: Binding, _ savedAAS: Binding) { + Task { + do { + if let address = try await userAddressAutoAccept(aas.wrappedValue.autoAccept) { + await MainActor.run { + ChatModel.shared.userAddress = address + savedAAS.wrappedValue = aas.wrappedValue } - } catch let error { - logger.error("userAddressAutoAccept error: \(responseError(error))") } + } catch let error { + logger.error("userAddressAutoAccept error: \(responseError(error))") } } } @@ -447,6 +543,8 @@ struct UserAddressView_Previews: PreviewProvider { static var previews: some View { let chatModel = ChatModel() chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D") + + return Group { UserAddressView() .environmentObject(chatModel) diff --git a/apps/ios/Shared/Views/UserSettings/UserProfile.swift b/apps/ios/Shared/Views/UserSettings/UserProfile.swift index 198fd495bd..8a70efbe82 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfile.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfile.swift @@ -11,8 +11,11 @@ import SimpleXChat struct UserProfile: View { @EnvironmentObject var chatModel: ChatModel + @EnvironmentObject var theme: AppTheme + @AppStorage(DEFAULT_PROFILE_IMAGE_CORNER_RADIUS) private var radius = defaultProfileImageCorner @State private var profile = Profile(displayName: "", fullName: "") - @State private var editProfile = false + @State private var currentProfileHash: Int? + // Modals @State private var showChooseSource = false @State private var showImagePicker = false @State private var showTakePhoto = false @@ -21,85 +24,86 @@ struct UserProfile: View { @FocusState private var focusDisplayName var body: some View { - let user: User = chatModel.currentUser! - - return VStack(alignment: .leading) { - Text("Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile.") - .padding(.bottom) - - if editProfile { - ZStack(alignment: .center) { - ZStack(alignment: .topTrailing) { + List { + Group { + if profile.image != nil { + ZStack(alignment: .bottomTrailing) { + ZStack(alignment: .topTrailing) { + profileImageView(profile.image) + .onTapGesture { showChooseSource = true } + overlayButton("multiply", edge: .top) { profile.image = nil } + } + overlayButton("camera", edge: .bottom) { showChooseSource = true } + } + } else { + ZStack(alignment: .center) { profileImageView(profile.image) - if user.image != nil { - Button { - profile.image = nil - } label: { - Image(systemName: "multiply") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 12) - } + editImageButton { showChooseSource = true } + } + } + } + .frame(maxWidth: .infinity, alignment: .center) + .listRowBackground(Color.clear) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + .padding(.top) + .contentShape(Rectangle()) + + Section { + HStack { + TextField("Enter your name…", text: $profile.displayName) + .focused($focusDisplayName) + if !validDisplayName(profile.displayName) { + Button { + alert = .invalidNameError(validName: mkValidName(profile.displayName)) + } label: { + Image(systemName: "exclamationmark.circle").foregroundColor(.red) } } - - editImageButton { showChooseSource = true } } - .frame(maxWidth: .infinity, alignment: .center) - - VStack(alignment: .leading) { - ZStack(alignment: .leading) { - if !validNewProfileName(user) { - Button { - alert = .invalidNameError(validName: mkValidName(profile.displayName)) - } label: { - Image(systemName: "exclamationmark.circle").foregroundColor(.red) - } - } else { - Image(systemName: "exclamationmark.circle").foregroundColor(.clear) - } - profileNameTextEdit("Profile name", $profile.displayName) - .focused($focusDisplayName) - } - .padding(.bottom) - if showFullName(user) { - profileNameTextEdit("Full name (optional)", $profile.fullName) - .padding(.bottom) - } - HStack(spacing: 20) { - Button("Cancel") { editProfile = false } - Button("Save (and notify contacts)") { saveProfile() } - .disabled(!canSaveProfile(user)) - } + if let user = chatModel.currentUser, showFullName(user) { + TextField("Full name (optional)", text: $profile.fullName) } - .frame(maxWidth: .infinity, minHeight: 120, alignment: .leading) - } else { - ZStack(alignment: .center) { - profileImageView(user.image) - .onTapGesture { startEditingImage(user) } + } footer: { + Text("Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile.") + } - if user.image == nil { - editImageButton { startEditingImage(user) } - } + Section { + Button(action: getCurrentProfile) { + Text("Reset") } - .frame(maxWidth: .infinity, alignment: .center) - - VStack(alignment: .leading) { - profileNameView("Profile name:", user.profile.displayName) - if showFullName(user) { - profileNameView("Full name:", user.profile.fullName) - } - Button("Edit") { - profile = fromLocalProfile(user.profile) - editProfile = true - focusDisplayName = true - } + .disabled(currentProfileHash == profile.hashValue) + Button(action: saveProfile) { + Text("Save (and notify contacts)") } - .frame(maxWidth: .infinity, minHeight: 120, alignment: .leading) + .disabled(!canSaveProfile) } } - .padding() - .frame(maxHeight: .infinity, alignment: .top) + // Lifecycle + .onAppear { + getCurrentProfile() + } + .onDisappear { + if canSaveProfile { + showAlert( + title: NSLocalizedString("Save your profile?", comment: "alert title"), + message: NSLocalizedString("Your profile was changed. If you save it, the updated profile will be sent to all your contacts.", comment: "alert message"), + buttonTitle: NSLocalizedString("Save (and notify contacts)", comment: "alert button"), + buttonAction: saveProfile, + cancelButton: true + ) + } + } + .onChange(of: chosenImage) { image in + Task { + let resized: String? = if let image { + await resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) + } else { + nil + } + await MainActor.run { profile.image = resized } + } + } + // Modals .confirmationDialog("Profile image", isPresented: $showChooseSource, titleVisibility: .visible) { Button("Take picture") { showTakePhoto = true @@ -126,57 +130,49 @@ struct UserProfile: View { } } } - .onChange(of: chosenImage) { image in - if let image = image { - profile.image = resizeImageToStrSize(cropToSquare(image), maxDataSize: 12500) - } else { - profile.image = nil - } - } .alert(item: $alert) { a in userProfileAlert(a, $profile.displayName) } } - func profileNameTextEdit(_ label: LocalizedStringKey, _ name: Binding) -> some View { - TextField(label, text: name) - .padding(.leading, 32) - } - - func profileNameView(_ label: LocalizedStringKey, _ name: String) -> some View { - HStack { - Text(label) - Text(name).fontWeight(.bold) - } - .padding(.bottom) - } - - func startEditingImage(_ user: User) { - profile = fromLocalProfile(user.profile) - editProfile = true - showChooseSource = true - } - - private func validNewProfileName(_ user: User) -> Bool { - profile.displayName == user.profile.displayName || validDisplayName(profile.displayName.trimmingCharacters(in: .whitespaces)) + @ViewBuilder + private func overlayButton( + _ systemName: String, + edge: Edge.Set, + action: @escaping () -> Void + ) -> some View { + Image(systemName: systemName) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 12) + .foregroundColor(theme.colors.primary) + .padding(6) + .frame(width: 36, height: 36, alignment: .center) + .background(radius >= 20 ? Color.clear : theme.colors.background.opacity(0.5)) + .clipShape(Circle()) + .contentShape(Circle()) + .padding([.trailing, edge], -12) + .onTapGesture(perform: action) } private func showFullName(_ user: User) -> Bool { user.profile.fullName != "" && user.profile.fullName != user.profile.displayName } - - private func canSaveProfile(_ user: User) -> Bool { - profile.displayName.trimmingCharacters(in: .whitespaces) != "" && validNewProfileName(user) + + private var canSaveProfile: Bool { + currentProfileHash != profile.hashValue && + profile.displayName.trimmingCharacters(in: .whitespaces) != "" && + validDisplayName(profile.displayName) } - func saveProfile() { + private func saveProfile() { + focusDisplayName = false Task { do { profile.displayName = profile.displayName.trimmingCharacters(in: .whitespaces) if let (newProfile, _) = try await apiUpdateProfile(profile: profile) { - DispatchQueue.main.async { + await MainActor.run { chatModel.updateCurrentUser(newProfile) - profile = newProfile + getCurrentProfile() } - editProfile = false } else { alert = .duplicateUserError } @@ -185,6 +181,13 @@ struct UserProfile: View { } } } + + private func getCurrentProfile() { + if let user = chatModel.currentUser { + profile = fromLocalProfile(user.profile) + currentProfileHash = profile.hashValue + } + } } func profileImageView(_ imageStr: String?) -> some View { @@ -201,19 +204,3 @@ func editImageButton(action: @escaping () -> Void) -> some View { .frame(width: 48) } } - -struct UserProfile_Previews: PreviewProvider { - static var previews: some View { - let chatModel1 = ChatModel() - chatModel1.currentUser = User.sampleData - let chatModel2 = ChatModel() - chatModel2.currentUser = User.sampleData - chatModel2.currentUser?.profile.image = "data:image/jpg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBMRXhpZgAATU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAAqACAAQAAAABAAAAgKADAAQAAAABAAAAgAAAAAD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/+ICNElDQ19QUk9GSUxFAAEBAAACJGFwcGwEAAAAbW50clJHQiBYWVogB+EABwAHAA0AFgAgYWNzcEFQUEwAAAAAQVBQTAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1hcHBsyhqVgiV/EE04mRPV0eoVggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZGVzYwAAAPwAAABlY3BydAAAAWQAAAAjd3RwdAAAAYgAAAAUclhZWgAAAZwAAAAUZ1hZWgAAAbAAAAAUYlhZWgAAAcQAAAAUclRSQwAAAdgAAAAgY2hhZAAAAfgAAAAsYlRSQwAAAdgAAAAgZ1RSQwAAAdgAAAAgZGVzYwAAAAAAAAALRGlzcGxheSBQMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBJbmMuLCAyMDE3AABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAACD3wAAPb////+7WFlaIAAAAAAAAEq/AACxNwAACrlYWVogAAAAAAAAKDgAABELAADIuXBhcmEAAAAAAAMAAAACZmYAAPKnAAANWQAAE9AAAApbc2YzMgAAAAAAAQxCAAAF3v//8yYAAAeTAAD9kP//+6L///2jAAAD3AAAwG7/wAARCACAAIADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9sAQwABAQEBAQECAQECAwICAgMEAwMDAwQGBAQEBAQGBwYGBgYGBgcHBwcHBwcHCAgICAgICQkJCQkLCwsLCwsLCwsL/9sAQwECAgIDAwMFAwMFCwgGCAsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL/90ABAAI/9oADAMBAAIRAxEAPwD4N1TV59SxpunRtBb/APPP/lo+eMsf4R+uKyxNa6Y32a3UTzjoi8Ip9/8AOfYV0tx4d1a8VlsojaWo6uThj+Pb6Cs2CCGyP2LQ4xPIMBpGIVVz7ngV+Ap31P2C1iSDQbnWXRtVYyMT8kSDkZ9B29zXXReD7ZVOkX0QlLgg2ycjBH8ZHXPoOK9O8L6LpljZidWMjyqMzAdc/wB3PJ+p4qjrPiuxs1a38LwLJIn35ScoP94jlm9hxW8ZKJm1fY/Gv4yeA/E37L3xf07xz4GuH0260+7i1bRLpDkwzQOHVfQ+WwAI7r1zmv7fv2Nv2nfCv7YH7PHh346+FwkD6nEYtRs1OTZ6jBhbiA98K/zJnrGynvX8u3x3+G6fFvwXcadcOZNTQebZyN1EgH3QB91W6H657VD/AMEYP2qdQ/Zb/aRuPgN8RpjZeFviJcJabJztWy1tPkgkOeFE3+ok9zGTwtfY5Nj1Vjyt6nzuZ4XlfMj+zamH5TupVYnhhgjsaRyMYNe8eEMC7jxxU+1SMYFQFyaevPWgRqaeuSVFb0SDgAZI/SsLS9w4kxux1HTNdTEAMDvQJst20UitvA4rotMh8ycbuAv6k1Rs3UgcHjrXc6Xb2iTKVIJPQEcZ96qKMW7nWabpNmzRyEE9wOlegtplzFCLiMbEcfKw5/XP51l6ZPK6b2SJsdd64A/Kr0t5fyRsqsPLU5baNo49P0q2I//Q8iuPD17eeTpVy32u2ufls5lAC5P8MmOA2O/Q/XIrHl+GWn+CGN7qyC9ugxkSID92nvz1+pwK/TKb9j34t3Pw/PjXXrpdR165L3F7pkiDz5RISzHzFIUzliXKBQCTgMGwD8P6zompRzR2V2xuLWV9sE7ggo4yPLlBxhgRgE8k8cHivyPPMl9g3iMMrw6r+X/gH6PlmZ+1tRrP3uj7/wDBPnjXdR1rXWDao5jtm4S3h43gf3jwSPyH1rW0Xw9f6uyw2MYSNAAT/Ag/qa9ii+GTWEv2nV8nfztH3m/+t/nirMsVtMPscGIYYuCqjj8fWvmo+9qz227aI5O38NeH/DeJIGE079ZW9fQf/W/Ovyx/ba+C1x/aR+K/h6FoLa5dUvDH8rRzj7kgI+7ux253DPev1yuINKtF3XriOMDlm+83+6O1eNePZoPH2h3ngWC032N7E0UhI7HuPcdQfWvQweJdKakjkxFFTjZn6+f8Eu/2yE/a+/Zss9R8TXCyeMvCpTSfECZ+eSZF/dXWPS5jG4n/AJ6Bx2r9JGbd0r+GX9jD476z/wAE5v20IL3xPM7eGdUZdK8QBeUewmYGO6A7tbviT127171/cfaXdve28d1aSJNFKqukiHcjqwyGUjggggg9xX6Dhq6q01JM+NxVF05tdCyRQCOvakY4GRTFYd66DmN2xk2sK6eE5+YVxlo5EwB4rrLZiTyePWgmSOmsAThCcZPFdxZ5KruJyprgrWQ5G3tXS21+FABzVrYyZ6ZZTTSqCR8vQ4rUudWgW1e3QMrBScj1/D+tcpp1+UXaOn09fWtKP7OAzNjK+tNiP//R/oYjkSW9NgqsWVA7HHyrk4AJ9Tzx6CvjL9qz4M+FrbRrn4q2s0Fjcs6R3ttKdsd+ZCFBUf8APx0xj/WAYOCA1fVF58Y/hbb/AAwPxlXWIH8OCHzhdKc57bAv3vM3fLsxu3cYzX58eGdH8f8A7b/xIHi/xOs2k+DNGkK28AOCgPVQejXMg++/IiU7RyefmI+Z79+qPl++0JpR/wATG7Z9M4WOQfeVv7srdT/snp+NeWa9bfZXez8KxCZQcGVhiJT/AOzH6fnX7K/Fn9mfwzf6N9r+GmnwWV3DF5UlmBiC8iAxtbPAkx0c/e6N/eH5s+IvDcuj2jWcUTJYwsYXDrtktHXgxuvBxngE9Oh9/is6yVUr4nDL3Oq7enl+R9Plmac9qNZ+90ff/gnybLoheT7XrM3nMo5JH8h2HtXJa9/aGoMYbAC0gTqwH7x1H8hXsHiWGDRUboqr/Eeck+nrXj9/d3twWmlzbQHnn77e/tXzaqXXuntuNtz4z/ay+Eul+NPAf9u+H4TLq2kqzEAfNLAeXU/T7w/Ed6/XL/giD+2n/wALr+Ck37Nnjq78zxV8PYkW0Z2+a60VjthbJ5LWzfuW/wBjyz3NfCGuJLLm30tSsT8OT/U1+b1v4w8VfsE/tXeHf2kfhqjz2Vvcl5rdDiO4tZflu7Q+zoSUz0baeq19RkWMUZexk/Q8LNMLzx51uf3yIxPXvTQuTkVw3wz+IfhH4seBNG+JngS7W+0XX7OG/sp1P34ZlDLn0Izhh2YEGu+LAHFfXo+XJ4P9cp6YNdbCWHFcerFSCK6OGcMBk0wOmtZMVswurDNcnHKB7VqxXbDGKaZEoncRXpt4iy8fWlN44XdM5+bGPauWbUAI9p5NeH/E39oTwF8OAdO1W6+06kfuWVuQ0vtvOcIPdiPalOrGC5pOyHToym7RV2f/0nXmiaPrF/ceJvC1hrUnhC11EyFGZsIN2Mtg+QLjy+A5GQcZI6V/QP8ABrWvhd4i+GmnXXwZeI6DAnkxRxgq0LL95JFb5hJnO7dyTz3qt4f8EeCPC3g5Pht4csYItKt4fKNngMpjfOd4PJLckk8k18FeKvBXj79kHxu/xW+ECte+F711XUtNdiVC54VvQj/lnL2+63FfNNqWh7rVtT9JdItdaitpV8QSxyy+a5VowVURE/KDnuB1PQ9a/OD4yfEbwv8AEP4rx6F8JNIfXb4QyQXMlqAwvmQgEBThSkQBUysQpyFBOBjE+NH7WWu/HtrH4QfACxvYpNZHl3bSr5M7kjLQqc/JGo5ml/u8DrX2X+z38A9C+B3hzyQUvNbvVX7dehcA7ekUQ/hiT+Fe/U81m1bVj1Px/wDiX4FXQ4b7WNItJXitXZLq3nU+fpzjqpQ87PQ88eowa+JdanuvP+03JzG3Kk87voP8a/pi+NPwStfiAo8V+GDHaeI7aPYsjj91dxj/AJYzjuOyv1X6V+Mfxk+By6eL7xPodhLE9kzDUNJYfvbSXqWUd4z147cjivjc3ybkviMMtOq7eaPo8tzXmtRrvXo/8z4aaC/1a3drrbDbr6nCgepPc+36V4T8Z/A/h7xz4KvPB8uGmcb4LhhxHKv3WUeh6HPY17TrMuo3dysUA3p0VUGEArCudFt7aH7bqjguOQP6V89SquLUk9T26lNNWZ7L/wAEJv2vNQ8L6xq/7BPxZma3ureafUPDHnHvy93Zg/X9/EO+XA7Cv6fFwRnNfwWftIWHi/wL4u0T9pX4Vu2ma74buobpJY+GEkDBo5CO4B+Vx3U4PFf2VfshftPeFf2tv2e/Dvx18LbYhq0G29tQcm0vovluID/uPkr6oVPev0TLsWq9FT69T43MMN7KpdbM+q1kA+WtuF8qCa5H7SD0qvrnjbw34L0KTxD4qvobCyhBLzTuFUY7DPU+wya7nNJXZwxu3ZHoqyqq5JxXnPxL+Nvw3+EemjUPHmqxWIbPlxcvNIR2WNcsfrjFflz8cf8AgpDJMZ/DvwKgwOVOq3S/rFGf0LV8MaZp/jf4j603ibxTdT3U053PdXRLu+eflB7fkK8PFZ5TheNHV/h/wT2cLlFSfvVNF+J+hnxI/ba8cfEa5fQfhnG+h6e5KCY/NeTD6jIjH0yfcV514W8HX2plrjUiWLEtIWbcSSOS7dST/k1x2g2PhrwdZhpyFbHzEnLk+5/oK6eDxRq2soYdPH2S0xjjh2H9K+erY+pVlzTdz3aWEhSjaCsf/9P+gafwFajxovjGKeVJSqrJEPuOVUoD7ZBGR32ivgn9pz9pHUfGOvP+zb8BIDrGr6kZLO/nhwUXH34UY/LwP9bJ91BxndxXyp41/ab/AGivht4c1D9mf+0La7vrOY6f/asUpe4WP7vlRzEhRnIHmMNyAkcEcfpB+zB+zBo37O/hQ3moBL3xLfxA312gyFA5EEOeRGp79Xb5j2x8wfQHyHZ/CP41fsg6lZ/GHT3tvEVvDC0WqxwIU8uGUqXXnnaCoIlHQj5vlOR+lPwv+Lngv4v+Gk8UeC7oTRBvLnib5ZYJcZKSL1B9D0YcgkU/QfEkXitbuzuLR7S5tGCTwS4bAfO3kcEEA5B/lg1+Yn7Qdtbfsd/E/TPiT8IdShs21jzDc6HIf3TRIQWyB0hYnCE8xt9044Ckr7k7H7AiUEf4V438U/hZa+O0TXNGkWy120XbDcEfJKn/ADxmA+8h7Hqp5HpWN8Efjv4N+OvhFfFHhOTy5otqXlnIR51tKRnaw7g9VccMOnOQPXZ71Yo2mdgiqMsWOAAOufasXoyrXPw++NX7P9zHdX174Q0wWOqW/wC81DSjjMe7J86HHDxtgnC5zzjkEV+Z3iOS20u7PlZupiT+9YYQH/ZWv6hvjRp3grXPAJ8c3t6lldabGZLC/j5be3KxY/jSUgAp+IwRkfzs/tYan4Vi+LM8nhzyo5bq2gnu4Iukd04PmDI6ZGGIHc18hnmW06K+s09LvVefkfRZTjZ1H7Cetlo/8z5d1bQk1m1ng1OMTRXCGOVX+7tbg5+tQf8ABPL9o/xV/wAE9vi/r3gDxhYahrPw18WSrMJbGMzvZXcYwkyxjn5k/dyr1OFI6VqBpJ8LdPiM9gOv0FWFTzJBFbJtzgADliT0H515uAzKphpNxV0z0sVhIVo8sj9rviP/AMFJPhxpuhJ/wqm2n1rUbhcqbmJreKLP95T8zEeg/GvzP8Y/Eb4vftA+Ije+Kb2XUWU/JCDstoAewH3Rj8TXmOi+HrJYTd63MII1OPLB+d8diev4DtXtWjeIrPTNNENtD9mjx8kY+V2H0/hH60YzNK2IdpPTsthYXL6VHWK17s2/C3gHQvDCLqPiKRZ7hei/wKfYdz7mu9/4TGa5lEGjREA8Z7/5+lec2Ntf65KLm+IjhXkZ4UCunt9X0zTONN56gu39K4k2dtlueh6Xpdxcz/a9UfMi84J4X+grv7fxNaaehi0oCWUDDSH7o+leNW99f30fls3l2+eT0z61oDVFgiEOngtgY3Y/kP61pEln/9T74+Ff/BPn4e6R8MnsPieWvfFF+haS+gkbbZM3RIQeHA/jLjMhznAwBufCz42+Mf2bPEsHwM/aNlMmiONmj6+cmIRg4Cuxz+7GQMn5oicNlcGvWf2ffiB418d/Dfwn4tvR9st9StTb3IVVUxSw8NK7E5O4qRgeo46msH9tXx78JfAfwS1CL4oQx30l8ki6XZ5Ama7VTtkQ9UWPIMjdNvynO4A/NHvnqP7Rn7Q/gX9nLwY3iXVGiudR1BS2n2aOA102PvkjpEowWfpjgcmviz9nH9njxT8afFEn7SX7TkJvJL8+bp+mXSfIUP3JJIyPljUf6qI9vmPOK+DfgboFl4V+LfhHxt+1DpWoW/he7iL6bJfRt9mLpgwOwbOYIyd23sSrFdvX+iZ7n7bY+fpkqHzU3RSj50IYZVuDhh34PIqG7bBufnr8Zv2fvF3wa8Vf8L8/ZgQ20sAJ1DR4lLRPF1fbGPvRHGWjHKn5kxjFe8fDD9qX4Q/FL4cXni/V7uHS2sIv+JpYXLgyQE/3RwZEc8Rso+bpwcive/E/irQPBOgXfizxTeJYafp8ZmnnkOFRR+pJPAA5J4GTX8uP7Uf7R3hHWPilqfjDwNpo02HVZ8wWqL84jAAaVlHAeUguVHAY/Unnq1oU6bnVdkuv6GtOlKclCmtWfQn7X37bl7qEqaB4HRbaCyXytOssgiBTgedL281hzg9Onrn8xl1eNpJNQ1C4M00zGSSV23M7HqST1Oa5K7Np44uf7Psmkubp3M0hCjcG9ZGzjn1r3fwR8LrDRokvNaIlmABw3IU/l1/yBXwWZY+eJnzS0itl/XU+tweEjh4WW73ZmaHpev8AiNhJCjW9vjh2+8w9hXqVnpukeGoFe4cqVIJdjyT2/X86W+8U2ljG1rpCiRxxu6jNeO+IrbX9amEzuwERy3rz9eB/M15jdztSPQhr7ahrEt/b/Ky8bXHIz0bn1HPP4CvW/CsEUKNqOqybQ3zZb77n2z/OvnvS2khv4r5wZLiLAUADbx6jvjtmvWNGinvbn7TqjlyRnGcjNNR0DmPTZtYuNSxb2KlY+w7fX3rd063toHDTAzSj+H/H0+lYulwz3Moislx2yOD+n9KzvF3xX8C/DCIwXbi+1NvuWsJzhj/fPRRxVRRV7ntNlp91eRm61F1hgUZOTtVawtT+JGiaQDYeF4hf3J+Uyn/VqT6dya+GNb+M3j74i339n3rx2ttG2PItwwT2yxALH6ce9e3eGLXyLFcofN24wf6nsPYU9gP/1fof9kb9uf4LeBf2QYLjxVctDrujNcIdJAImuJHkYoIiRjaejFsbMHI6Zf8As+/BTxt+1l4/X9qT9pSPdpW4NoukOCIpI0OYyUPS3Q8qDzK3zNkdfkv/AIJ4/s0ah+0xZWv7Q3xmjik8PCZvstqgwuoSQnYC3cwJtwSeZmBz8uc/vtp3iPQrm+k0LT50M9oMNCo27QuFIXgAheAdudp4ODXzeyPfbIviJ4C8I/FLwnceCPHFmLvTrkdOjxOPuyRt/A69iPocgkV+dehfEbxr+wf4ot/hz8W5ZtZ+Hd+7DS9VRCz2h67CvoM/PFnK/eTK5FfpHrviHR/DejXXiDxBdRWNhYxNPcXEzBI4o0GWZieAAK/mw/bP/bF1n9pvxTH4a8DxvD4X0mZjYRSAo88pBQ3Uw6jKkiOP+FSc/MxxhUqQpwc6jtFFU6cqk1GCu2W/26f269Y+Nutnwv4KElv4cs5M2ds/ytcOOPtE2O/9xP4R7kmvz00L4e614kvTqniKR087qf429h/dH616Zofg/S/D+dW16Xz7k/MXbr9AO3+ea2W1q8v/AN1pqeTE3AYj5iPb/P4V8DmWZzxU9NILZfq/M+uwWCjh495dWa2jWPh7wZaC10+FFfsqD5ifUnrn3/WpbibUtVI+0Psj/uA449z/AErPjtrTTI/tepybc8kE5Ymse78UXV0fL0hPIjHG89fw9K8u3c7W7Grd38WjOEt0Blx95v4c+i/41iW5ur+VmvHIG7IHTmqscK2ymaY5dhnLck/Qf41sWlqyqZp3EWevrRZCu2bdgoUiCIYOeT3zXp2hrp+nRfb9VmWCFerP1PsB3NeNz+K9O0eApYr58q/xN0B9f/1VzZ1q/wBQv/td07Mw6lvT2HRR+pockhpHp3jv4q6pdwnR/CObKBxgyf8ALZx7dxXz5p+i6tPqryW8WXYHLSgso7/Oe59s16Np9rNdXTG0Uh24Z++Pr2H5n6V6LZ22k+HoFudVcBs/LHjv7L1J9z+lRzGyiM8IeCI7fZfXKguFUGRjkcDnaD/WvQrrxNYaQo0rSYzLMR25wfUn/P0rift2ueJG2RB7S3PRV/1jD3PRRj/9ddh4b0C1iJKAY/MZPv8AxH9KhS1Lt3P/1v0M/YPkRP2ZNBhiARY3uVCqMAAStwAOwr6budO8L6Fe3PjW/dbUQRySzTSSlII12jzJGBIRTtQbnwOBya+Lf+CevizRdf8A2VNH1vS7lJbQT3hMmcBQshJ3Z+7t75xivy7/AG6/27G+OWpy/CP4WXTL4OgfE9wmQ2qyIeG7H7MrfcU48w4Y8bRXy9ScYRc5uyW59BGEpT5YrUs/tq/tm6r+0x4gPw3+G9xJa+CdPmDM/KNqMiHiVxwfKB5ijPX77c4C/GVlc2eip9h0SLz5z94noD/tH/J9hXJaTZXUkGxT5MA5YZxnPdm9/QV1j3WmeHoFkuPk4+Vf4mHsP4R7n8q+DzTMpYufLHSC2/zZ9XgcFHDxu/iZaj0i6uZDqGtThtvJzwoqrdeJY7RzbaYuSRw7Dt7f5xXE6h4kvNamG/5YgcqmcLj1Pc/X8qtLAwQGPDyPzk9B/n0ryuXsdzkW5LyS4k8+/kLsx4X/AB/wFdFYxXVwyxW6gMe55Ix6Cm6Z4et7JTqevzCJj1Zu/wBBUepeNba3t2svDcflL/FPJyT9BSsuormlcPYaJGHuGM0zcjJrk7vUbvUZwJD8vO1Rwo/Dv+Ncvda3AP3s7FpHOSzHLE+w7Utm+q6uTFZDyo8/Mx6/WomWkb+baDDTPlj0ReSPqRnFdBpukXeptv2iK3Xl3Y4RQPU1mWkFhpOQF+0XAwCO+TnAJ6L9OvtViJNV8RShdTcC2j5ESfLEvufU/Xn0rNstRPQI9QtwgsfCyiYr/wAvLjEQP+yv8X1P610mj+H0WcXWpO1xeMOWbl8fyQU3RbbMSiyG1EH+sbjgf3R2+tdbamytrc3KnbErANM3OWPOAP4iR0qGzdGotg2xbNBktjKJk/p1P48fSuziOn6DBtuj5twekYP3Sf7xH8q8/ttbvriUw6eGgSTv/wAtZB65/hH0P49qll1PS9FJF0RLP2jU5xn1qLiP/9k=" - return Group { - UserProfile() - .environmentObject(chatModel1) - UserProfile() - .environmentObject(chatModel2) - } - } -} diff --git a/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift b/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift index 160130bccc..7cd86ef1ef 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfilesView.swift @@ -9,7 +9,6 @@ import SimpleXChat struct UserProfilesView: View { @EnvironmentObject private var m: ChatModel @EnvironmentObject private var theme: AppTheme - @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 @@ -22,6 +21,7 @@ struct UserProfilesView: View { @State private var profileHidden = false @State private var profileAction: UserProfileAction? @State private var actionPassword = "" + @State private var navigateToProfileCreate = false var trimmedSearchTextOrPassword: String { searchTextOrPassword.trimmingCharacters(in: .whitespaces)} @@ -56,17 +56,6 @@ struct UserProfilesView: View { } var body: some View { - if authorized { - userProfilesView() - } else { - Button(action: runAuth) { Label("Unlock", systemImage: "lock") } - .onAppear(perform: runAuth) - } - } - - private func runAuth() { authorize(NSLocalizedString("Open user profiles", comment: "authentication reason"), $authorized) } - - private func userProfilesView() -> some View { List { if profileHidden { Button { @@ -78,12 +67,14 @@ struct UserProfilesView: View { Section { let users = filteredUsers() let v = ForEach(users) { u in - userView(u.user) + userView(u) } if #available(iOS 16, *) { v.onDelete { indexSet in if let i = indexSet.first { - confirmDeleteUser(users[i].user) + withAuth { + confirmDeleteUser(users[i].user) + } } } } else { @@ -91,13 +82,22 @@ struct UserProfilesView: View { } if trimmedSearchTextOrPassword == "" { - NavigationLink { - CreateProfile() - } label: { + NavigationLink( + destination: CreateProfile(), + isActive: $navigateToProfileCreate + ) { Label("Add profile", systemImage: "plus") + .frame(maxWidth: .infinity, alignment: .leading) + .frame(height: 38) + .padding(.leading, 16).padding(.vertical, 8).padding(.trailing, 32) + .contentShape(Rectangle()) + .onTapGesture { + withAuth { + self.navigateToProfileCreate = true + } + } + .padding(.leading, -16).padding(.vertical, -8).padding(.trailing, -32) } - .frame(height: 44) - .padding(.vertical, 4) } } footer: { Text("Tap to activate profile.") @@ -191,7 +191,25 @@ struct UserProfilesView: View { private var visibleUsersCount: Int { m.users.filter({ u in !u.user.hidden }).count } - + + private func withAuth(_ action: @escaping () -> Void) { + if authorized { + action() + } else { + authenticate( + reason: NSLocalizedString("Change chat profiles", comment: "authentication reason") + ) { laResult in + switch laResult { + case .success, .unavailable: + authorized = true + AppSheetState.shared.scenePhaseActive = true + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: action) + case .failed: authorized = false + } + } + } + } + private func correctPassword(_ user: User, _ pwd: String) -> Bool { if let ph = user.viewPwdHash { return pwd != "" && chatPasswordHash(pwd, ph.salt) == ph.hash @@ -215,8 +233,10 @@ struct UserProfilesView: View { passwordField settingsRow("trash", color: theme.colors.secondary) { Button("Delete chat profile", role: .destructive) { - profileAction = nil - Task { await removeUser(user, delSMPQueues, viewPwd: actionPassword) } + withAuth { + profileAction = nil + Task { await removeUser(user, delSMPQueues, viewPwd: actionPassword) } + } } .disabled(!actionEnabled(user)) } @@ -233,8 +253,10 @@ struct UserProfilesView: View { passwordField settingsRow("lock.open", color: theme.colors.secondary) { Button("Unhide chat profile") { - profileAction = nil - setUserPrivacy(user) { try await apiUnhideUser(user.userId, viewPwd: actionPassword) } + withAuth{ + profileAction = nil + setUserPrivacy(user) { try await apiUnhideUser(user.userId, viewPwd: actionPassword) } + } } .disabled(!actionEnabled(user)) } @@ -257,11 +279,13 @@ struct UserProfilesView: View { private func deleteModeButton(_ title: LocalizedStringKey, _ delSMPQueues: Bool) -> some View { Button(title, role: .destructive) { - if let user = userToDelete { - if passwordEntryRequired(user) { - profileAction = .deleteUser(user: user, delSMPQueues: delSMPQueues) - } else { - alert = .deleteUser(user: user, delSMPQueues: delSMPQueues) + withAuth { + if let user = userToDelete { + if passwordEntryRequired(user) { + profileAction = .deleteUser(user: user, delSMPQueues: delSMPQueues) + } else { + alert = .deleteUser(user: user, delSMPQueues: delSMPQueues) + } } } } @@ -285,7 +309,7 @@ struct UserProfilesView: View { await MainActor.run { onboardingStageDefault.set(.step1_SimpleXInfo) m.onboardingStage = .step1_SimpleXInfo - showSettings = false + dismissAllSheets() } } } else { @@ -303,30 +327,38 @@ struct UserProfilesView: View { } } - @ViewBuilder private func userView(_ user: User) -> some View { + @ViewBuilder private func userView(_ userInfo: UserInfo) -> some View { + let user = userInfo.user let v = Button { Task { do { try await changeActiveUserAsync_(user.userId, viewPwd: userViewPassword(user)) + dismissAllSheets() } catch { await MainActor.run { alert = .activateUserError(error: responseError(error)) } } } } label: { HStack { - ProfileImage(imageStr: user.image, size: 44) - .padding(.vertical, 4) + ProfileImage(imageStr: user.image, size: 38) .padding(.trailing, 12) Text(user.chatViewName) Spacer() if user.activeUser { Image(systemName: "checkmark").foregroundColor(theme.colors.onBackground) - } else if user.hidden { - Image(systemName: "lock").foregroundColor(theme.colors.secondary) - } else if !user.showNtfs { - Image(systemName: "speaker.slash").foregroundColor(theme.colors.secondary) } else { - Image(systemName: "checkmark").foregroundColor(.clear) + if userInfo.unreadCount > 0 { + UnreadBadge(userInfo: userInfo) + } + if user.hidden { + Image(systemName: "lock").foregroundColor(theme.colors.secondary) + } else if userInfo.unreadCount == 0 { + if !user.showNtfs { + Image(systemName: "speaker.slash").foregroundColor(theme.colors.secondary) + } else { + Image(systemName: "checkmark").foregroundColor(.clear) + } + } } } } @@ -334,30 +366,38 @@ struct UserProfilesView: View { .swipeActions(edge: .leading, allowsFullSwipe: true) { if user.hidden { Button("Unhide") { - if passwordEntryRequired(user) { - profileAction = .unhideUser(user: user) - } else { - setUserPrivacy(user) { try await apiUnhideUser(user.userId, viewPwd: trimmedSearchTextOrPassword) } + withAuth { + if passwordEntryRequired(user) { + profileAction = .unhideUser(user: user) + } else { + setUserPrivacy(user) { try await apiUnhideUser(user.userId, viewPwd: trimmedSearchTextOrPassword) } + } } } .tint(.green) } else { if visibleUsersCount > 1 { Button("Hide") { - selectedUser = user + withAuth { + selectedUser = user + } } .tint(.gray) } Group { if user.showNtfs { Button("Mute") { - setUserPrivacy(user, successAlert: showMuteProfileAlert ? .muteProfileAlert : nil) { - try await apiMuteUser(user.userId) + withAuth { + setUserPrivacy(user, successAlert: showMuteProfileAlert ? .muteProfileAlert : nil) { + try await apiMuteUser(user.userId) + } } } } else { Button("Unmute") { - setUserPrivacy(user) { try await apiUnmuteUser(user.userId) } + withAuth { + setUserPrivacy(user) { try await apiUnmuteUser(user.userId) } + } } } } @@ -369,7 +409,9 @@ struct UserProfilesView: View { } else { v.swipeActions(edge: .trailing, allowsFullSwipe: true) { Button("Delete", role: .destructive) { - confirmDeleteUser(user) + withAuth { + confirmDeleteUser(user) + } } } } @@ -406,8 +448,15 @@ public func chatPasswordHash(_ pwd: String, _ salt: String) -> String { return hash } +public func correctPassword(_ user: User, _ pwd: String) -> Bool { + if let ph = user.viewPwdHash { + return pwd != "" && chatPasswordHash(pwd, ph.salt) == ph.hash + } + return false +} + struct UserProfilesView_Previews: PreviewProvider { static var previews: some View { - UserProfilesView(showSettings: Binding.constant(true)) + UserProfilesView() } } diff --git a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff index 40481d81f1..ef91bb30fd 100644 --- a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff +++ b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff @@ -187,23 +187,18 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - ** إضافة جهة اتصال جديدة **: لإنشاء رمز QR لمرة واحدة أو رابط جهة الاتصال الخاصة بكم. - No comment provided by engineer. - **Create link / QR code** for your contact to use. ** أنشئ رابطًا / رمز QR ** لتستخدمه جهة الاتصال الخاصة بك. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. ** المزيد من الخصوصية **: تحققوا من الرسائل الجديدة كل 20 دقيقة. تتم مشاركة رمز الجهاز مع خادم SimpleX Chat ، ولكن ليس عدد جهات الاتصال أو الرسائل لديكم. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. ** الأكثر خصوصية **: لا تستخدم خادم إشعارات SimpleX Chat ، وتحقق من الرسائل بشكل دوري في الخلفية (يعتمد على عدد مرات استخدامكم للتطبيق). No comment provided by engineer. @@ -217,8 +212,8 @@ ** يرجى ملاحظة **: لن تتمكنوا من استعادة أو تغيير عبارة المرور إذا فقدتموها. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. ** موصى به **: يتم إرسال رمز الجهاز والإشعارات إلى خادم إشعارات SimpleX Chat ، ولكن ليس محتوى الرسالة أو حجمها أو مصدرها. No comment provided by engineer. @@ -1048,8 +1043,8 @@ Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1064,8 +1059,8 @@ Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1428,16 +1423,16 @@ Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1528,8 +1523,8 @@ Image will be received when your contact is online, please wait or check later! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1625,8 +1620,8 @@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -1926,8 +1921,8 @@ We will be adding server redundancy to prevent lost messages. Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -1978,8 +1973,8 @@ We will be adding server redundancy to prevent lost messages. Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2010,8 +2005,8 @@ We will be adding server redundancy to prevent lost messages. Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -2590,8 +2585,8 @@ We will be adding server redundancy to prevent lost messages. Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -2622,8 +2617,8 @@ We will be adding server redundancy to prevent lost messages. The microphone does not work when the app is in the background. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -2686,8 +2681,8 @@ We will be adding server redundancy to prevent lost messages. To prevent the call interruption, enable Do Not Disturb mode. 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -2860,8 +2855,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -2972,10 +2967,6 @@ To connect, please ask your contact to create another connection link and check You can use markdown to format messages: No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. @@ -3752,8 +3743,8 @@ SimpleX servers cannot see your profile. %u messages skipped. %u تم تخطي الرسائل. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **إضافة جهة اتصال**: لإنشاء رابط دعوة جديد، أو الاتصال عبر الرابط الذي تلقيتوهم. 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 419f0ae864..4aa1f2213f 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,14 @@ %@ е потвърдено No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded %@ качено @@ -137,6 +130,10 @@ %@ иска да се свърже! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ и %lld членове @@ -157,11 +154,31 @@ %d дни time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d часа time interval + + %d messages not forwarded + alert title + %d min %d мин. @@ -322,14 +339,9 @@ ) 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 or link for your contact. - **Добави нов контакт**: за да създадете своя еднократен QR код или линк за вашия контакт. + + **Create 1-time link**: to create and share a new invitation link. + **Добави контакт**: за създаване на нов линк. No comment provided by engineer. @@ -337,13 +349,13 @@ **Създай група**: за създаване на нова група. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **По поверително**: проверявайте новите съобщения на всеки 20 минути. Токенът на устройството се споделя със сървъра за чат SimpleX, но не и колко контакти или съобщения имате. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението). No comment provided by engineer. @@ -357,11 +369,15 @@ **Моля, обърнете внимание**: НЯМА да можете да възстановите или промените паролата, ако я загубите. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е. No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **Внимание**: Незабавните push известия изискват парола, запазена в Keychain. @@ -468,6 +484,14 @@ 1 седмица time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 минути @@ -537,19 +561,13 @@ Откажи смяна на адрес? No comment provided by engineer. - - About SimpleX - За SimpleX - No comment provided by engineer. - About SimpleX Chat За SimpleX Chat No comment provided by engineer. - - About SimpleX address - Повече за SimpleX адреса + + About operators No comment provided by engineer. @@ -563,6 +581,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Приемане на заявка за връзка? @@ -579,6 +601,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged No comment provided by engineer. @@ -596,14 +622,8 @@ Добавете адрес към вашия профил, така че вашите контакти да могат да го споделят с други хора. Актуализацията на профила ще бъде изпратена до вашите контакти. No comment provided by engineer. - - Add contact - Добави контакт - No comment provided by engineer. - - - Add preset servers - Добави предварително зададени сървъри + + Add friends No comment provided by engineer. @@ -621,6 +641,10 @@ Добави сървъри чрез сканиране на QR кодове. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Добави към друго устройство @@ -631,6 +655,18 @@ Добави съобщение при посрещане No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent No comment provided by engineer. @@ -653,6 +689,14 @@ Промяната на адреса ще бъде прекъсната. Ще се използва старият адрес за получаване. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. Администраторите могат да блокират член за всички. @@ -687,8 +731,8 @@ Всички данни се изтриват при въвеждане. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. No comment provided by engineer. @@ -696,6 +740,10 @@ Всички членове на групата ще останат свързани. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Всички съобщения ще бъдат изтрити - това не може да бъде отменено! @@ -713,7 +761,7 @@ All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -871,6 +919,11 @@ Отговор на повикване No comment provided by engineer. + + Anybody can host servers. + Протокол и код с отворен код – всеки може да оперира собствени сървъри. + No comment provided by engineer. + App build: %@ Компилация на приложението: %@ @@ -901,6 +954,10 @@ Кода за достъп до приложение се заменя с код за самоунищожение. No comment provided by engineer. + + App session + No comment provided by engineer. + App version Версия на приложението @@ -1003,6 +1060,10 @@ Автоматично приемане на изображения No comment provided by engineer. + + Auto-accept settings + alert title + Back Назад @@ -1027,11 +1088,19 @@ Лош хеш на съобщението No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups По-добри групи No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages По-добри съобщения @@ -1041,6 +1110,18 @@ Better networking No comment provided by engineer. + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience + No comment provided by engineer. + Black No comment provided by engineer. @@ -1118,6 +1199,14 @@ Български, финландски, тайландски и украински - благодарение на потребителите и [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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) (БЕТА). @@ -1167,7 +1256,8 @@ Cancel Отказ - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1186,7 +1276,7 @@ Cannot receive file Файлът не може да бъде получен - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1202,6 +1292,10 @@ Промени No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Промяна на паролата на базата данни? @@ -1248,9 +1342,16 @@ authentication reason set passcode view - - Chat archive - Архив на чата + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1310,19 +1411,44 @@ Чат настройки No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + Потребителски профил + No comment provided by engineer. + Chat theme No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Чатове No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Проверете адреса на сървъра и опитайте отново. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1403,15 +1529,47 @@ Completed No comment provided by engineer. + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers Конфигурирай ICE сървъри No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm Потвърди @@ -1592,6 +1750,10 @@ This is your own one-time link! Заявката за връзка е изпратена! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated Връзката е прекратена @@ -1685,6 +1847,10 @@ This is your own one-time link! Версия на ядрото: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? Поправи име на %@? @@ -1695,6 +1861,10 @@ This is your own one-time link! Създай No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address Създай SimpleX адрес @@ -1705,11 +1875,6 @@ This is your own one-time link! Създай група с автоматично генериран профилл. No comment provided by engineer. - - Create an address to let people connect with you. - Създайте адрес, за да позволите на хората да се свързват с вас. - No comment provided by engineer. - Create file Създай файл @@ -1769,11 +1934,6 @@ This is your own one-time link! Създаден на: %@ copied message info - - Created on %@ - Създаден на %@ - No comment provided by engineer. - Creating archive link Създаване на архивен линк @@ -1789,6 +1949,10 @@ This is your own one-time link! Текущ kод за достъп No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Текуща парола… @@ -1808,6 +1972,10 @@ This is your own one-time link! Персонализирано време No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme No comment provided by engineer. @@ -1936,7 +2104,8 @@ This is your own one-time link! Delete Изтрий - chat item action + alert action + chat item action swipe action @@ -1973,14 +2142,8 @@ This is your own one-time link! Изтрий и уведоми контакт No comment provided by engineer. - - Delete archive - Изтрий архив - No comment provided by engineer. - - - Delete chat archive? - Изтриване на архива на чата? + + Delete chat No comment provided by engineer. @@ -1993,6 +2156,10 @@ This is your own one-time link! Изтриване на чат профила? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Изтрий връзката @@ -2097,6 +2264,10 @@ This is your own one-time link! Изтрий старата база данни? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? Изтрий предстоящата връзка? @@ -2143,6 +2314,10 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Доставка @@ -2237,8 +2412,12 @@ This is your own one-time link! Лични съобщения chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Личните съобщения между членовете са забранени в тази група. No comment provided by engineer. @@ -2276,8 +2455,8 @@ This is your own one-time link! Изчезващите съобщения са забранени в този чат. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Изчезващите съобщения са забранени в тази група. No comment provided by engineer. @@ -2334,6 +2513,10 @@ This is your own one-time link! Не изпращай история на нови членове. No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address Не създавай адрес @@ -2357,7 +2540,8 @@ This is your own one-time link! Download Изтегли - chat item action + alert button + chat item action Download errors @@ -2373,6 +2557,10 @@ This is your own one-time link! Свали файл server test step + + Download files + alert action + Downloaded No comment provided by engineer. @@ -2401,6 +2589,10 @@ This is your own one-time link! Продължителност No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Редактирай @@ -2421,6 +2613,10 @@ This is your own one-time link! Активиране (запазване на промените) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Активирай SimpleX заключване @@ -2625,26 +2821,33 @@ This is your own one-time link! Грешка при отказване на промяна на адреса No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request Грешка при приемане на заявка за контакт No comment provided by engineer. - - Error accessing database file - Грешка при достъпа до файла с базата данни - No comment provided by engineer. - Error adding member(s) Грешка при добавяне на член(ове) No comment provided by engineer. + + Error adding server + alert title + Error changing address Грешка при промяна на адреса No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role Грешка при промяна на ролята @@ -2655,6 +2858,10 @@ This is your own one-time link! Грешка при промяна на настройката No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. No comment provided by engineer. @@ -2768,9 +2975,12 @@ This is your own one-time link! Грешка при присъединяване към група No comment provided by engineer. - - Error loading %@ servers - Грешка при зареждане на %@ сървъри + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. @@ -2781,7 +2991,7 @@ This is your own one-time link! Error receiving file Грешка при получаване на файл - No comment provided by engineer. + alert title Error reconnecting server @@ -2800,11 +3010,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - Грешка при запазване на %@ сървъра - No comment provided by engineer. - Error saving ICE servers Грешка при запазване на ICE сървърите @@ -2825,6 +3030,10 @@ This is your own one-time link! Грешка при запазване на парола в Кeychain No comment provided by engineer. + + Error saving servers + alert title + Error saving settings Грешка при запазване на настройките @@ -2870,10 +3079,14 @@ This is your own one-time link! Грешка при спиране на чата No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! Грешка при смяна на профил! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2890,6 +3103,10 @@ This is your own one-time link! Грешка при актуализиране на съобщението No comment provided by engineer. + + Error updating server + alert title + Error updating settings Грешка при актуализиране на настройките @@ -2918,8 +3135,7 @@ This is your own one-time link! Error: %@ Грешка: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2935,6 +3151,10 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. Дори когато е деактивиран в разговора. @@ -3003,6 +3223,11 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. file error text @@ -3053,8 +3278,8 @@ This is your own one-time link! Файлове и медия chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Файловете и медията са забранени в тази група. No comment provided by engineer. @@ -3123,21 +3348,53 @@ This is your own one-time link! Поправката не се поддържа от члена на групата No comment provided by engineer. + + For chat profile %@: + servers error + For console За конзолата No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward Препрати chat item action + + Forward %d message(s)? + alert title + Forward and save messages Препращане и запазване на съобщения No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded Препратено @@ -3148,6 +3405,10 @@ This is your own one-time link! Препратено от No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. No comment provided by engineer. @@ -3190,11 +3451,6 @@ Error: %2$@ Пълно име (незадължително) No comment provided by engineer. - - Full name: - Пълно име: - No comment provided by engineer. - Fully decentralized – visible only to members. Напълно децентрализирана – видима е само за членовете. @@ -3278,41 +3534,6 @@ Error: %2$@ Групови линкове No comment provided by engineer. - - Group members can add message reactions. - Членовете на групата могат да добавят реакции към съобщенията. - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа) - No comment provided by engineer. - - - Group members can send SimpleX links. - Членовете на групата могат да изпращат SimpleX линкове. - No comment provided by engineer. - - - Group members can send direct messages. - Членовете на групата могат да изпращат лични съобщения. - No comment provided by engineer. - - - Group members can send disappearing messages. - Членовете на групата могат да изпращат изчезващи съобщения. - No comment provided by engineer. - - - Group members can send files and media. - Членовете на групата могат да изпращат файлове и медия. - No comment provided by engineer. - - - Group members can send voice messages. - Членовете на групата могат да изпращат гласови съобщения. - No comment provided by engineer. - Group message: Групово съобщение: @@ -3408,9 +3629,12 @@ Error: %2$@ Как работи SimpleX No comment provided by engineer. - - How it works - Как работи + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3438,6 +3662,10 @@ Error: %2$@ ICE сървъри (по един на ред) No comment provided by engineer. + + IP address + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. Ако не можете да се срещнете лично, покажете QR код във видеоразговора или споделете линка. @@ -3478,8 +3706,8 @@ Error: %2$@ Веднага No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Защитен от спам и злоупотреби No comment provided by engineer. @@ -3512,6 +3740,11 @@ Error: %2$@ Импортиране на архив No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery Подобрена доставка на съобщения @@ -3612,6 +3845,11 @@ Error: %2$@ Инсталирайте [SimpleX Chat за терминал](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Мигновено + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3619,11 +3857,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Мигновено - No comment provided by engineer. - Interface Интерфейс @@ -3671,7 +3904,7 @@ Error: %2$@ Invalid server address! Невалиден адрес на сървъра! - No comment provided by engineer. + alert title Invalid status @@ -3693,6 +3926,10 @@ Error: %2$@ Покани членове No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Покани в групата @@ -3708,8 +3945,8 @@ Error: %2$@ Необратимото изтриване на съобщения е забранено в този чат. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Необратимото изтриване на съобщения е забранено в тази група. No comment provided by engineer. @@ -3798,7 +4035,7 @@ This is your link for group %@! Keep Запази - No comment provided by engineer. + alert action Keep conversation @@ -3812,7 +4049,7 @@ This is your link for group %@! Keep unused invitation? Запази неизползваната покана за връзка? - No comment provided by engineer. + alert title Keep your connections @@ -3849,6 +4086,14 @@ This is your link for group %@! Напусни swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Напусни групата @@ -3899,11 +4144,6 @@ This is your link for group %@! Съобщения на живо No comment provided by engineer. - - Local - Локално - No comment provided by engineer. - Local name Локално име @@ -3924,11 +4164,6 @@ This is your link for group %@! Режим на заключване No comment provided by engineer. - - Make a private connection - Добави поверителна връзка - No comment provided by engineer. - Make one message disappear Накарайте едно съобщение да изчезне @@ -3939,21 +4174,11 @@ This is your link for group %@! Направи профила поверителен! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Уверете се, че %@ сървърните адреси са в правилен формат, разделени на редове и не се дублират (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Уверете се, че адресите на WebRTC ICE сървъра са в правилен формат, разделени на редове и не са дублирани. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Много хора попитаха: *ако SimpleX няма потребителски идентификатори, как може да доставя съобщения?* - No comment provided by engineer. - Mark deleted for everyone Маркирай като изтрито за всички @@ -3996,6 +4221,10 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Ролята на члена ще бъде променена на "%@". Всички членове на групата ще бъдат уведомени. @@ -4006,11 +4235,50 @@ This is your link for group %@! Ролята на члена ще бъде променена на "%@". Членът ще получи нова покана. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Членът ще бъде премахнат от групата - това не може да бъде отменено! No comment provided by engineer. + + Members can add message reactions. + Членовете на групата могат да добавят реакции към съобщенията. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа) + No comment provided by engineer. + + + Members can send SimpleX links. + Членовете на групата могат да изпращат SimpleX линкове. + No comment provided by engineer. + + + Members can send direct messages. + Членовете на групата могат да изпращат лични съобщения. + No comment provided by engineer. + + + Members can send disappearing messages. + Членовете на групата могат да изпращат изчезващи съобщения. + No comment provided by engineer. + + + Members can send files and media. + Членовете на групата могат да изпращат файлове и медия. + No comment provided by engineer. + + + Members can send voice messages. + Членовете на групата могат да изпращат гласови съобщения. + No comment provided by engineer. + Menus No comment provided by engineer. @@ -4056,8 +4324,8 @@ This is your link for group %@! Реакциите на съобщения са забранени в този чат. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Реакциите на съобщения са забранени в тази група. No comment provided by engineer. @@ -4069,6 +4337,10 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + No comment provided by engineer. + Message source remains private. Източникът на съобщението остава скрит. @@ -4115,6 +4387,10 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Съобщенията, файловете и разговорите са защитени чрез **криптиране от край до край** с перфектна секретност при препращане, правдоподобно опровержение и възстановяване при взлом. @@ -4180,9 +4456,9 @@ This is your link for group %@! Миграцията е завършена No comment provided by engineer. - - Migrations: %@ - Миграции: %@ + + Migrations: + Миграции: No comment provided by engineer. @@ -4210,6 +4486,10 @@ This is your link for group %@! По-надеждна мрежова връзка. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Най-вероятно тази връзка е изтрита. @@ -4245,6 +4525,10 @@ This is your link for group %@! Мрежова връзка No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. snd error text @@ -4254,6 +4538,10 @@ This is your link for group %@! Управление на мрежата No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Мрежови настройки @@ -4269,6 +4557,14 @@ This is your link for group %@! Нов kод за достъп No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat Нов чат @@ -4288,11 +4584,6 @@ This is your link for group %@! Нов контакт: notification - - New database archive - Нов архив на база данни - No comment provided by engineer. - New desktop app! Ново настолно приложение! @@ -4303,6 +4594,10 @@ This is your link for group %@! Ново име No comment provided by engineer. + + New events + notification + New in %@ Ново в %@ @@ -4327,6 +4622,10 @@ This is your link for group %@! Нова парола… No comment provided by engineer. + + New server + No comment provided by engineer. + No Не @@ -4380,21 +4679,63 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection Няма мрежова връзка No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message Няма разрешение за запис на гласово съобщение No comment provided by engineer. + + No push server + Локално + No comment provided by engineer. + No received or sent files Няма получени или изпратени файлове No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Първата платформа без никакви потребителски идентификатори – поверителна по дизайн. + No comment provided by engineer. + Not compatible! Несъвместим! @@ -4404,6 +4745,10 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + alert title + Notifications Известия @@ -4414,6 +4759,10 @@ This is your link for group %@! Известията са деактивирани! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4436,18 +4785,13 @@ This is your link for group %@! Ok Ок - No comment provided by engineer. + alert button Old database Стара база данни No comment provided by engineer. - - Old database archive - Стар архив на база данни - No comment provided by engineer. - One-time invitation link Линк за еднократна покана @@ -4472,8 +4816,12 @@ Requires compatible VPN. Няма се използват Onion хостове. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Само потребителските устройства съхраняват потребителски профили, контакти, групи и съобщения, изпратени с **двуслойно криптиране от край до край**. No comment provided by engineer. @@ -4556,6 +4904,10 @@ Requires compatible VPN. Отвори настройки No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Отвори чат @@ -4566,6 +4918,10 @@ Requires compatible VPN. Отвори конзолата authentication reason + + Open conditions + No comment provided by engineer. + Open group Отвори група @@ -4576,25 +4932,23 @@ Requires compatible VPN. Отвори миграцията към друго устройство authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - Отвори потребителските профили - authentication reason - - - Open-source protocol and code – anybody can run the servers. - Протокол и код с отворен код – всеки може да оперира собствени сървъри. - No comment provided by engineer. - Opening app… Приложението се отваря… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link Или постави архивен линк @@ -4615,14 +4969,19 @@ Requires compatible VPN. Или покажи този код No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other Други No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4659,6 +5018,10 @@ Requires compatible VPN. Кодът за достъп е зададен! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show Парола за показване @@ -4693,13 +5056,8 @@ Requires compatible VPN. Pending No comment provided by engineer. - - People can connect to you only via the links you share. - Хората могат да се свържат с вас само чрез ликовете, които споделяте. - No comment provided by engineer. - - - Periodically + + Periodic Периодично No comment provided by engineer. @@ -4803,6 +5161,10 @@ Error: %@ Полски интерфейс No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Въжможно е пръстовият отпечатък на сертификата в адреса на сървъра да е неправилен @@ -4813,16 +5175,15 @@ Error: %@ Запазете последната чернова на съобщението с прикачени файлове. No comment provided by engineer. - - Preset server - Предварително зададен сървър - No comment provided by engineer. - Preset server address Предварително зададен адрес на сървъра No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview Визуализация @@ -4837,6 +5198,10 @@ Error: %@ Поверителност и сигурност No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Поверителността преосмислена @@ -4883,16 +5248,6 @@ Error: %@ Профилни изображения No comment provided by engineer. - - Profile name - Име на профила - No comment provided by engineer. - - - Profile name: - Име на профила: - No comment provided by engineer. - Profile password Профилна парола @@ -4905,7 +5260,7 @@ Error: %@ Profile update will be sent to your contacts. Актуализацията на профила ще бъде изпратена до вашите контакти. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4989,6 +5344,10 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + No comment provided by engineer. + Push notifications Push известия @@ -5028,26 +5387,21 @@ Enable in *Network & servers* settings. Прочетете още 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Прочетете повече в нашето хранилище в GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Прочетете повече в нашето [GitHub хранилище](https://github.com/simplex-chat/simplex-chat#readme). @@ -5200,6 +5554,10 @@ Enable in *Network & servers* settings. Премахване No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image No comment provided by engineer. @@ -5344,6 +5702,14 @@ Enable in *Network & servers* settings. Покажи chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke Отзови @@ -5373,6 +5739,10 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + No comment provided by engineer. + Safely receive files No comment provided by engineer. @@ -5385,17 +5755,18 @@ Enable in *Network & servers* settings. Save Запази - chat item action + alert button + chat item action Save (and notify contacts) Запази (и уведоми контактите) - No comment provided by engineer. + alert button Save and notify contact Запази и уведоми контакта - No comment provided by engineer. + alert button Save and notify group members @@ -5411,16 +5782,6 @@ Enable in *Network & servers* settings. Запази и актуализирай профила на групата No comment provided by engineer. - - Save archive - Запази архив - No comment provided by engineer. - - - Save auto-accept settings - Запази настройките за автоматично приемане - No comment provided by engineer. - Save group profile Запази профила на групата @@ -5439,7 +5800,7 @@ Enable in *Network & servers* settings. Save preferences? Запази настройките? - No comment provided by engineer. + alert title Save profile password @@ -5454,18 +5815,17 @@ Enable in *Network & servers* settings. Save servers? Запази сървърите? - No comment provided by engineer. - - - Save settings? - Запази настройките? - No comment provided by engineer. + alert title Save welcome message? Запази съобщението при посрещане? No comment provided by engineer. + + Save your profile? + alert title + Saved Запазено @@ -5486,6 +5846,10 @@ Enable in *Network & servers* settings. Запазено съобщение message info title + + Saving %lld messages + No comment provided by engineer. + Scale No comment provided by engineer. @@ -5562,6 +5926,10 @@ Enable in *Network & servers* settings. Избери chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld No comment provided by engineer. @@ -5646,11 +6014,6 @@ Enable in *Network & servers* settings. Изпращай известия No comment provided by engineer. - - Send notifications: - Изпратени известия: - No comment provided by engineer. - Send questions and ideas Изпращайте въпроси и идеи @@ -5674,7 +6037,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Подателят отмени прехвърлянето на файла. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5766,6 +6129,14 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address No comment provided by engineer. @@ -5778,6 +6149,18 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Сървърът изисква оторизация за създаване на опашки, проверете паролата @@ -5877,6 +6260,10 @@ Enable in *Network & servers* settings. Настройки No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images Променете формата на профилните изображения @@ -5885,22 +6272,35 @@ Enable in *Network & servers* settings. Share Сподели - chat item action + alert action + chat item action Share 1-time link Сподели еднократен линк No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Сподели адрес No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Сподели адреса с контактите? - No comment provided by engineer. + alert title Share from other apps. @@ -5911,6 +6311,10 @@ Enable in *Network & servers* settings. Сподели линк No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link Сподели този еднократен линк за връзка @@ -5976,6 +6380,10 @@ Enable in *Network & servers* settings. SimpleX Адрес No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Сигурността на SimpleX Chat беше одитирана от Trail of Bits. @@ -6006,6 +6414,14 @@ Enable in *Network & servers* settings. SimpleX адрес No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX адрес за контакт @@ -6026,8 +6442,8 @@ Enable in *Network & servers* settings. SimpleX линкове chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. SimpleX линкове са забранени в тази група. No comment provided by engineer. @@ -6041,6 +6457,10 @@ Enable in *Network & servers* settings. Еднократна покана за SimpleX simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Опростен режим инкогнито @@ -6069,6 +6489,10 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: No comment provided by engineer. @@ -6082,6 +6506,11 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Някой @@ -6130,11 +6559,6 @@ Enable in *Network & servers* settings. Спри чата No comment provided by engineer. - - Stop chat to enable database actions - Спрете чата, за да активирате действията с базата данни - 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. Спрете чата, за да експортирате, импортирате или изтриете чат базата данни. Няма да можете да получавате и изпращате съобщения, докато чатът е спрян. @@ -6163,12 +6587,12 @@ Enable in *Network & servers* settings. Stop sharing Спри споделянето - No comment provided by engineer. + alert action Stop sharing address? Спри споделянето на адреса? - No comment provided by engineer. + alert title Stopping chat @@ -6201,6 +6625,14 @@ Enable in *Network & servers* settings. Подкрепете SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System Системен @@ -6235,11 +6667,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture Направи снимка No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Докосни бутона @@ -6297,7 +6737,7 @@ Enable in *Network & servers* settings. Tests failed! Тестовете са неуспешни! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6314,11 +6754,6 @@ Enable in *Network & servers* settings. Благодарение на потребителите – допринесете през Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Първата платформа без никакви потребителски идентификатори – поверителна по дизайн. - No comment provided by engineer. - 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. @@ -6331,6 +6766,10 @@ It can happen because of some bug or when the connection is compromised.Приложението може да ви уведоми, когато получите съобщения или заявки за контакт - моля, отворете настройките, за да активирате. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). No comment provided by engineer. @@ -6345,6 +6784,10 @@ It can happen because of some bug or when the connection is compromised.QR кодът, който сканирахте, не е SimpleX линк за връзка. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Връзката, която приехте, ще бъде отказана! @@ -6365,6 +6808,11 @@ It can happen because of some bug or when the connection is compromised.Криптирането работи и новото споразумение за криптиране не е необходимо. Това може да доведе до грешки при свързване! No comment provided by engineer. + + The future of messaging + Ново поколение поверителни съобщения + No comment provided by engineer. + The hash of the previous message is different. Хешът на предишното съобщение е различен. @@ -6388,11 +6836,6 @@ It can happen because of some bug or when the connection is compromised.The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - Ново поколение поверителни съобщения - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита. @@ -6403,6 +6846,18 @@ It can happen because of some bug or when the connection is compromised.Профилът се споделя само с вашите контакти. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Втората отметка, която пропуснахме! ✅ @@ -6418,15 +6873,27 @@ It can happen because of some bug or when the connection is compromised.Сървърите за нови връзки на текущия ви чат профил **%@**. No comment provided by engineer. + + The servers for new files 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. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Тези настройки са за текущия ви профил **%@**. @@ -6525,9 +6992,8 @@ It can happen because of some bug or when the connection is compromised.За да направите нова връзка 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. - За да се защити поверителността, вместо потребителски идентификатори, използвани от всички други платформи, SimpleX има идентификатори за опашки от съобщения, отделни за всеки от вашите контакти. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6546,6 +7012,23 @@ You will be prompted to complete authentication before this feature is enabled.< Ще бъдете подканени да извършите идентификация, преди тази функция да бъде активирана. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + За да се защити поверителността, вместо потребителски идентификатори, използвани от всички други платформи, SimpleX има идентификатори за опашки от съобщения, отделни за всеки от вашите контакти. + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. За да запишете гласово съобщение, моля, дайте разрешение за използване на микрофон. @@ -6556,11 +7039,19 @@ You will be prompted to complete authentication before this feature is enabled.< За да разкриете своя скрит профил, въведете пълна парола в полето за търсене на страницата **Вашите чат профили**. No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. За поддръжка на незабавни push известия, базата данни за чат трябва да бъде мигрирана. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. За да проверите криптирането от край до край с вашия контакт, сравнете (или сканирайте) кода на вашите устройства. @@ -6647,6 +7138,10 @@ You will be prompted to complete authentication before this feature is enabled.< Отблокирай член? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state Неочаквано състояние на миграция @@ -6694,7 +7189,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6799,11 +7294,19 @@ To connect, please ask your contact to create another connection link and check Архивът се качва No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts Използвай .onion хостове No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? Използвай сървърите на SimpleX Chat? @@ -6819,6 +7322,14 @@ To connect, please ask your contact to create another connection link and check Използвай текущия профил No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Използвай за нови връзки @@ -6857,6 +7368,10 @@ To connect, please ask your contact to create another connection link and check Използвай сървър No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. Използвайте приложението по време на разговора. @@ -6866,15 +7381,14 @@ To connect, please ask your contact to create another connection link and check Use the app with one hand. No comment provided by engineer. - - User profile - Потребителски профил - No comment provided by engineer. - User selection No comment provided by engineer. + + Username + No comment provided by engineer. + Using SimpleX Chat servers. Използват се сървърите на SimpleX Chat. @@ -6945,11 +7459,19 @@ To connect, please ask your contact to create another connection link and check Видео и файлове до 1gb No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Виж кода за сигурност No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history Видима история @@ -6965,8 +7487,8 @@ To connect, please ask your contact to create another connection link and check Гласовите съобщения са забранени в този чат. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Гласовите съобщения са забранени в тази група. No comment provided by engineer. @@ -7058,9 +7580,8 @@ To connect, please ask your contact to create another connection link and check При свързване на аудио и видео разговори. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Когато хората искат да се свържат с вас, можете да ги приемете или отхвърлите. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7104,7 +7625,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7128,11 +7649,6 @@ To connect, please ask your contact to create another connection link and check XFTP server No comment provided by engineer. - - You - Вие - No comment provided by engineer. - You **must not** use the same database on two devices. **Не трябва** да използвате една и съща база данни на две устройства. @@ -7158,6 +7674,10 @@ To connect, please ask your contact to create another connection link and check Вече сте вече свързани с %@. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. Вече се свързвате с %@. @@ -7218,6 +7738,14 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + No comment provided by engineer. + You can create it later Можете да го създадете по-късно @@ -7257,6 +7785,10 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. Можете да зададете визуализация на известията на заключен екран през настройките. @@ -7272,11 +7804,6 @@ Repeat join request? Можете да споделите този адрес с вашите контакти, за да им позволите да се свържат с **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Можете да споделите адреса си като линк или QR код - всеки може да се свърже с вас. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Можете да започнете чат през Настройки на приложението / База данни или като рестартирате приложението @@ -7299,23 +7826,23 @@ Repeat join request? You can view invitation link again in connection details. Можете да видите отново линкът за покана в подробностите за връзката. - No comment provided by engineer. + alert message You can't send messages! Не може да изпращате съобщения! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Вие контролирате през кой сървър(и) **да получавате** съобщенията, вашите контакти – сървърите, които използвате, за да им изпращате съобщения. - No comment provided by engineer. - You could not be verified; please try again. Не можахте да бъдете потвърдени; Моля, опитайте отново. No comment provided by engineer. + + You decide who can connect. + Хората могат да се свържат с вас само чрез ликовете, които споделяте. + No comment provided by engineer. + You have already requested connection via this address! Вече сте заявили връзка през този адрес! @@ -7415,6 +7942,10 @@ Repeat connection request? Все още ще получавате обаждания и известия от заглушени профили, когато са активни. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Ще спрете да получавате съобщения от тази група. Историята на чата ще бъде запазена. @@ -7435,11 +7966,6 @@ Repeat connection request? Използвате инкогнито профил за тази група - за да се предотврати споделянето на основния ви профил, поканите на контакти не са разрешени No comment provided by engineer. - - Your %@ servers - Вашите %@ сървъри - No comment provided by engineer. - Your ICE servers Вашите ICE сървъри @@ -7455,11 +7981,6 @@ Repeat connection request? Вашият SimpleX адрес No comment provided by engineer. - - Your XFTP servers - Вашите XFTP сървъри - No comment provided by engineer. - Your calls Вашите обаждания @@ -7475,11 +7996,19 @@ Repeat connection request? Вашата чат база данни не е криптирана - задайте парола, за да я криптирате. No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles Вашите чат профили No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Вашият контакт изпрати файл, който е по-голям от поддържания в момента максимален размер (%@). @@ -7495,6 +8024,10 @@ Repeat connection request? Вашите контакти ще останат свързани. No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Вашата текуща чат база данни ще бъде ИЗТРИТА и ЗАМЕНЕНА с импортираната. @@ -7525,13 +8058,15 @@ Repeat connection request? Вашият профил **%@** ще бъде споделен. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. -SimpleX сървърите не могат да видят вашия профил. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. Вашият профил, контакти и доставени съобщения се съхраняват на вашето устройство. @@ -7542,16 +8077,15 @@ SimpleX сървърите не могат да видят вашия профи Вашият автоматично генериран профил No comment provided by engineer. - - Your server - Вашият сървър - No comment provided by engineer. - Your server address Вашият адрес на сървъра No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings Вашите настройки @@ -7592,6 +8126,10 @@ SimpleX сървърите не могат да видят вашия профи обаждането прието call status + + accepted invitation + chat list item title + admin админ @@ -7778,7 +8316,7 @@ SimpleX сървърите не могат да видят вашия профи connecting… свързване… - chat list item title + No comment provided by engineer. connection established @@ -7967,6 +8505,10 @@ SimpleX сървърите не могат да видят вашия профи expired No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded препратено @@ -8258,6 +8800,10 @@ SimpleX сървърите не могат да видят вашия профи ви острани rcv group event chat item + + requested to connect + chat list item title + saved запазено @@ -8574,6 +9120,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/bg.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - diff --git a/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff b/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff index b92196b78b..7002f790df 100644 --- a/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff +++ b/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff @@ -193,20 +193,16 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - No comment provided by engineer. - **Create link / QR code** for your contact to use. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. No comment provided by engineer. @@ -217,8 +213,8 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. No comment provided by engineer. @@ -1251,8 +1247,8 @@ Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1271,8 +1267,8 @@ Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1751,24 +1747,24 @@ Group links No comment provided by engineer. - - Group members can add message reactions. + + Members can add message reactions. No comment provided by engineer. Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1899,8 +1895,8 @@ Immediately No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -2020,8 +2016,8 @@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -2207,8 +2203,8 @@ Message reactions are prohibited in this chat. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. No comment provided by engineer. @@ -2239,8 +2235,8 @@ Migration is completed No comment provided by engineer. - - Migrations: %@ + + Migrations: No comment provided by engineer. @@ -2409,8 +2405,8 @@ Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2477,8 +2473,8 @@ Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2537,8 +2533,8 @@ Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -3373,8 +3369,8 @@ Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -3418,8 +3414,8 @@ It can happen because of some bug or when the connection is compromised.The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -3490,8 +3486,8 @@ It can happen because of some bug or when the connection is compromised.To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -3724,8 +3720,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -3876,10 +3872,6 @@ To connect, please ask your contact to create another connection link and check You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. 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 a02203e630..668888c20e 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -126,6 +111,14 @@ %@ je ověřený No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded No comment provided by engineer. @@ -135,6 +128,10 @@ %@ se chce připojit! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members No comment provided by engineer. @@ -154,11 +151,31 @@ %d dní time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d hodin time interval + + %d messages not forwarded + alert title + %d min %d minuty @@ -312,26 +329,21 @@ ) 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 or link for your contact. - **Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt. + + **Create 1-time link**: to create and share a new invitation link. No comment provided by engineer. **Create group**: to create a new group. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Soukromější**: kontrolovat nové zprávy každých 20 minut. Token zařízení je sdílen se serverem SimpleX Chat, ale ne kolik máte kontaktů nebo zpráv. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -344,11 +356,15 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + 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. @@ -450,6 +466,14 @@ 1 týden time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 minut @@ -519,19 +543,13 @@ Přerušit změnu adresy? No comment provided by engineer. - - About SimpleX - O SimpleX - No comment provided by engineer. - About SimpleX Chat O SimpleX chat No comment provided by engineer. - - About SimpleX address - O SimpleX adrese + + About operators No comment provided by engineer. @@ -545,6 +563,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Přijmout kontakt? @@ -561,6 +583,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged No comment provided by engineer. @@ -578,13 +604,8 @@ 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. No comment provided by engineer. - - Add contact - No comment provided by engineer. - - - Add preset servers - Přidejte přednastavené servery + + Add friends No comment provided by engineer. @@ -602,6 +623,10 @@ Přidejte servery skenováním QR kódů. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Přidat do jiného zařízení @@ -612,6 +637,18 @@ Přidat uvítací zprávu No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent No comment provided by engineer. @@ -634,6 +671,14 @@ Změna adresy bude přerušena. Budou použity staré přijímací adresy. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. No comment provided by engineer. @@ -667,8 +712,8 @@ Všechna data se při zadání vymažou. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. No comment provided by engineer. @@ -676,6 +721,10 @@ Všichni členové skupiny zůstanou připojeni. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! No comment provided by engineer. @@ -691,7 +740,7 @@ All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -845,6 +894,11 @@ Přijmout hovor No comment provided by engineer. + + Anybody can host servers. + Servery může provozovat kdokoli. + No comment provided by engineer. + App build: %@ Sestavení aplikace: %@ @@ -874,6 +928,10 @@ Přístupový kód aplikace je nahrazen sebedestrukčním přístupovým heslem. No comment provided by engineer. + + App session + No comment provided by engineer. + App version Verze aplikace @@ -973,6 +1031,10 @@ Automaticky přijímat obrázky No comment provided by engineer. + + Auto-accept settings + alert title + Back Zpět @@ -996,10 +1058,18 @@ Špatný hash zprávy No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages Lepší zprávy @@ -1009,6 +1079,18 @@ Better networking No comment provided by engineer. + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience + No comment provided by engineer. + Black No comment provided by engineer. @@ -1079,6 +1161,14 @@ Bulharský, finský, thajský a ukrajinský - díky uživatelům a [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). Podle chat profilu (výchozí) nebo [podle připojení](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1127,7 +1217,8 @@ Cancel Zrušit - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1145,7 +1236,7 @@ Cannot receive file Nelze přijmout soubor - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1160,6 +1251,10 @@ Změnit No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Změnit přístupovou frázi databáze? @@ -1206,9 +1301,16 @@ authentication reason set passcode view - - Chat archive - Chat se archivuje + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1266,19 +1368,44 @@ Předvolby chatu No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + Profil uživatele + No comment provided by engineer. + Chat theme No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Chaty No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Zkontrolujte adresu serveru a zkuste to znovu. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1357,15 +1484,47 @@ Completed No comment provided by engineer. + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers Konfigurace serverů ICE No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm Potvrdit @@ -1531,6 +1690,10 @@ This is your own one-time link! Požadavek na připojení byl odeslán! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated No comment provided by engineer. @@ -1623,6 +1786,10 @@ This is your own one-time link! Verze jádra: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? No comment provided by engineer. @@ -1632,6 +1799,10 @@ This is your own one-time link! Vytvořit No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address Vytvořit SimpleX adresu @@ -1641,11 +1812,6 @@ This is your own one-time link! Create a group using a random profile. No comment provided by engineer. - - Create an address to let people connect with you. - Vytvořit adresu, aby se s vámi lidé mohli spojit. - No comment provided by engineer. - Create file Vytvořit soubor @@ -1701,11 +1867,6 @@ This is your own one-time link! Created at: %@ copied message info - - Created on %@ - Vytvořeno na %@ - No comment provided by engineer. - Creating archive link No comment provided by engineer. @@ -1719,6 +1880,10 @@ This is your own one-time link! Aktuální heslo No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Aktuální přístupová fráze… @@ -1738,6 +1903,10 @@ This is your own one-time link! Vlastní čas No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme No comment provided by engineer. @@ -1866,7 +2035,8 @@ This is your own one-time link! Delete Smazat - chat item action + alert action + chat item action swipe action @@ -1901,14 +2071,8 @@ This is your own one-time link! Delete and notify contact No comment provided by engineer. - - Delete archive - Smazat archiv - No comment provided by engineer. - - - Delete chat archive? - Smazat archiv chatu? + + Delete chat No comment provided by engineer. @@ -1921,6 +2085,10 @@ This is your own one-time link! Smazat chat profil? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Smazat připojení @@ -2024,6 +2192,10 @@ This is your own one-time link! Smazat starou databázi? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? Smazat čekající připojení? @@ -2070,6 +2242,10 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Doručenka @@ -2161,8 +2337,12 @@ This is your own one-time link! Přímé zprávy chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Přímé zprávy mezi členy jsou v této skupině zakázány. No comment provided by engineer. @@ -2200,8 +2380,8 @@ This is your own one-time link! Mizící zprávy jsou v tomto chatu zakázány. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Mizící zprávy jsou v této skupině zakázány. No comment provided by engineer. @@ -2255,6 +2435,10 @@ This is your own one-time link! Do not send history to new members. No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address Nevytvářet adresu @@ -2277,7 +2461,8 @@ This is your own one-time link! Download - chat item action + alert button + chat item action Download errors @@ -2292,6 +2477,10 @@ This is your own one-time link! Stáhnout soubor server test step + + Download files + alert action + Downloaded No comment provided by engineer. @@ -2318,6 +2507,10 @@ This is your own one-time link! Trvání No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Upravit @@ -2338,6 +2531,10 @@ This is your own one-time link! Povolit (zachovat přepsání) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Zapnutí zámku SimpleX @@ -2532,26 +2729,33 @@ This is your own one-time link! Chyba přerušení změny adresy No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request Chyba při přijímání žádosti o kontakt No comment provided by engineer. - - Error accessing database file - Chyba přístupu k souboru databáze - No comment provided by engineer. - Error adding member(s) Chyba přidávání člena(ů) No comment provided by engineer. + + Error adding server + alert title + Error changing address Chuba změny adresy No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role Chyba při změně role @@ -2562,6 +2766,10 @@ This is your own one-time link! Chyba změny nastavení No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. No comment provided by engineer. @@ -2673,9 +2881,12 @@ This is your own one-time link! Chyba při připojování ke skupině No comment provided by engineer. - - Error loading %@ servers - Chyba načítání %@ serverů + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. @@ -2685,7 +2896,7 @@ This is your own one-time link! Error receiving file Chyba při příjmu souboru - No comment provided by engineer. + alert title Error reconnecting server @@ -2704,11 +2915,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - Chyba při ukládání serverů %@ - No comment provided by engineer. - Error saving ICE servers Chyba při ukládání serverů ICE @@ -2729,6 +2935,10 @@ This is your own one-time link! Při ukládání přístupové fráze do klíčenky došlo k chybě No comment provided by engineer. + + Error saving servers + alert title + Error saving settings when migrating @@ -2772,10 +2982,14 @@ This is your own one-time link! Chyba při zastavení chatu No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! Chyba při přepínání profilu! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2792,6 +3006,10 @@ This is your own one-time link! Chyba aktualizace zprávy No comment provided by engineer. + + Error updating server + alert title + Error updating settings Chyba při aktualizaci nastavení @@ -2818,8 +3036,7 @@ This is your own one-time link! Error: %@ Chyba: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2835,6 +3052,10 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. I při vypnutí v konverzaci. @@ -2900,6 +3121,11 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. file error text @@ -2950,8 +3176,8 @@ This is your own one-time link! Soubory a média chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Soubory a média jsou zakázány v této skupině. No comment provided by engineer. @@ -3017,19 +3243,51 @@ This is your own one-time link! Opravit nepodporované členem skupiny No comment provided by engineer. + + For chat profile %@: + servers error + For console Pro konzoli No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward chat item action + + Forward %d message(s)? + alert title + Forward and save messages No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded No comment provided by engineer. @@ -3038,6 +3296,10 @@ This is your own one-time link! Forwarded from No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. No comment provided by engineer. @@ -3079,11 +3341,6 @@ Error: %2$@ Celé jméno (volitelně) No comment provided by engineer. - - Full name: - Celé jméno: - No comment provided by engineer. - Fully decentralized – visible only to members. No comment provided by engineer. @@ -3164,40 +3421,6 @@ Error: %2$@ Odkazy na skupiny No comment provided by engineer. - - 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. (24 hours) - Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin) - No comment provided by engineer. - - - Group members can send SimpleX links. - No comment provided by engineer. - - - Group members can send direct messages. - Členové skupiny mohou posílat přímé zprávy. - No comment provided by engineer. - - - Group members can send disappearing messages. - Členové skupiny mohou posílat mizící zprávy. - No comment provided by engineer. - - - Group members can send files and media. - Členové skupiny mohou posílat soubory a média. - No comment provided by engineer. - - - Group members can send voice messages. - Členové skupiny mohou posílat hlasové zprávy. - No comment provided by engineer. - Group message: Skupinová zpráva: @@ -3292,9 +3515,12 @@ Error: %2$@ Jak SimpleX funguje No comment provided by engineer. - - How it works - Jak to funguje + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3321,6 +3547,10 @@ Error: %2$@ Servery ICE (jeden na řádek) No comment provided by engineer. + + IP address + 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. @@ -3361,8 +3591,8 @@ Error: %2$@ Ihned No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Odolná vůči spamu a zneužití No comment provided by engineer. @@ -3393,6 +3623,11 @@ Error: %2$@ Importing archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery No comment provided by engineer. @@ -3488,6 +3723,11 @@ Error: %2$@ Nainstalujte [SimpleX Chat pro terminál](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Okamžitě + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3495,11 +3735,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Okamžitě - No comment provided by engineer. - Interface Rozhranní @@ -3541,7 +3776,7 @@ Error: %2$@ Invalid server address! Neplatná adresa serveru! - No comment provided by engineer. + alert title Invalid status @@ -3563,6 +3798,10 @@ Error: %2$@ Pozvat členy No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Pozvat do skupiny @@ -3578,8 +3817,8 @@ Error: %2$@ Nevratné mazání zpráv je v tomto chatu zakázáno. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Nevratné mazání zpráv je v této skupině zakázáno. No comment provided by engineer. @@ -3662,7 +3901,7 @@ This is your link for group %@! Keep - No comment provided by engineer. + alert action Keep conversation @@ -3674,7 +3913,7 @@ This is your link for group %@! Keep unused invitation? - No comment provided by engineer. + alert title Keep your connections @@ -3711,6 +3950,14 @@ This is your link for group %@! Opustit swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Opustit skupinu @@ -3758,11 +4005,6 @@ This is your link for group %@! Živé zprávy No comment provided by engineer. - - Local - Místní - No comment provided by engineer. - Local name Místní název @@ -3783,11 +4025,6 @@ This is your link for group %@! Režim zámku No comment provided by engineer. - - Make a private connection - Vytvořte si soukromé připojení - No comment provided by engineer. - Make one message disappear Nechat jednu zprávu zmizet @@ -3798,21 +4035,11 @@ This is your link for group %@! Změnit profil na soukromý! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Ujistěte se, že adresy %@ serverů jsou ve správném formátu, oddělené řádky a nejsou duplicitní (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Ujistěte se, že adresy serverů WebRTC ICE jsou ve správném formátu, oddělené na řádcích a nejsou duplicitní. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Mnoho lidí se ptalo: *Pokud SimpleX nemá žádné uživatelské identifikátory, jak může doručovat zprávy?* - No comment provided by engineer. - Mark deleted for everyone Označit jako smazané pro všechny @@ -3855,6 +4082,10 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Role člena se změní na "%@". Všichni členové skupiny budou upozorněni. @@ -3865,11 +4096,49 @@ This is your link for group %@! Role člena se změní na "%@". Člen obdrží novou pozvánku. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Člen bude odstraněn ze skupiny - toto nelze vzít zpět! No comment provided by engineer. + + Members can add message reactions. + Členové skupin mohou přidávat reakce na zprávy. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin) + No comment provided by engineer. + + + Members can send SimpleX links. + No comment provided by engineer. + + + Members can send direct messages. + Členové skupiny mohou posílat přímé zprávy. + No comment provided by engineer. + + + Members can send disappearing messages. + Členové skupiny mohou posílat mizící zprávy. + No comment provided by engineer. + + + Members can send files and media. + Členové skupiny mohou posílat soubory a média. + No comment provided by engineer. + + + Members can send voice messages. + Členové skupiny mohou posílat hlasové zprávy. + No comment provided by engineer. + Menus No comment provided by engineer. @@ -3915,8 +4184,8 @@ This is your link for group %@! Reakce na zprávy jsou v tomto chatu zakázány. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Reakce na zprávy jsou v této skupině zakázány. No comment provided by engineer. @@ -3928,6 +4197,10 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3971,6 +4244,10 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. No comment provided by engineer. @@ -4027,9 +4304,9 @@ This is your link for group %@! Přenesení dokončeno No comment provided by engineer. - - Migrations: %@ - Migrace: %@ + + Migrations: + Migrace: No comment provided by engineer. @@ -4056,6 +4333,10 @@ This is your link for group %@! More reliable network connection. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Pravděpodobně je toto spojení smazáno. @@ -4090,6 +4371,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. snd error text @@ -4098,6 +4383,10 @@ This is your link for group %@! Network management No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Nastavení sítě @@ -4113,6 +4402,14 @@ This is your link for group %@! Nové heslo No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat No comment provided by engineer. @@ -4131,11 +4428,6 @@ This is your link for group %@! Nový kontakt: notification - - New database archive - Archiv nové databáze - No comment provided by engineer. - New desktop app! Nová desktopová aplikace! @@ -4146,6 +4438,10 @@ This is your link for group %@! Nově zobrazované jméno No comment provided by engineer. + + New events + notification + New in %@ Nový V %@ @@ -4170,6 +4466,10 @@ This is your link for group %@! Nová přístupová fráze… No comment provided by engineer. + + New server + No comment provided by engineer. + No Ne @@ -4223,20 +4523,62 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message Nemáte oprávnění nahrávat hlasové zprávy No comment provided by engineer. + + No push server + Místní + No comment provided by engineer. + No received or sent files Žádné přijaté ani odeslané soubory No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Bez uživatelských identifikátorů + No comment provided by engineer. + Not compatible! No comment provided by engineer. @@ -4245,6 +4587,10 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + alert title + Notifications Oznámení @@ -4255,6 +4601,10 @@ This is your link for group %@! Oznámení jsou zakázána! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4276,18 +4626,13 @@ This is your link for group %@! Ok Ok - No comment provided by engineer. + alert button Old database Stará databáze No comment provided by engineer. - - Old database archive - Archiv staré databáze - No comment provided by engineer. - One-time invitation link Jednorázový zvací odkaz @@ -4312,8 +4657,12 @@ Vyžaduje povolení sítě VPN. Onion hostitelé nebudou použiti. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Pouze klientská zařízení ukládají uživatelské profily, kontakty, skupiny a zprávy odeslané s **2vrstvým šifrováním typu end-to-end**. No comment provided by engineer. @@ -4396,6 +4745,10 @@ Vyžaduje povolení sítě VPN. Otevřít nastavení No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Otevřete chat @@ -4406,6 +4759,10 @@ Vyžaduje povolení sítě VPN. Otevřete konzolu chatu authentication reason + + Open conditions + No comment provided by engineer. + Open group No comment provided by engineer. @@ -4414,24 +4771,22 @@ Vyžaduje povolení sítě VPN. Open migration to another device authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - Otevřít uživatelské profily - authentication reason - - - 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 app… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link No comment provided by engineer. @@ -4448,13 +4803,18 @@ Vyžaduje povolení sítě VPN. Or show this code No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4491,6 +4851,10 @@ Vyžaduje povolení sítě VPN. Heslo nastaveno! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show Heslo k zobrazení @@ -4521,13 +4885,8 @@ Vyžaduje povolení sítě VPN. Pending No comment provided by engineer. - - People can connect to you only via the links you share. - Lidé se s vámi mohou spojit pouze prostřednictvím odkazů, které sdílíte. - No comment provided by engineer. - - - Periodically + + Periodic Pravidelně No comment provided by engineer. @@ -4627,6 +4986,10 @@ Error: %@ Polské rozhraní No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Je možné, že otisk certifikátu v adrese serveru je nesprávný @@ -4637,16 +5000,15 @@ Error: %@ Zachování posledního návrhu zprávy s přílohami. No comment provided by engineer. - - Preset server - Přednastavený server - No comment provided by engineer. - Preset server address Přednastavená adresa serveru No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview Náhled @@ -4661,6 +5023,10 @@ Error: %@ Ochrana osobních údajů a zabezpečení No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Nové vymezení soukromí @@ -4705,14 +5071,6 @@ Error: %@ Profile images No comment provided by engineer. - - Profile name - No comment provided by engineer. - - - Profile name: - No comment provided by engineer. - Profile password Heslo profilu @@ -4725,7 +5083,7 @@ Error: %@ Profile update will be sent to your contacts. Aktualizace profilu bude zaslána vašim kontaktům. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4808,6 +5166,10 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + No comment provided by engineer. + Push notifications Nabízená oznámení @@ -4845,25 +5207,20 @@ Enable in *Network & servers* settings. Přečíst více No comment provided by engineer. - - Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). - Další informace naleznete v [Uživatelské příručce](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). No comment provided by engineer. + + Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + No comment provided by engineer. + Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). Přečtěte si více v [Uživatelské příručce](https://simplex.chat/docs/guide/readme.html#connect-to-friends). No comment provided by engineer. - - Read more in our GitHub repository. - Další informace najdete v našem repozitáři GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Přečtěte si více v našem [GitHub repozitáři](https://github.com/simplex-chat/simplex-chat#readme). @@ -5014,6 +5371,10 @@ Enable in *Network & servers* settings. Odstranit No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image No comment provided by engineer. @@ -5152,6 +5513,14 @@ Enable in *Network & servers* settings. Odhalit chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke Odvolat @@ -5181,6 +5550,10 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + No comment provided by engineer. + Safely receive files No comment provided by engineer. @@ -5192,17 +5565,18 @@ Enable in *Network & servers* settings. Save Uložit - chat item action + alert button + chat item action Save (and notify contacts) Uložit (a informovat kontakty) - No comment provided by engineer. + alert button Save and notify contact Uložit a upozornit kontakt - No comment provided by engineer. + alert button Save and notify group members @@ -5218,16 +5592,6 @@ Enable in *Network & servers* settings. Uložit a aktualizovat profil skupiny No comment provided by engineer. - - Save archive - Uložit archiv - No comment provided by engineer. - - - Save auto-accept settings - Uložit nastavení automatického přijímání - No comment provided by engineer. - Save group profile Uložení profilu skupiny @@ -5246,7 +5610,7 @@ Enable in *Network & servers* settings. Save preferences? Uložit předvolby? - No comment provided by engineer. + alert title Save profile password @@ -5261,18 +5625,17 @@ Enable in *Network & servers* settings. Save servers? Uložit servery? - No comment provided by engineer. - - - Save settings? - Uložit nastavení? - No comment provided by engineer. + alert title Save welcome message? Uložit uvítací zprávu? No comment provided by engineer. + + Save your profile? + alert title + Saved No comment provided by engineer. @@ -5290,6 +5653,10 @@ Enable in *Network & servers* settings. Saved message message info title + + Saving %lld messages + No comment provided by engineer. + Scale No comment provided by engineer. @@ -5363,6 +5730,10 @@ Enable in *Network & servers* settings. Vybrat chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld No comment provided by engineer. @@ -5447,11 +5818,6 @@ Enable in *Network & servers* settings. Odeslat oznámení No comment provided by engineer. - - Send notifications: - Odeslat oznámení: - No comment provided by engineer. - Send questions and ideas Zasílání otázek a nápadů @@ -5474,7 +5840,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Odesílatel zrušil přenos souboru. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5566,6 +5932,14 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address No comment provided by engineer. @@ -5578,6 +5952,18 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Server vyžaduje autorizaci pro vytváření front, zkontrolujte heslo @@ -5675,6 +6061,10 @@ Enable in *Network & servers* settings. Nastavení No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images No comment provided by engineer. @@ -5682,22 +6072,35 @@ Enable in *Network & servers* settings. Share Sdílet - chat item action + alert action + chat item action Share 1-time link Sdílet jednorázovou pozvánku No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Sdílet adresu No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Sdílet adresu s kontakty? - No comment provided by engineer. + alert title Share from other apps. @@ -5708,6 +6111,10 @@ Enable in *Network & servers* settings. Sdílet odkaz No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link No comment provided by engineer. @@ -5771,6 +6178,10 @@ Enable in *Network & servers* settings. SimpleX Adresa No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Zabezpečení SimpleX chatu bylo auditováno společností Trail of Bits. @@ -5801,6 +6212,14 @@ Enable in *Network & servers* settings. Adresa SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX kontaktní adresa @@ -5821,8 +6240,8 @@ Enable in *Network & servers* settings. Odkazy na SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. No comment provided by engineer. @@ -5834,6 +6253,10 @@ Enable in *Network & servers* settings. Jednorázová pozvánka SimpleX simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Zjednodušený inkognito režim @@ -5862,6 +6285,10 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: No comment provided by engineer. @@ -5875,6 +6302,11 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Někdo @@ -5920,11 +6352,6 @@ Enable in *Network & servers* settings. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - Zastavte chat pro povolení akcí databáze - 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. Zastavení chatu pro export, import nebo smazání databáze chatu. Během zastavení chatu nebudete moci přijímat a odesílat zprávy. @@ -5953,12 +6380,12 @@ Enable in *Network & servers* settings. Stop sharing Přestat sdílet - No comment provided by engineer. + alert action Stop sharing address? Přestat sdílet adresu? - No comment provided by engineer. + alert title Stopping chat @@ -5990,6 +6417,14 @@ Enable in *Network & servers* settings. Podpořte SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System Systém @@ -6024,11 +6459,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture Vyfotit No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Klepněte na tlačítko @@ -6083,7 +6526,7 @@ Enable in *Network & servers* settings. Tests failed! Testy selhaly! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6100,11 +6543,6 @@ Enable in *Network & servers* settings. Díky uživatelům - přispívejte prostřednictvím Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - 1. Platforma bez identifikátorů uživatelů - soukromá už od záměru. - No comment provided by engineer. - 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. @@ -6117,6 +6555,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Aplikace vás může upozornit na přijaté zprávy nebo žádosti o kontakt - povolte to v nastavení. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). No comment provided by engineer. @@ -6130,6 +6572,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován The code you scanned is not a SimpleX link QR code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Připojení, které jste přijali, bude zrušeno! @@ -6150,6 +6596,11 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Šifrování funguje a nové povolení šifrování není vyžadováno. To může vyvolat chybu v připojení! No comment provided by engineer. + + The future of messaging + Nová generace soukromých zpráv + No comment provided by engineer. + The hash of the previous message is different. Hash předchozí zprávy se liší. @@ -6173,11 +6624,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - Nová generace soukromých zpráv - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Stará databáze nebyla během přenášení odstraněna, lze ji smazat. @@ -6188,6 +6634,18 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Profil je sdílen pouze s vašimi kontakty. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Druhé zaškrtnutí jsme přehlédli! ✅ @@ -6203,14 +6661,26 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Servery pro nová připojení vašeho aktuálního chat profilu **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + No comment provided by engineer. + The text you pasted is not a SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Toto nastavení je pro váš aktuální profil **%@**. @@ -6302,9 +6772,8 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován Vytvoření nového připojení 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. - Pro ochranu soukromí namísto ID uživatelů používaných všemi ostatními platformami má SimpleX identifikátory pro fronty zpráv, oddělené pro každý z vašich kontaktů. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6323,6 +6792,23 @@ You will be prompted to complete authentication before this feature is enabled.< Před zapnutím této funkce budete vyzváni k dokončení ověření. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Pro ochranu soukromí namísto ID uživatelů používaných všemi ostatními platformami má SimpleX identifikátory pro fronty zpráv, oddělené pro každý z vašich kontaktů. + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Chcete-li nahrávat hlasové zprávy, udělte povolení k použití mikrofonu. @@ -6333,11 +6819,19 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Chcete-li odhalit svůj skrytý profil, zadejte celé heslo do vyhledávacího pole na stránce **Chat profily**. No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Pro podporu doručování okamžitých upozornění musí být přenesena chat databáze. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Chcete-li ověřit koncové šifrování u svého kontaktu, porovnejte (nebo naskenujte) kód na svých zařízeních. @@ -6418,6 +6912,10 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Unblock member? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state Neočekávaný stav přenášení @@ -6465,7 +6963,7 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření. Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6565,11 +7063,19 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Uploading archive No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts Použít hostitele .onion No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? Používat servery SimpleX Chat? @@ -6585,6 +7091,14 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Použít aktuální profil No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Použít pro nová připojení @@ -6621,6 +7135,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Použít server No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. No comment provided by engineer. @@ -6629,15 +7147,14 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Use the app with one hand. No comment provided by engineer. - - User profile - Profil uživatele - No comment provided by engineer. - User selection No comment provided by engineer. + + Username + No comment provided by engineer. + Using SimpleX Chat servers. Používat servery SimpleX Chat. @@ -6702,11 +7219,19 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Videa a soubory až do velikosti 1 gb No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Zobrazení bezpečnostního kódu No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history chat feature @@ -6721,8 +7246,8 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Hlasové zprávy jsou v tomto chatu zakázány. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Hlasové zprávy jsou v této skupině zakázány. No comment provided by engineer. @@ -6809,9 +7334,8 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu When connecting audio and video calls. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Když někdo požádá o připojení, můžete žádost přijmout nebo odmítnout. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -6850,7 +7374,7 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -6874,11 +7398,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu XFTP server No comment provided by engineer. - - You - Vy - No comment provided by engineer. - You **must not** use the same database on two devices. No comment provided by engineer. @@ -6903,6 +7422,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu Již jste připojeni k %@. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. No comment provided by engineer. @@ -6955,6 +7478,14 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + No comment provided by engineer. + You can create it later Můžete vytvořit později @@ -6992,6 +7523,10 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. Náhled oznámení na zamykací obrazovce můžete změnit v nastavení. @@ -7007,11 +7542,6 @@ Repeat join request? Tuto adresu můžete sdílet s vašimi kontakty, abyse se mohli spojit s **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Chat můžete zahájit prostřednictvím aplikace Nastavení / Databáze nebo restartováním aplikace @@ -7033,23 +7563,23 @@ Repeat join request? You can view invitation link again in connection details. - No comment provided by engineer. + alert message You can't send messages! Nemůžete posílat zprávy! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Sami řídíte, přes který server(y) **přijímat** zprávy, své kontakty – servery, které používáte k odesílání zpráv. - No comment provided by engineer. - You could not be verified; please try again. Nemohli jste být ověřeni; Zkuste to prosím znovu. No comment provided by engineer. + + You decide who can connect. + Lidé se s vámi mohou spojit pouze prostřednictvím odkazu, který sdílíte. + No comment provided by engineer. + You have already requested connection via this address! No comment provided by engineer. @@ -7144,6 +7674,10 @@ Repeat connection request? Stále budete přijímat volání a upozornění od umlčených profilů pokud budou aktivní. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + 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. @@ -7164,11 +7698,6 @@ Repeat connection request? Pro tuto skupinu používáte inkognito profil - abyste zabránili sdílení svého hlavního profilu, není pozvání kontaktů povoleno No comment provided by engineer. - - Your %@ servers - Vaše servery %@ - No comment provided by engineer. - Your ICE servers Vaše servery ICE @@ -7184,11 +7713,6 @@ Repeat connection request? Vaše SimpleX adresa No comment provided by engineer. - - Your XFTP servers - Vaše XFTP servery - No comment provided by engineer. - Your calls Vaše hovory @@ -7204,11 +7728,19 @@ Repeat connection request? Vaše chat databáze není šifrována – nastavte přístupovou frázi pro její šifrování. No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles Vaše chat profily No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Kontakt odeslal soubor, který je větší než aktuálně podporovaná maximální velikost (%@). @@ -7224,6 +7756,10 @@ Repeat connection request? Vaše kontakty zůstanou připojeny. No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Vaše aktuální chat databáze bude ODSTRANĚNA a NAHRAZENA importovanou. @@ -7253,13 +7789,15 @@ Repeat connection request? Váš profil **%@** bude sdílen. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. -Servery SimpleX nevidí váš profil. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení. @@ -7270,16 +7808,15 @@ Servery SimpleX nevidí váš profil. Váš náhodný profil No comment provided by engineer. - - Your server - Váš server - No comment provided by engineer. - Your server address Adresa vašeho serveru No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings Vaše nastavení @@ -7320,6 +7857,10 @@ Servery SimpleX nevidí váš profil. přijatý hovor call status + + accepted invitation + chat list item title + admin správce @@ -7499,7 +8040,7 @@ Servery SimpleX nevidí váš profil. connecting… připojení… - chat list item title + No comment provided by engineer. connection established @@ -7685,6 +8226,10 @@ Servery SimpleX nevidí váš profil. expired No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded No comment provided by engineer. @@ -7970,6 +8515,10 @@ Servery SimpleX nevidí váš profil. odstranil vás rcv group event chat item + + requested to connect + chat list item title + saved No comment provided by engineer. @@ -8273,6 +8822,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/cs.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 6461ee91bc..e993740f1c 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ wurde erfolgreich überprüft No comment provided by engineer. + + %@ server + %@ Server + No comment provided by engineer. + + + %@ servers + %@ Server + No comment provided by engineer. + %@ uploaded %@ hochgeladen @@ -137,6 +132,11 @@ %@ will sich mit Ihnen verbinden! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ und %lld Mitglieder @@ -157,11 +157,36 @@ %d Tage time interval + + %d file(s) are still being downloaded. + %d Datei(en) wird/werden immer noch heruntergeladen. + forward confirmation reason + + + %d file(s) failed to download. + Bei %d Datei(en) ist das Herunterladen fehlgeschlagen. + forward confirmation reason + + + %d file(s) were deleted. + %d Datei(en) wurde(n) gelöscht. + forward confirmation reason + + + %d file(s) were not downloaded. + %d Datei(en) wurde(n) nicht heruntergeladen. + forward confirmation reason + %d hours %d Stunden time interval + + %d messages not forwarded + %d Nachrichten wurden nicht weitergeleitet + alert title + %d min %d min @@ -322,14 +347,9 @@ ) No comment provided by engineer. - - **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. - - - **Add new contact**: to create your one-time QR Code or link for your contact. - **Neuen Kontakt hinzufügen**: Um einen Einmal-QR-Code oder -Link für Ihren Kontakt zu erzeugen. + + **Create 1-time link**: to create and share a new invitation link. + **Kontakt hinzufügen**: Um einen neuen Einladungslink zu erstellen. No comment provided by engineer. @@ -337,13 +357,13 @@ **Gruppe erstellen**: Um eine neue Gruppe zu erstellen. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Mehr Privatsphäre**: Es wird alle 20 Minuten auf neue Nachrichten geprüft. Nur Ihr Geräte-Token wird dem SimpleX-Chat-Server mitgeteilt, aber nicht wie viele Kontakte Sie haben oder welche Nachrichten Sie empfangen. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +377,16 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + **Link scannen / einfügen**: Um eine Verbindung über den Link herzustellen, den Sie erhalten haben. + 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. @@ -468,6 +493,16 @@ wöchentlich time interval + + 1-time link + Einmal-Link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Ein Einmal-Link kann *nur mit einem Kontakt* genutzt werden - teilen Sie in nur persönlich oder über einen beliebigen Messenger. + No comment provided by engineer. + 5 minutes 5 Minuten @@ -537,19 +572,14 @@ Wechsel der Empfängeradresse beenden? No comment provided by engineer. - - About SimpleX - Über SimpleX - No comment provided by engineer. - About SimpleX Chat Über SimpleX Chat No comment provided by engineer. - - About SimpleX address - Über die SimpleX-Adresse + + About operators + Über Betreiber No comment provided by engineer. @@ -564,6 +594,11 @@ accept incoming call via notification swipe action + + Accept conditions + Nutzungsbedingungen akzeptieren + No comment provided by engineer. + Accept connection request? Kontaktanfrage annehmen? @@ -580,6 +615,11 @@ accept contact request via notification swipe action + + Accepted conditions + Akzeptierte Nutzungsbedingungen + No comment provided by engineer. + Acknowledged Bestätigt @@ -600,14 +640,9 @@ 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 + + Add friends + Freunde aufnehmen No comment provided by engineer. @@ -625,6 +660,11 @@ Fügen Sie Server durch Scannen der QR Codes hinzu. No comment provided by engineer. + + Add team members + Team-Mitglieder aufnehmen + No comment provided by engineer. + Add to another device Einem anderen Gerät hinzufügen @@ -635,6 +675,21 @@ Begrüßungsmeldung hinzufügen No comment provided by engineer. + + Add your team members to the conversations. + Nehmen Sie Team-Mitglieder in Ihre Unterhaltungen auf. + No comment provided by engineer. + + + Added media & file servers + Medien- und Dateiserver hinzugefügt + No comment provided by engineer. + + + Added message servers + Nachrichtenserver hinzugefügt + No comment provided by engineer. + Additional accent Erste Akzentfarbe @@ -660,6 +715,16 @@ Der Wechsel der Empfängeradresse wird beendet. Die bisherige Adresse wird weiter verwendet. No comment provided by engineer. + + Address or 1-time link? + Adress- oder Einmal-Link? + No comment provided by engineer. + + + Address settings + Adress-Einstellungen + No comment provided by engineer. + Admins can block a member for all. Administratoren können ein Gruppenmitglied für Alle blockieren. @@ -695,8 +760,8 @@ Alle Daten werden gelöscht, sobald dieser eingegeben wird. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Alle Daten werden nur auf Ihrem Gerät gespeichert. No comment provided by engineer. @@ -705,6 +770,11 @@ Alle Gruppenmitglieder bleiben verbunden. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Alle Nachrichten und Dateien werden **Ende-zu-Ende verschlüsselt** versendet - in Direkt-Nachrichten mit Post-Quantum-Security. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Es werden alle Nachrichten gelöscht. Dies kann nicht rückgängig gemacht werden! @@ -723,7 +793,7 @@ All profiles Alle Profile - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -885,6 +955,11 @@ Anruf annehmen No comment provided by engineer. + + Anybody can host servers. + Jeder kann seine eigenen Server aufsetzen. + No comment provided by engineer. + App build: %@ App Build: %@ @@ -915,6 +990,11 @@ App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt. No comment provided by engineer. + + App session + App-Sitzung + No comment provided by engineer. + App version App Version @@ -1020,6 +1100,11 @@ Bilder automatisch akzeptieren No comment provided by engineer. + + Auto-accept settings + Einstellungen automatisch akzeptieren + alert title + Back Zurück @@ -1045,11 +1130,21 @@ Ungültiger Nachrichten-Hash No comment provided by engineer. + + Better calls + Verbesserte Anrufe + No comment provided by engineer. + Better groups Bessere Gruppen No comment provided by engineer. + + Better message dates. + Verbesserte Nachrichten-Datumsinformation + No comment provided by engineer. + Better messages Verbesserungen bei Nachrichten @@ -1057,7 +1152,22 @@ Better networking - Bessere Vernetzung + Kontrollieren Sie Ihr Netzwerk + No comment provided by engineer. + + + Better notifications + Verbesserte Benachrichtigungen + No comment provided by engineer. + + + Better security ✅ + Verbesserte Sicherheit ✅ + No comment provided by engineer. + + + Better user experience + Verbesserte Nutzer-Erfahrung No comment provided by engineer. @@ -1140,6 +1250,16 @@ Bulgarisch, Finnisch, Thailändisch und Ukrainisch - Dank der Nutzer und [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Geschäftliche Adresse + No comment provided by engineer. + + + Business chats + Geschäftliche Chats + 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). Per Chat-Profil (Voreinstellung) oder [per Verbindung](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1193,7 +1313,8 @@ Cancel Abbrechen - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1334,7 @@ Cannot receive file Datei kann nicht empfangen werden - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1351,11 @@ Ändern No comment provided by engineer. + + Change chat profiles + Chat-Profile wechseln + authentication reason + Change database passphrase? Datenbank-Passwort ändern? @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Datenbank Archiv + + Chat + Chat + No comment provided by engineer. + + + Chat already exists + Chat besteht bereits + No comment provided by engineer. + + + Chat already exists! + Chat besteht bereits! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Chat-Präferenzen No comment provided by engineer. + + Chat preferences were changed. + Die Chat-Präferenzen wurden geändert. + alert message + + + Chat profile + Benutzerprofil + No comment provided by engineer. + Chat theme Chat-Design No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + Der Chat wird für alle Mitglieder gelöscht. Dies kann nicht rückgängig gemacht werden! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + Der Chat wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden! + No comment provided by engineer. + Chats Chats No comment provided by engineer. + + Check messages every 20 min. + Alle 20min Nachrichten überprüfen. + No comment provided by engineer. + + + Check messages when allowed. + Wenn es erlaubt ist, Nachrichten überprüfen. + No comment provided by engineer. + Check server address and try again. Überprüfen Sie die Serveradresse und versuchen Sie es nochmal. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1393,22 +1559,22 @@ Clear - Löschen + Entfernen swipe action Clear conversation - Chatinhalte löschen + Chat-Inhalte entfernen No comment provided by engineer. Clear conversation? - Unterhaltung löschen? + Chat-Inhalte entfernen? No comment provided by engineer. Clear private notes? - Private Notizen löschen? + Private Notizen entfernen? No comment provided by engineer. @@ -1441,16 +1607,56 @@ Abgeschlossen No comment provided by engineer. + + Conditions accepted on: %@. + Die Nutzungsbedingungen wurden akzeptiert am: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Die Nutzungsbedingungen der/des folgenden Betreiber(s) wurden schon akzeptiert: **%@**. + No comment provided by engineer. + + + Conditions of use + Nutzungsbedingungen + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Die Nutzungsbedingungen der aktivierten Betreiber werden nach 30 Tagen akzeptiert. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Die Nutzungsbedingungen werden akzeptiert am: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Die Nutzungsbedingungen der aktivierten Betreiber werden automatisch akzeptiert am: %@. + No comment provided by engineer. + Configure ICE servers ICE-Server konfigurieren No comment provided by engineer. - - Configured %@ servers - Konfigurierte %@ Server - No comment provided by engineer. - Confirm Bestätigen @@ -1640,6 +1846,11 @@ Das ist Ihr eigener Einmal-Link! Verbindungsanfrage wurde gesendet! No comment provided by engineer. + + Connection security + Verbindungs-Sicherheit + No comment provided by engineer. + Connection terminated Verbindung beendet @@ -1722,7 +1933,7 @@ Das ist Ihr eigener Einmal-Link! Conversation deleted! - Unterhaltung gelöscht! + Chat-Inhalte entfernt! No comment provided by engineer. @@ -1740,6 +1951,11 @@ Das ist Ihr eigener Einmal-Link! Core Version: v%@ No comment provided by engineer. + + Corner + Abrundung Ecken + No comment provided by engineer. + Correct name to %@? Richtiger Name für %@? @@ -1750,6 +1966,11 @@ Das ist Ihr eigener Einmal-Link! Erstellen No comment provided by engineer. + + Create 1-time link + Einmal-Link erstellen + No comment provided by engineer. + Create SimpleX address SimpleX-Adresse erstellen @@ -1760,11 +1981,6 @@ Das ist Ihr eigener Einmal-Link! Erstellen Sie eine Gruppe mit einem zufälligen Profil. No comment provided by engineer. - - Create an address to let people connect with you. - Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können. - No comment provided by engineer. - Create file Datei erstellen @@ -1825,11 +2041,6 @@ Das ist Ihr eigener Einmal-Link! Erstellt um: %@ copied message info - - Created on %@ - Erstellt am %@ - No comment provided by engineer. - Creating archive link Archiv-Link erzeugen @@ -1845,6 +2056,11 @@ Das ist Ihr eigener Einmal-Link! Aktueller Zugangscode No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + Der Text der aktuellen Nutzungsbedingungen konnte nicht geladen werden. Sie können die Nutzungsbedingungen unter diesem Link einsehen: + No comment provided by engineer. + Current passphrase… Aktuelles Passwort… @@ -1865,6 +2081,11 @@ Das ist Ihr eigener Einmal-Link! Zeit anpassen No comment provided by engineer. + + Customizable message shape. + Anpassbares Format des Nachrichtenfelds + No comment provided by engineer. + Customize theme Design anpassen @@ -1996,7 +2217,8 @@ Das ist Ihr eigener Einmal-Link! Delete Löschen - chat item action + alert action + chat item action swipe action @@ -2034,14 +2256,9 @@ Das ist Ihr eigener Einmal-Link! Kontakt löschen und benachrichtigen No comment provided by engineer. - - Delete archive - Archiv löschen - No comment provided by engineer. - - - Delete chat archive? - Chat Archiv löschen? + + Delete chat + Chat löschen No comment provided by engineer. @@ -2054,6 +2271,11 @@ Das ist Ihr eigener Einmal-Link! Chat-Profil löschen? No comment provided by engineer. + + Delete chat? + Chat löschen? + No comment provided by engineer. + Delete connection Verbindung löschen @@ -2159,6 +2381,11 @@ Das ist Ihr eigener Einmal-Link! Alte Datenbank löschen? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Bis zu 200 Nachrichten löschen oder moderieren + No comment provided by engineer. + Delete pending connection? Ausstehende Verbindung löschen? @@ -2209,6 +2436,11 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Löschen No comment provided by engineer. + + Delivered even when Apple drops them. + Auslieferung, selbst wenn Apple sie löscht. + No comment provided by engineer. + Delivery Zustellung @@ -2309,8 +2541,13 @@ Das ist Ihr eigener Einmal-Link! Direkte Nachrichten chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + In diesem Chat sind Direktnachrichten zwischen Mitgliedern nicht erlaubt. + No comment provided by engineer. + + + Direct messages between members are prohibited. In dieser Gruppe sind Direktnachrichten zwischen Mitgliedern nicht erlaubt. No comment provided by engineer. @@ -2349,8 +2586,8 @@ Das ist Ihr eigener Einmal-Link! In diesem Chat sind verschwindende Nachrichten nicht erlaubt. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. In dieser Gruppe sind verschwindende Nachrichten nicht erlaubt. No comment provided by engineer. @@ -2409,6 +2646,11 @@ Das ist Ihr eigener Einmal-Link! Den Nachrichtenverlauf nicht an neue Mitglieder senden. No comment provided by engineer. + + Do not use credentials with proxy. + Verwenden Sie keine Anmeldeinformationen mit einem Proxy. + No comment provided by engineer. + Don't create address Keine Adresse erstellt @@ -2432,7 +2674,8 @@ Das ist Ihr eigener Einmal-Link! Download Herunterladen - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ Das ist Ihr eigener Einmal-Link! Datei herunterladen server test step + + Download files + Dateien herunterladen + alert action + Downloaded Heruntergeladen @@ -2479,6 +2727,11 @@ Das ist Ihr eigener Einmal-Link! Dauer No comment provided by engineer. + + E2E encrypted notifications. + E2E-verschlüsselte Benachrichtigungen. + No comment provided by engineer. + Edit Bearbeiten @@ -2499,6 +2752,11 @@ Das ist Ihr eigener Einmal-Link! Aktivieren (vorgenommene Einstellungen bleiben erhalten) No comment provided by engineer. + + Enable Flux + Flux aktivieren + No comment provided by engineer. + Enable SimpleX Lock SimpleX-Sperre aktivieren @@ -2704,26 +2962,36 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Beenden des Adresswechsels No comment provided by engineer. + + Error accepting conditions + Fehler beim Akzeptieren der Nutzungsbedingungen + alert title + Error accepting contact request Fehler beim Annehmen der Kontaktanfrage No comment provided by engineer. - - Error accessing database file - Fehler beim Zugriff auf die Datenbankdatei - No comment provided by engineer. - Error adding member(s) Fehler beim Hinzufügen von Mitgliedern No comment provided by engineer. + + Error adding server + Fehler beim Hinzufügen des Servers + alert title + Error changing address Fehler beim Wechseln der Empfängeradresse No comment provided by engineer. + + Error changing connection profile + Fehler beim Wechseln des Verbindungs-Profils + No comment provided by engineer. + Error changing role Fehler beim Ändern der Rolle @@ -2734,6 +3002,11 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Ändern der Einstellung No comment provided by engineer. + + Error changing to incognito! + Fehler beim Wechseln zum Inkognito-Profil! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Fehler beim Verbinden mit dem Weiterleitungsserver %@. Bitte versuchen Sie es später erneut. @@ -2849,9 +3122,14 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Beitritt zur Gruppe No comment provided by engineer. - - Error loading %@ servers - Fehler beim Laden von %@ Servern + + Error loading servers + Fehler beim Laden der Server + alert title + + + Error migrating settings + Fehler beim Migrieren der Einstellungen No comment provided by engineer. @@ -2862,7 +3140,7 @@ Das ist Ihr eigener Einmal-Link! Error receiving file Fehler beim Empfangen der Datei - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3162,6 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Zurücksetzen der Statistiken No comment provided by engineer. - - Error saving %@ servers - Fehler beim Speichern der %@-Server - No comment provided by engineer. - Error saving ICE servers Fehler beim Speichern der ICE-Server @@ -2909,6 +3182,11 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Speichern des Passworts in den Schlüsselbund No comment provided by engineer. + + Error saving servers + Fehler beim Speichern der Server + alert title + Error saving settings Fehler beim Abspeichern der Einstellungen @@ -2954,10 +3232,15 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Beenden des Chats No comment provided by engineer. + + Error switching profile + Fehler beim Wechseln des Profils + No comment provided by engineer. + Error switching profile! Fehler beim Umschalten des Profils! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3257,11 @@ Das ist Ihr eigener Einmal-Link! Fehler beim Aktualisieren der Nachricht No comment provided by engineer. + + Error updating server + Fehler beim Aktualisieren des Servers + alert title + Error updating settings Fehler beim Aktualisieren der Einstellungen @@ -3002,8 +3290,7 @@ Das ist Ihr eigener Einmal-Link! Error: %@ Fehler: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3307,11 @@ Das ist Ihr eigener Einmal-Link! Fehler No comment provided by engineer. + + Errors in servers configuration. + Fehler in der Server-Konfiguration. + servers error + Even when disabled in the conversation. Auch wenn sie im Chat deaktiviert sind. @@ -3090,6 +3382,13 @@ Das ist Ihr eigener Einmal-Link! Datei-Fehler No comment provided by engineer. + + File errors: +%@ + Datei-Fehler: +%@ + alert message + File not found - most likely file was deleted or cancelled. Datei nicht gefunden - höchstwahrscheinlich wurde die Datei gelöscht oder der Transfer abgebrochen. @@ -3145,8 +3444,8 @@ Das ist Ihr eigener Einmal-Link! Dateien und Medien chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. In dieser Gruppe sind Dateien und Medien nicht erlaubt. No comment provided by engineer. @@ -3215,21 +3514,61 @@ Das ist Ihr eigener Einmal-Link! Reparatur wird vom Gruppenmitglied nicht unterstützt No comment provided by engineer. + + For chat profile %@: + Für das Chat-Profil %@: + servers error + For console Für Konsole No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Wenn Ihr Kontakt beispielsweise Nachrichten über einen SimpleX-Chatserver empfängt, wird Ihre App diese über einen der Server von Flux versenden. + No comment provided by engineer. + + + For private routing + Für privates Routing + No comment provided by engineer. + + + For social media + Für soziale Medien + No comment provided by engineer. + Forward Weiterleiten chat item action + + Forward %d message(s)? + %d Nachricht(en) weiterleiten? + alert title + Forward and save messages Nachrichten weiterleiten und speichern No comment provided by engineer. + + Forward messages + Nachrichten weiterleiten + alert action + + + Forward messages without files? + Nachrichten ohne Dateien weiterleiten? + alert message + + + Forward up to 20 messages at once. + Bis zu 20 Nachrichten auf einmal weiterleiten + No comment provided by engineer. + Forwarded Weitergeleitet @@ -3240,6 +3579,11 @@ Das ist Ihr eigener Einmal-Link! Weitergeleitet aus No comment provided by engineer. + + Forwarding %lld messages + %lld Nachricht(en) wird/werden weitergeleitet + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. Weiterleitungsserver %@ konnte sich nicht mit dem Zielserver %@ verbinden. Bitte versuchen Sie es später erneut. @@ -3289,11 +3633,6 @@ Fehler: %2$@ Vollständiger Name (optional) No comment provided by engineer. - - Full name: - Vollständiger Name: - No comment provided by engineer. - Fully decentralized – visible only to members. Vollständig dezentralisiert – nur für Mitglieder sichtbar. @@ -3379,41 +3718,6 @@ Fehler: %2$@ Gruppen-Links No comment provided by engineer. - - 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. (24 hours) - Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden) - No comment provided by engineer. - - - Group members can send SimpleX links. - Gruppenmitglieder können SimpleX-Links senden. - No comment provided by engineer. - - - Group members can send direct messages. - Gruppenmitglieder können Direktnachrichten versenden. - No comment provided by engineer. - - - Group members can send disappearing messages. - Gruppenmitglieder können verschwindende Nachrichten senden. - No comment provided by engineer. - - - Group members can send files and media. - Gruppenmitglieder können Dateien und Medien senden. - No comment provided by engineer. - - - Group members can send voice messages. - Gruppenmitglieder können Sprachnachrichten versenden. - No comment provided by engineer. - Group message: Grppennachricht: @@ -3451,7 +3755,7 @@ Fehler: %2$@ Group will be deleted for you - this cannot be undone! - Die Gruppe wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden! + Die Gruppe wird nur bei Ihnen gelöscht. Dies kann nicht rückgängig gemacht werden! No comment provided by engineer. @@ -3509,9 +3813,14 @@ Fehler: %2$@ Wie SimpleX funktioniert No comment provided by engineer. - - How it works - Wie es funktioniert + + How it affects privacy + Wie es die Privatsphäre beeinflusst + No comment provided by engineer. + + + How it helps privacy + Wie es die Privatsphäre schützt No comment provided by engineer. @@ -3539,6 +3848,11 @@ Fehler: %2$@ ICE-Server (einer pro Zeile) No comment provided by engineer. + + IP address + IP-Adresse + 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. @@ -3579,8 +3893,8 @@ Fehler: %2$@ Sofort No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Immun gegen Spam und Missbrauch No comment provided by engineer. @@ -3614,6 +3928,13 @@ Fehler: %2$@ Archiv wird importiert No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Verbesserte Nachrichten-Auslieferung und verringerter Datenverbrauch. +Weitere Verbesserungen sind bald verfügbar! + No comment provided by engineer. + Improved message delivery Verbesserte Zustellung von Nachrichten @@ -3714,6 +4035,11 @@ Fehler: %2$@ Installieren Sie [SimpleX Chat als Terminalanwendung](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Sofort + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4047,6 @@ Fehler: %2$@ No comment provided by engineer. - - Instantly - Sofort - No comment provided by engineer. - Interface Schnittstelle @@ -3774,7 +4095,7 @@ Fehler: %2$@ Invalid server address! Ungültige Serveradresse! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4117,11 @@ Fehler: %2$@ Mitglieder einladen No comment provided by engineer. + + Invite to chat + Zum Chat einladen + No comment provided by engineer. + Invite to group In Gruppe einladen @@ -3811,8 +4137,8 @@ Fehler: %2$@ In diesem Chat ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. In dieser Gruppe ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt. No comment provided by engineer. @@ -3902,11 +4228,11 @@ Das ist Ihr Link für die Gruppe %@! Keep Behalten - No comment provided by engineer. + alert action Keep conversation - Unterhaltung behalten + Chat-Inhalte beibehalten No comment provided by engineer. @@ -3917,7 +4243,7 @@ Das ist Ihr Link für die Gruppe %@! Keep unused invitation? Nicht genutzte Einladung behalten? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4280,16 @@ Das ist Ihr Link für die Gruppe %@! Verlassen swipe action + + Leave chat + Chat verlassen + No comment provided by engineer. + + + Leave chat? + Chat verlassen? + No comment provided by engineer. + Leave group Gruppe verlassen @@ -4004,11 +4340,6 @@ Das ist Ihr Link für die Gruppe %@! Live Nachrichten No comment provided by engineer. - - Local - Lokal - No comment provided by engineer. - Local name Lokaler Name @@ -4029,11 +4360,6 @@ Das ist Ihr Link für die Gruppe %@! Sperr-Modus No comment provided by engineer. - - Make a private connection - Stellen Sie eine private Verbindung her - No comment provided by engineer. - Make one message disappear Eine verschwindende Nachricht verfassen @@ -4044,21 +4370,11 @@ Das ist Ihr Link für die Gruppe %@! Privates Profil erzeugen! No comment provided by engineer. - - 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 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?* - No comment provided by engineer. - Mark deleted for everyone Für Alle als gelöscht markieren @@ -4104,6 +4420,11 @@ Das ist Ihr Link für die Gruppe %@! Mitglied inaktiv item status text + + Member role will be changed to "%@". All chat members will be notified. + Die Rolle des Mitglieds wird auf "%@" geändert. Alle Chat-Mitglieder werden darüber informiert. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Die Mitgliederrolle wird auf "%@" geändert. Alle Mitglieder der Gruppe werden benachrichtigt. @@ -4114,11 +4435,51 @@ Das ist Ihr Link für die Gruppe %@! Die Mitgliederrolle wird auf "%@" geändert. Das Mitglied wird eine neue Einladung erhalten. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + Das Mitglied wird aus dem Chat entfernt. Dies kann nicht rückgängig gemacht werden! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Das Mitglied wird aus der Gruppe entfernt. Dies kann nicht rückgängig gemacht werden! No comment provided by engineer. + + Members can add message reactions. + Gruppenmitglieder können eine Reaktion auf Nachrichten geben. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden) + No comment provided by engineer. + + + Members can send SimpleX links. + Gruppenmitglieder können SimpleX-Links senden. + No comment provided by engineer. + + + Members can send direct messages. + Gruppenmitglieder können Direktnachrichten versenden. + No comment provided by engineer. + + + Members can send disappearing messages. + Gruppenmitglieder können verschwindende Nachrichten senden. + No comment provided by engineer. + + + Members can send files and media. + Gruppenmitglieder können Dateien und Medien senden. + No comment provided by engineer. + + + Members can send voice messages. + Gruppenmitglieder können Sprachnachrichten versenden. + No comment provided by engineer. + Menus Menüs @@ -4169,8 +4530,8 @@ Das ist Ihr Link für die Gruppe %@! In diesem Chat sind Reaktionen auf Nachrichten nicht erlaubt. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. In dieser Gruppe sind Reaktionen auf Nachrichten nicht erlaubt. No comment provided by engineer. @@ -4184,6 +4545,11 @@ Das ist Ihr Link für die Gruppe %@! Nachrichten-Server No comment provided by engineer. + + Message shape + Nachrichten-Form + No comment provided by engineer. + Message source remains private. Die Nachrichtenquelle bleibt privat. @@ -4234,6 +4600,11 @@ Das ist Ihr Link für die Gruppe %@! Gesendete Nachrichten No comment provided by engineer. + + Messages were deleted after you selected them. + Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Nachrichten, Dateien und Anrufe sind durch **Ende-zu-Ende-Verschlüsselung** mit Perfect Forward Secrecy, Ablehnung und Einbruchs-Wiederherstellung geschützt. @@ -4299,9 +4670,9 @@ Das ist Ihr Link für die Gruppe %@! Die Migration wurde abgeschlossen No comment provided by engineer. - - Migrations: %@ - Migrationen: %@ + + Migrations: + Migrationen: No comment provided by engineer. @@ -4329,6 +4700,11 @@ Das ist Ihr Link für die Gruppe %@! Zuverlässigere Netzwerkverbindung. No comment provided by engineer. + + More reliable notifications + Zuverlässigere Benachrichtigungen + No comment provided by engineer. + Most likely this connection is deleted. Wahrscheinlich ist diese Verbindung gelöscht worden. @@ -4364,6 +4740,11 @@ Das ist Ihr Link für die Gruppe %@! Netzwerkverbindung No comment provided by engineer. + + Network decentralization + Dezentralisiertes Netzwerk + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Netzwerk-Fehler - die Nachricht ist nach vielen Sende-Versuchen abgelaufen. @@ -4374,6 +4755,11 @@ Das ist Ihr Link für die Gruppe %@! Netzwerk-Verwaltung No comment provided by engineer. + + Network operator + Netzwerk-Betreiber + No comment provided by engineer. + Network settings Netzwerkeinstellungen @@ -4389,6 +4775,16 @@ Das ist Ihr Link für die Gruppe %@! Neuer Zugangscode No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt + No comment provided by engineer. + New chat Neuer Chat @@ -4409,11 +4805,6 @@ Das ist Ihr Link für die Gruppe %@! Neuer Kontakt: notification - - New database archive - Neues Datenbankarchiv - No comment provided by engineer. - New desktop app! Neue Desktop-App! @@ -4424,6 +4815,11 @@ Das ist Ihr Link für die Gruppe %@! Neuer Anzeigename No comment provided by engineer. + + New events + Neue Ereignisse + notification + New in %@ Neu in %@ @@ -4449,6 +4845,11 @@ Das ist Ihr Link für die Gruppe %@! Neues Passwort… No comment provided by engineer. + + New server + Neuer Server + No comment provided by engineer. + No Nein @@ -4504,21 +4905,71 @@ Das ist Ihr Link für die Gruppe %@! Keine Information - es wird versucht neu zu laden No comment provided by engineer. + + No media & file servers. + Keine Medien- und Dateiserver. + servers error + + + No message servers. + Keine Nachrichten-Server. + servers error + No network connection Keine Netzwerkverbindung No comment provided by engineer. + + No permission to record speech + Keine Genehmigung für Sprach-Aufnahmen + No comment provided by engineer. + + + No permission to record video + Keine Genehmigung für Video-Aufnahmen + No comment provided by engineer. + No permission to record voice message Keine Berechtigung für das Aufnehmen von Sprachnachrichten No comment provided by engineer. + + No push server + Lokal + No comment provided by engineer. + No received or sent files Keine empfangenen oder gesendeten Dateien No comment provided by engineer. + + No servers for private message routing. + Keine Server für privates Nachrichten-Routing. + servers error + + + No servers to receive files. + Keine Server für den Empfang von Dateien. + servers error + + + No servers to receive messages. + Keine Server für den Empfang von Nachrichten. + servers error + + + No servers to send files. + Keine Server für das Versenden von Dateien. + servers error + + + No user identifiers. + Keine Benutzerkennungen. + No comment provided by engineer. + Not compatible! Nicht kompatibel! @@ -4529,6 +4980,11 @@ Das ist Ihr Link für die Gruppe %@! Nichts ausgewählt No comment provided by engineer. + + Nothing to forward! + Es gibt nichts zum Weiterleiten! + alert title + Notifications Benachrichtigungen @@ -4539,6 +4995,11 @@ Das ist Ihr Link für die Gruppe %@! Benachrichtigungen sind deaktiviert! No comment provided by engineer. + + Notifications privacy + Datenschutz für Benachrichtigungen + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5022,13 @@ Das ist Ihr Link für die Gruppe %@! Ok Ok - No comment provided by engineer. + alert button Old database Alte Datenbank No comment provided by engineer. - - Old database archive - Altes Datenbankarchiv - No comment provided by engineer. - One-time invitation link Einmal-Einladungslink @@ -4597,14 +5053,19 @@ Dies erfordert die Aktivierung eines VPNs. Onion-Hosts werden nicht verwendet. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + Nur Chat-Eigentümer können die Präferenzen ändern. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Nur die Endgeräte speichern die Benutzerprofile, Kontakte, Gruppen und Nachrichten, welche über eine **2-Schichten Ende-zu-Ende-Verschlüsselung** gesendet werden. No comment provided by engineer. Only delete conversation - Nur die Unterhaltung löschen + Nur die Chat-Inhalte löschen No comment provided by engineer. @@ -4682,6 +5143,11 @@ Dies erfordert die Aktivierung eines VPNs. Geräte-Einstellungen öffnen No comment provided by engineer. + + Open changes + Änderungen öffnen + No comment provided by engineer. + Open chat Chat öffnen @@ -4692,6 +5158,11 @@ Dies erfordert die Aktivierung eines VPNs. Chat-Konsole öffnen authentication reason + + Open conditions + Nutzungsbedingungen öffnen + No comment provided by engineer. + Open group Gruppe öffnen @@ -4702,26 +5173,26 @@ Dies erfordert die Aktivierung eines VPNs. Migration auf ein anderes Gerät öffnen authentication reason - - Open server settings - Server-Einstellungen öffnen - No comment provided by engineer. - - - Open user profiles - Benutzerprofile öffnen - authentication reason - - - 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 app… App wird geöffnet… No comment provided by engineer. + + Operator + Betreiber + No comment provided by engineer. + + + Operator server + Betreiber-Server + alert title + + + Or import archive file + Oder importieren Sie eine Archiv-Datei + No comment provided by engineer. + Or paste archive link Oder fügen Sie den Archiv-Link ein @@ -4742,15 +5213,22 @@ Dies erfordert die Aktivierung eines VPNs. Oder diesen QR-Code anzeigen No comment provided by engineer. + + Or to share privately + Oder zum privaten Teilen + No comment provided by engineer. + Other Andere No comment provided by engineer. - - Other %@ servers - Andere %@ Server - No comment provided by engineer. + + Other file errors: +%@ + Andere(r) Datei-Fehler: +%@ + alert message PING count @@ -4787,6 +5265,11 @@ Dies erfordert die Aktivierung eines VPNs. Zugangscode eingestellt! No comment provided by engineer. + + Password + Passwort + No comment provided by engineer. + Password to show Passwort anzeigen @@ -4822,13 +5305,8 @@ Dies erfordert die Aktivierung eines VPNs. Ausstehend No comment provided by engineer. - - People can connect to you only via the links you share. - Verbindungen mit Kontakten sind nur über Links möglich, die Sie oder Ihre Kontakte untereinander teilen. - No comment provided by engineer. - - - Periodically + + Periodic Periodisch No comment provided by engineer. @@ -4936,6 +5414,11 @@ Fehler: %@ Polnische Bedienoberfläche No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig @@ -4946,16 +5429,16 @@ Fehler: %@ Den letzten Nachrichtenentwurf, auch mit seinen Anhängen, aufbewahren. No comment provided by engineer. - - Preset server - Voreingestellter Server - No comment provided by engineer. - Preset server address Voreingestellte Serveradresse No comment provided by engineer. + + Preset servers + Voreingestellte Server + No comment provided by engineer. + Preview Vorschau @@ -4971,6 +5454,11 @@ Fehler: %@ Datenschutz & Sicherheit No comment provided by engineer. + + Privacy for your customers. + Schutz der Privatsphäre Ihrer Kunden. + No comment provided by engineer. + Privacy redefined Datenschutz neu definiert @@ -5021,16 +5509,6 @@ Fehler: %@ Profil-Bilder No comment provided by engineer. - - Profile name - Profilname - No comment provided by engineer. - - - Profile name: - Profilname: - No comment provided by engineer. - Profile password Passwort für Profil @@ -5044,7 +5522,7 @@ Fehler: %@ Profile update will be sent to your contacts. Profil-Aktualisierung wird an Ihre Kontakte gesendet. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5133,6 +5611,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Proxy-Server No comment provided by engineer. + + Proxy requires password + Der Proxy benötigt ein Passwort + No comment provided by engineer. + Push notifications Push-Benachrichtigungen @@ -5155,7 +5638,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Reachable chat toolbar - Erreichbare Chat-Symbolleiste + Chat-Symbolleiste unten No comment provided by engineer. @@ -5173,26 +5656,21 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Mehr erfahren 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses) lesen. + 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. No comment provided by engineer. - - Read more in our GitHub repository. - Erfahren Sie in unserem GitHub-Repository mehr dazu. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Erfahren Sie in unserem [GitHub-Repository](https://github.com/simplex-chat/simplex-chat#readme) mehr dazu. @@ -5354,6 +5832,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Entfernen No comment provided by engineer. + + Remove archive? + Archiv entfernen? + No comment provided by engineer. + Remove image Bild entfernen @@ -5504,6 +5987,16 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Aufdecken chat item action + + Review conditions + Nutzungsbedingungen einsehen + No comment provided by engineer. + + + Review later + Später einsehen + No comment provided by engineer. + Revoke Widerrufen @@ -5534,6 +6027,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. SMP-Server No comment provided by engineer. + + SOCKS proxy + SOCKS-Proxy + No comment provided by engineer. + Safely receive files Dateien sicher empfangen @@ -5547,17 +6045,18 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Save Speichern - chat item action + alert button + chat item action Save (and notify contacts) Speichern (und Kontakte benachrichtigen) - No comment provided by engineer. + alert button Save and notify contact Speichern und Kontakt benachrichtigen - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6073,6 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Gruppen-Profil sichern und aktualisieren No comment provided by engineer. - - Save archive - Archiv speichern - No comment provided by engineer. - - - Save auto-accept settings - Einstellungen von "Automatisch akzeptieren" speichern - No comment provided by engineer. - Save group profile Gruppenprofil speichern @@ -5602,7 +6091,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Save preferences? Präferenzen speichern? - No comment provided by engineer. + alert title Save profile password @@ -5617,18 +6106,18 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Save servers? Alle Server speichern? - No comment provided by engineer. - - - Save settings? - Einstellungen speichern? - No comment provided by engineer. + alert title Save welcome message? Begrüßungsmeldung speichern? No comment provided by engineer. + + Save your profile? + Ihr Profil speichern? + alert title + Saved Abgespeichert @@ -5649,6 +6138,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Gespeicherte Nachricht message info title + + Saving %lld messages + Es wird/werden %lld Nachricht(en) gesichert + No comment provided by engineer. + Scale Skalieren @@ -5696,7 +6190,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Search or paste SimpleX link - Suchen oder fügen Sie den SimpleX-Link ein + Suchen oder SimpleX-Link einfügen No comment provided by engineer. @@ -5729,6 +6223,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Auswählen chat item action + + Select chat profile + Chat-Profil auswählen + No comment provided by engineer. + Selected %lld %lld ausgewählt @@ -5819,11 +6318,6 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Benachrichtigungen senden No comment provided by engineer. - - Send notifications: - Benachrichtigungen senden: - No comment provided by engineer. - Send questions and ideas Senden Sie Fragen und Ideen @@ -5847,7 +6341,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Sender cancelled file transfer. Der Absender hat die Dateiübertragung abgebrochen. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5944,6 +6438,16 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Über einen Proxy gesendet No comment provided by engineer. + + Server + Server + No comment provided by engineer. + + + Server added to operator %@. + Der Server wurde dem Betreiber %@ hinzugefügt. + alert message + Server address Server-Adresse @@ -5959,6 +6463,21 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Die Server-Adresse ist nicht mit den Netzwerkeinstellungen kompatibel: %@. No comment provided by engineer. + + Server operator changed. + Der Server-Betreiber wurde geändert. + alert title + + + Server operators + Server-Betreiber + No comment provided by engineer. + + + Server protocol changed. + Das Server-Protokoll wurde geändert. + alert title + Server requires authorization to create queues, check password Um Warteschlangen zu erzeugen benötigt der Server eine Authentifizierung. Bitte überprüfen Sie das Passwort @@ -6064,6 +6583,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Einstellungen No comment provided by engineer. + + Settings were changed. + Die Einstellungen wurden geändert. + alert message + Shape profile images Form der Profil-Bilder @@ -6072,22 +6596,38 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Share Teilen - chat item action + alert action + chat item action Share 1-time link Einmal-Link teilen No comment provided by engineer. + + Share 1-time link with a friend + Den Einmal-Einladungslink mit einem Freund teilen + No comment provided by engineer. + + + Share SimpleX address on social media. + Die SimpleX-Adresse auf sozialen Medien teilen. + No comment provided by engineer. + Share address Adresse teilen No comment provided by engineer. + + Share address publicly + Die Adresse öffentlich teilen + No comment provided by engineer. + Share address with contacts? Die Adresse mit Kontakten teilen? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6639,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Link teilen No comment provided by engineer. + + Share profile + Profil teilen + No comment provided by engineer. + Share this 1-time invite link Teilen Sie diesen Einmal-Einladungslink @@ -6169,6 +6714,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. SimpleX-Adresse No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + SimpleX-Chat und Flux haben vereinbart, die von Flux betriebenen Server in die App aufzunehmen. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Die Sicherheit von SimpleX Chat wurde von Trail of Bits überprüft. @@ -6199,6 +6749,16 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. SimpleX-Adresse No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + Die SimpleX-Adresse und Einmal-Links können sicher über beliebige Messenger geteilt werden. + No comment provided by engineer. + + + SimpleX address or 1-time link? + SimpleX-Adresse oder Einmal-Link? + No comment provided by engineer. + SimpleX contact address SimpleX-Kontaktadressen-Link @@ -6219,8 +6779,8 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. SimpleX-Links chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. In dieser Gruppe sind SimpleX-Links nicht erlaubt. No comment provided by engineer. @@ -6234,6 +6794,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. SimpleX-Einmal-Einladung simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Die SimpleX-Protokolle wurden von Trail of Bits überprüft. + No comment provided by engineer. + Simplified incognito mode Vereinfachter Inkognito-Modus @@ -6264,6 +6829,11 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Weich blur media + + Some app settings were not migrated. + Einige App-Einstellungen wurden nicht migriert. + No comment provided by engineer. + Some file(s) were not exported: Einzelne Datei(en) wurde(n) nicht exportiert: @@ -6279,6 +6849,13 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Während des Imports traten ein paar nicht schwerwiegende Fehler auf: No comment provided by engineer. + + Some servers failed the test: +%@ + Einige Server haben den Test nicht bestanden: +%@ + alert message + Somebody Jemand @@ -6329,11 +6906,6 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Chat beenden No comment provided by engineer. - - Stop chat to enable database actions - Chat beenden, um Datenbankaktionen zu erlauben - 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. Beenden Sie den Chat, um die Chat-Datenbank zu exportieren, zu importieren oder zu löschen. Solange der Chat angehalten ist, können Sie keine Nachrichten empfangen oder senden. @@ -6362,12 +6934,12 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Stop sharing Teilen beenden - No comment provided by engineer. + alert action Stop sharing address? Das Teilen der Adresse beenden? - No comment provided by engineer. + alert title Stopping chat @@ -6404,6 +6976,16 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Unterstützung von SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Während des Anrufs zwischen Audio und Video wechseln + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Das Chat-Profil für Einmal-Einladungen wechseln + No comment provided by engineer. + System System @@ -6439,11 +7021,21 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Sprechblasen-Format + No comment provided by engineer. + Take picture Machen Sie ein Foto No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Tippen Sie im Menü auf SimpleX-Adresse erstellen, um sie später zu erstellen. + No comment provided by engineer. + Tap button Schaltfläche antippen @@ -6502,7 +7094,7 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Tests failed! Tests sind fehlgeschlagen! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7111,6 @@ Aktivieren Sie es in den *Netzwerk & Server* Einstellungen. Dank der Nutzer - Tragen Sie per Weblate bei! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Die erste Plattform ohne Benutzerkennungen – Privat per Design. - No comment provided by engineer. - 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. @@ -6536,6 +7123,11 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Wenn sie Nachrichten oder Kontaktanfragen empfangen, kann Sie die App benachrichtigen - Um dies zu aktivieren, öffnen Sie bitte die Einstellungen. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + Durch Verwendung verschiedener Netzwerk-Betreiber für jede Unterhaltung schützt die App Ihre Privatsphäre. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). Die App wird eine Bestätigung bei Downloads von unbekannten Datei-Servern anfordern (außer bei .onion). @@ -6551,6 +7143,11 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Der von Ihnen gescannte Code ist kein SimpleX-Link-QR-Code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + Diese Verbindung hat das Limit der nicht ausgelieferten Nachrichten erreicht. Ihr Kontakt ist möglicherweise offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Die von Ihnen akzeptierte Verbindung wird abgebrochen! @@ -6571,6 +7168,11 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Die Verschlüsselung funktioniert und ein neues Verschlüsselungsabkommen ist nicht erforderlich. Es kann zu Verbindungsfehlern kommen! No comment provided by engineer. + + The future of messaging + Die nächste Generation von privatem Messaging + No comment provided by engineer. + The hash of the previous message is different. Der Hash der vorherigen Nachricht unterscheidet sich. @@ -6588,7 +7190,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro The messages will be deleted for all members. - Die Nachrichten werden für alle Mitglieder gelöscht werden. + Die Nachrichten werden für alle Gruppenmitglieder gelöscht. No comment provided by engineer. @@ -6596,11 +7198,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Die Nachrichten werden für alle Mitglieder als moderiert gekennzeichnet werden. No comment provided by engineer. - - The next generation of private messaging - Die nächste Generation von privatem Messaging - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden. @@ -6611,6 +7208,21 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Das Profil wird nur mit Ihren Kontakten geteilt. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Dieselben Nutzungsbedingungen gelten auch für den/die Betreiber: **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + Der zweite voreingestellte Netzwerk-Betreiber in der App! + No comment provided by engineer. + The second tick we missed! ✅ Wir haben das zweite Häkchen vermisst! ✅ @@ -6623,7 +7235,12 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro The servers for new connections of your current chat profile **%@**. - Mögliche Server für neue Verbindungen von Ihrem aktuellen Chat-Profil **%@**. + Nachrichten-Server für neue Verbindungen über Ihr aktuelles Chat-Profil **%@**. + No comment provided by engineer. + + + The servers for new files of your current chat profile **%@**. + Medien- und Datei-Server für neue Daten über Ihr aktuelles Chat-Profil **%@**. No comment provided by engineer. @@ -6631,11 +7248,21 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Der von Ihnen eingefügte Text ist kein SimpleX-Link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + Das hochgeladene Datenbank-Archiv wird dauerhaft von den Servern entfernt. + No comment provided by engineer. + Themes Design No comment provided by engineer. + + These conditions will also apply for: **%@**. + Diese Nutzungsbedingungen gelten auch für: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Diese Einstellungen betreffen Ihr aktuelles Profil **%@**. @@ -6736,9 +7363,9 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro Um eine Verbindung mit einem neuen Kontakt zu erstellen 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. - Zum Schutz Ihrer Privatsphäre verwendet SimpleX an Stelle von Benutzerkennungen, die von allen anderen Plattformen verwendet werden, Kennungen für Nachrichtenwarteschlangen, die für jeden Ihrer Kontakte individuell sind. + + To protect against your link being replaced, you can compare contact security codes. + Zum Schutz vor dem Austausch Ihres Links können Sie die Sicherheitscodes Ihrer Kontakte vergleichen. No comment provided by engineer. @@ -6758,6 +7385,26 @@ You will be prompted to complete authentication before this feature is enabled.< Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funktion aktiviert wird. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Zum Schutz Ihrer Privatsphäre verwendet SimpleX an Stelle von Benutzerkennungen, die von allen anderen Plattformen verwendet werden, Kennungen für Nachrichtenwarteschlangen, die für jeden Ihrer Kontakte individuell sind. + No comment provided by engineer. + + + To receive + Für den Empfang + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Bitte erteilen Sie für Sprach-Aufnahmen die Genehmigung das Mikrofon zu nutzen. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Bitte erteilen Sie für Video-Aufnahmen die Genehmigung die Kamera zu nutzen. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können. @@ -6768,11 +7415,21 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Ihre Chat-Profile** ein, um Ihr verborgenes Profil zu sehen. No comment provided by engineer. + + To send + Für das Senden + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Um sofortige Push-Benachrichtigungen zu unterstützen, muss die Chat-Datenbank migriert werden. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + Um die Server von **%@** zu nutzen, müssen Sie dessen Nutzungsbedingungen akzeptieren. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Um die Ende-zu-Ende-Verschlüsselung mit Ihrem Kontakt zu überprüfen, müssen Sie den Sicherheitscode in Ihren Apps vergleichen oder scannen. @@ -6863,6 +7520,11 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Mitglied freigeben? No comment provided by engineer. + + Undelivered messages + Nicht ausgelieferte Nachrichten + No comment provided by engineer. + Unexpected migration state Unerwarteter Migrationsstatus @@ -6911,7 +7573,7 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt Unknown servers! Unbekannte Server! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7682,21 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Archiv wird hochgeladen No comment provided by engineer. + + Use %@ + Verwende %@ + No comment provided by engineer. + Use .onion hosts Verwende .onion-Hosts No comment provided by engineer. + + Use SOCKS proxy + SOCKS-Proxy nutzen + No comment provided by engineer. + Use SimpleX Chat servers? Verwenden Sie SimpleX-Chat-Server? @@ -7040,6 +7712,16 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Aktuelles Profil nutzen No comment provided by engineer. + + Use for files + Für Dateien verwenden + No comment provided by engineer. + + + Use for messages + Für Nachrichten verwenden + No comment provided by engineer. + Use for new connections Für neue Verbindungen nutzen @@ -7080,6 +7762,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Server nutzen No comment provided by engineer. + + Use servers + Verwende Server + No comment provided by engineer. + Use the app while in the call. Die App kann während eines Anrufs genutzt werden. @@ -7087,12 +7774,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Use the app with one hand. - Die App mit einer Hand nutzen. - No comment provided by engineer. - - - User profile - Benutzerprofil + Die App mit einer Hand bedienen. No comment provided by engineer. @@ -7100,6 +7782,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Benutzer-Auswahl No comment provided by engineer. + + Username + Benutzername + No comment provided by engineer. + Using SimpleX Chat servers. Verwendung von SimpleX-Chat-Servern. @@ -7170,11 +7857,21 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Videos und Dateien bis zu 1GB No comment provided by engineer. + + View conditions + Nutzungsbedingungen anschauen + No comment provided by engineer. + View security code Schauen Sie sich den Sicherheitscode an No comment provided by engineer. + + View updated conditions + Aktualisierte Nutzungsbedingungen anschauen + No comment provided by engineer. + Visible history Sichtbarer Nachrichtenverlauf @@ -7190,8 +7887,8 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s In diesem Chat sind Sprachnachrichten nicht erlaubt. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. In dieser Gruppe sind Sprachnachrichten nicht erlaubt. No comment provided by engineer. @@ -7285,9 +7982,9 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Bei der Verbindung über Audio- und Video-Anrufe. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Wenn Personen eine Verbindung anfordern, können Sie diese annehmen oder ablehnen. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Wenn mehrere Netzwerk-Betreiber aktiviert sind, hat keiner von ihnen Metadaten, um zu erfahren, wer mit wem kommuniziert. No comment provided by engineer. @@ -7333,7 +8030,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8057,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s XFTP-Server No comment provided by engineer. - - You - Profil - No comment provided by engineer. - You **must not** use the same database on two devices. Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen. @@ -7390,6 +8082,11 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s Sie sind bereits mit %@ verbunden. No comment provided by engineer. + + You are already connected with %@. + Sie sind bereits mit %@ verbunden. + No comment provided by engineer. + You are already connecting to %@. Sie sind bereits mit %@ verbunden. @@ -7452,6 +8149,16 @@ Verbindungsanfrage wiederholen? Kann von Ihnen in den Erscheinungsbild-Einstellungen geändert werden. No comment provided by engineer. + + You can configure operators in Network & servers settings. + Sie können die Betreiber in den Netzwerk- und Servereinstellungen konfigurieren. + No comment provided by engineer. + + + You can configure servers via settings. + Sie können die Server über die Einstellungen konfigurieren. + No comment provided by engineer. + You can create it later Sie können dies später erstellen @@ -7492,6 +8199,11 @@ Verbindungsanfrage wiederholen? Sie können aus den archivierten Kontakten heraus Nachrichten an %@ versenden. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + Sie können einen Verbindungsnamen festlegen, um sich zu merken, mit wem der Link geteilt wurde. + No comment provided by engineer. + You can set lock screen notification preview via settings. Über die Geräte-Einstellungen können Sie die Benachrichtigungsvorschau im Sperrbildschirm erlauben. @@ -7507,11 +8219,6 @@ Verbindungsanfrage wiederholen? Sie können diese Adresse mit Ihren Kontakten teilen, um sie mit **%@** verbinden zu lassen. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Sie können Ihre Adresse als Link oder als QR-Code teilen – Jede Person kann sich darüber mit Ihnen verbinden. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Sie können den Chat über die App-Einstellungen / Datenbank oder durch Neustart der App starten @@ -7519,7 +8226,7 @@ Verbindungsanfrage wiederholen? You can still view conversation with %@ in the list of chats. - Sie können in der Chatliste weiterhin die Unterhaltung mit %@ einsehen. + Sie können in der Chat-Liste weiterhin die Unterhaltung mit %@ einsehen. No comment provided by engineer. @@ -7535,23 +8242,23 @@ Verbindungsanfrage wiederholen? 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. + alert message You can't send messages! Sie können keine Nachrichten versenden! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Sie können selbst festlegen, über welche Server Sie Ihre Nachrichten **empfangen** und an Ihre Kontakte **senden** wollen. - No comment provided by engineer. - You could not be verified; please try again. Sie konnten nicht überprüft werden; bitte versuchen Sie es erneut. No comment provided by engineer. + + You decide who can connect. + Sie entscheiden, wer sich mit Ihnen verbinden kann. + No comment provided by engineer. + You have already requested connection via this address! Sie haben über diese Adresse bereits eine Verbindung beantragt! @@ -7654,6 +8361,11 @@ Verbindungsanfrage wiederholen? 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 chat. Chat history will be preserved. + Sie werden von diesem Chat keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten. + 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 Nachrichtenverlauf wird beibehalten. @@ -7674,11 +8386,6 @@ Verbindungsanfrage wiederholen? Sie verwenden ein Inkognito-Profil für diese Gruppe. Um zu verhindern, dass Sie Ihr Hauptprofil teilen, ist in diesem Fall das Einladen von Kontakten nicht erlaubt No comment provided by engineer. - - Your %@ servers - Ihre %@-Server - No comment provided by engineer. - Your ICE servers Ihre ICE-Server @@ -7694,11 +8401,6 @@ Verbindungsanfrage wiederholen? Ihre SimpleX-Adresse No comment provided by engineer. - - Your XFTP servers - Ihre XFTP-Server - No comment provided by engineer. - Your calls Anrufe @@ -7714,11 +8416,21 @@ Verbindungsanfrage wiederholen? Ihre Chat-Datenbank ist nicht verschlüsselt. Bitte legen Sie ein Passwort fest, um sie zu schützen. No comment provided by engineer. + + Your chat preferences + Ihre Chat-Präferenzen + alert title + Your chat profiles Ihre Chat-Profile No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Ihre Verbindung wurde auf %@ verschoben. Während Sie auf das Profil weitergeleitet wurden trat aber ein unerwarteter Fehler auf. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Ihr Kontakt hat eine Datei gesendet, die größer ist als die derzeit unterstützte maximale Größe (%@). @@ -7734,6 +8446,11 @@ Verbindungsanfrage wiederholen? Ihre Kontakte bleiben weiterhin verbunden. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Ihre Anmeldeinformationen können unverschlüsselt versendet werden. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT. @@ -7764,13 +8481,16 @@ Verbindungsanfrage wiederholen? Ihr Profil **%@** wird geteilt. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. -SimpleX-Server können Ihr Profil nicht einsehen. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Ihr Profil wurde geändert. Wenn Sie es speichern, wird das aktualisierte Profil an alle Ihre Kontakte gesendet. + alert message + Your profile, contacts and delivered messages are stored on your device. Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert. @@ -7781,16 +8501,16 @@ SimpleX-Server können Ihr Profil nicht einsehen. Ihr Zufallsprofil No comment provided by engineer. - - Your server - Ihr Server - No comment provided by engineer. - Your server address Ihre Serveradresse No comment provided by engineer. + + Your servers + Ihre Server + No comment provided by engineer. + Your settings Einstellungen @@ -7831,6 +8551,11 @@ SimpleX-Server können Ihr Profil nicht einsehen. Anruf angenommen call status + + accepted invitation + Einladung akzeptiert + chat list item title + admin Admin @@ -8019,7 +8744,7 @@ SimpleX-Server können Ihr Profil nicht einsehen. connecting… Verbinde… - chat list item title + No comment provided by engineer. connection established @@ -8208,7 +8933,12 @@ SimpleX-Server können Ihr Profil nicht einsehen. expired - abgelaufen + Abgelaufen + No comment provided by engineer. + + + for better metadata privacy. + für einen besseren Metadatenschutz. No comment provided by engineer. @@ -8440,7 +9170,7 @@ SimpleX-Server können Ihr Profil nicht einsehen. other - andere + Andere No comment provided by engineer. @@ -8508,6 +9238,11 @@ SimpleX-Server können Ihr Profil nicht einsehen. hat Sie aus der Gruppe entfernt rcv group event chat item + + requested to connect + Zur Verbindung aufgefordert + chat list item title + saved abgespeichert @@ -8833,6 +9568,38 @@ Zuletzt empfangene Nachricht: %2$@ + +
+ +
+ + + %d new events + %d neue Ereignisse + notification body + + + From: %@ + Von: %@ + notification body + + + New events + Neue Ereignisse + notification + + + New messages + Neue Nachrichten + notification + + + New messages in %d chats + Neue Nachrichten in %d Chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/de.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/de.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 b8432a33b6..b601d1fa74 100644 --- a/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff +++ b/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff @@ -186,20 +186,16 @@ Available in v5.1 ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - No comment provided by engineer. - **Create link / QR code** for your contact to use. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. No comment provided by engineer. @@ -210,8 +206,8 @@ Available in v5.1 **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. No comment provided by engineer. @@ -1128,8 +1124,8 @@ Available in v5.1 Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1144,8 +1140,8 @@ Available in v5.1 Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1580,16 +1576,16 @@ Available in v5.1 Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1708,8 +1704,8 @@ Available in v5.1 Immediately No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1821,8 +1817,8 @@ Available in v5.1 Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -2016,8 +2012,8 @@ Available in v5.1 Migration is completed No comment provided by engineer. - - Migrations: %@ + + Migrations: No comment provided by engineer. @@ -2174,8 +2170,8 @@ Available in v5.1 Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2234,8 +2230,8 @@ Available in v5.1 Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2290,8 +2286,8 @@ Available in v5.1 Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -2994,8 +2990,8 @@ Available in v5.1 Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -3039,8 +3035,8 @@ It can happen because of some bug or when the connection is compromised.The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -3111,8 +3107,8 @@ It can happen because of some bug or when the connection is compromised.To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -3337,8 +3333,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -3478,10 +3474,6 @@ SimpleX Lock must be enabled. You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. @@ -4200,7 +4192,7 @@ SimpleX servers cannot see your profile. ## In reply to - ## Ως απαντηση σε + ## Ως απάντηση σε copied message info 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 c217793f03..cebd6c90d1 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ is verified No comment provided by engineer. + + %@ server + %@ server + No comment provided by engineer. + + + %@ servers + %@ servers + No comment provided by engineer. + %@ uploaded %@ uploaded @@ -137,6 +132,11 @@ %@ wants to connect! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ and %lld members @@ -157,11 +157,36 @@ %d days time interval + + %d file(s) are still being downloaded. + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d hours time interval + + %d messages not forwarded + %d messages not forwarded + alert title + %d min %d min @@ -322,14 +347,9 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. - **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 or link for your contact. - **Add new contact**: to create your one-time QR Code or link for your contact. + + **Create 1-time link**: to create and share a new invitation link. + **Create 1-time link**: to create and share a new invitation link. No comment provided by engineer. @@ -337,14 +357,14 @@ **Create group**: to create a new group. 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. - **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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. 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). - **Most private**: do not use SimpleX Chat notifications server, check messages periodically in the background (depends on how often you use the app). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. No comment provided by engineer. @@ -357,9 +377,14 @@ **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. - **Recommended**: device token and notifications are sent to SimpleX Chat notification server, but not the message content, size or who it is from. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. + No comment provided by engineer. + + + **Scan / Paste link**: to connect via a link you received. + **Scan / Paste link**: to connect via a link you received. No comment provided by engineer. @@ -468,6 +493,16 @@ 1 week time interval + + 1-time link + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 minutes @@ -537,19 +572,14 @@ Abort changing address? No comment provided by engineer. - - About SimpleX - About SimpleX - No comment provided by engineer. - About SimpleX Chat About SimpleX Chat No comment provided by engineer. - - About SimpleX address - About SimpleX address + + About operators + About operators No comment provided by engineer. @@ -564,6 +594,11 @@ accept incoming call via notification swipe action + + Accept conditions + Accept conditions + No comment provided by engineer. + Accept connection request? Accept connection request? @@ -580,6 +615,11 @@ accept contact request via notification swipe action + + Accepted conditions + Accepted conditions + No comment provided by engineer. + Acknowledged Acknowledged @@ -600,14 +640,9 @@ 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 - Add contact - No comment provided by engineer. - - - Add preset servers - Add preset servers + + Add friends + Add friends No comment provided by engineer. @@ -625,6 +660,11 @@ Add servers by scanning QR codes. No comment provided by engineer. + + Add team members + Add team members + No comment provided by engineer. + Add to another device Add to another device @@ -635,6 +675,21 @@ Add welcome message No comment provided by engineer. + + Add your team members to the conversations. + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + Added media & file servers + No comment provided by engineer. + + + Added message servers + Added message servers + No comment provided by engineer. + Additional accent Additional accent @@ -660,6 +715,16 @@ Address change will be aborted. Old receiving address will be used. No comment provided by engineer. + + Address or 1-time link? + Address or 1-time link? + No comment provided by engineer. + + + Address settings + Address settings + No comment provided by engineer. + Admins can block a member for all. Admins can block a member for all. @@ -695,9 +760,9 @@ All data is erased when it is entered. No comment provided by engineer. - - All data is private to your device. - All data is private to your device. + + All data is kept private on your device. + All data is kept private on your device. No comment provided by engineer. @@ -705,6 +770,11 @@ All group members will remain connected. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! All messages will be deleted - this cannot be undone! @@ -723,7 +793,7 @@ All profiles All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -885,6 +955,11 @@ Answer call No comment provided by engineer. + + Anybody can host servers. + Anybody can host servers. + No comment provided by engineer. + App build: %@ App build: %@ @@ -915,6 +990,11 @@ App passcode is replaced with self-destruct passcode. No comment provided by engineer. + + App session + App session + No comment provided by engineer. + App version App version @@ -1020,6 +1100,11 @@ Auto-accept images No comment provided by engineer. + + Auto-accept settings + Auto-accept settings + alert title + Back Back @@ -1045,11 +1130,21 @@ Bad message hash No comment provided by engineer. + + Better calls + Better calls + No comment provided by engineer. + Better groups Better groups No comment provided by engineer. + + Better message dates. + Better message dates. + No comment provided by engineer. + Better messages Better messages @@ -1060,6 +1155,21 @@ Better networking No comment provided by engineer. + + Better notifications + Better notifications + No comment provided by engineer. + + + Better security ✅ + Better security ✅ + No comment provided by engineer. + + + Better user experience + Better user experience + No comment provided by engineer. + Black Black @@ -1140,6 +1250,16 @@ Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Business address + No comment provided by engineer. + + + Business chats + Business chats + 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). By chat profile (default) or [by connection](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1193,7 +1313,8 @@ Cancel Cancel - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1334,7 @@ Cannot receive file Cannot receive file - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1351,11 @@ Change No comment provided by engineer. + + Change chat profiles + Change chat profiles + authentication reason + Change database passphrase? Change database passphrase? @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Chat archive + + Chat + Chat + No comment provided by engineer. + + + Chat already exists + Chat already exists + No comment provided by engineer. + + + Chat already exists! + Chat already exists! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Chat preferences No comment provided by engineer. + + Chat preferences were changed. + Chat preferences were changed. + alert message + + + Chat profile + Chat profile + No comment provided by engineer. + Chat theme Chat theme No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Chats No comment provided by engineer. + + Check messages every 20 min. + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Check server address and try again. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1441,16 +1607,56 @@ Completed No comment provided by engineer. + + Conditions accepted on: %@. + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers Configure ICE servers No comment provided by engineer. - - Configured %@ servers - Configured %@ servers - No comment provided by engineer. - Confirm Confirm @@ -1640,6 +1846,11 @@ This is your own one-time link! Connection request sent! No comment provided by engineer. + + Connection security + Connection security + No comment provided by engineer. + Connection terminated Connection terminated @@ -1740,6 +1951,11 @@ This is your own one-time link! Core version: v%@ No comment provided by engineer. + + Corner + Corner + No comment provided by engineer. + Correct name to %@? Correct name to %@? @@ -1750,6 +1966,11 @@ This is your own one-time link! Create No comment provided by engineer. + + Create 1-time link + Create 1-time link + No comment provided by engineer. + Create SimpleX address Create SimpleX address @@ -1760,11 +1981,6 @@ This is your own one-time link! Create a group using a random profile. No comment provided by engineer. - - Create an address to let people connect with you. - Create an address to let people connect with you. - No comment provided by engineer. - Create file Create file @@ -1825,11 +2041,6 @@ This is your own one-time link! Created at: %@ copied message info - - Created on %@ - Created on %@ - No comment provided by engineer. - Creating archive link Creating archive link @@ -1845,6 +2056,11 @@ This is your own one-time link! Current Passcode No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Current passphrase… @@ -1865,6 +2081,11 @@ This is your own one-time link! Custom time No comment provided by engineer. + + Customizable message shape. + Customizable message shape. + No comment provided by engineer. + Customize theme Customize theme @@ -1996,7 +2217,8 @@ This is your own one-time link! Delete Delete - chat item action + alert action + chat item action swipe action @@ -2034,14 +2256,9 @@ This is your own one-time link! Delete and notify contact No comment provided by engineer. - - Delete archive - Delete archive - No comment provided by engineer. - - - Delete chat archive? - Delete chat archive? + + Delete chat + Delete chat No comment provided by engineer. @@ -2054,6 +2271,11 @@ This is your own one-time link! Delete chat profile? No comment provided by engineer. + + Delete chat? + Delete chat? + No comment provided by engineer. + Delete connection Delete connection @@ -2159,6 +2381,11 @@ This is your own one-time link! Delete old database? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? Delete pending connection? @@ -2209,6 +2436,11 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Delivery @@ -2309,9 +2541,14 @@ This is your own one-time link! Direct messages chat feature - - Direct messages between members are prohibited in this group. - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. + Direct messages between members are prohibited. No comment provided by engineer. @@ -2349,9 +2586,9 @@ This is your own one-time link! Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. + Disappearing messages are prohibited. No comment provided by engineer. @@ -2409,6 +2646,11 @@ This is your own one-time link! Do not send history to new members. No comment provided by engineer. + + Do not use credentials with proxy. + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address Don't create address @@ -2432,7 +2674,8 @@ This is your own one-time link! Download Download - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ This is your own one-time link! Download file server test step + + Download files + Download files + alert action + Downloaded Downloaded @@ -2479,6 +2727,11 @@ This is your own one-time link! Duration No comment provided by engineer. + + E2E encrypted notifications. + E2E encrypted notifications. + No comment provided by engineer. + Edit Edit @@ -2499,6 +2752,11 @@ This is your own one-time link! Enable (keep overrides) No comment provided by engineer. + + Enable Flux + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Enable SimpleX Lock @@ -2704,26 +2962,36 @@ This is your own one-time link! Error aborting address change No comment provided by engineer. + + Error accepting conditions + Error accepting conditions + alert title + Error accepting contact request Error accepting contact request No comment provided by engineer. - - Error accessing database file - Error accessing database file - No comment provided by engineer. - Error adding member(s) Error adding member(s) No comment provided by engineer. + + Error adding server + Error adding server + alert title + Error changing address Error changing address No comment provided by engineer. + + Error changing connection profile + Error changing connection profile + No comment provided by engineer. + Error changing role Error changing role @@ -2734,6 +3002,11 @@ This is your own one-time link! Error changing setting No comment provided by engineer. + + Error changing to incognito! + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Error connecting to forwarding server %@. Please try later. @@ -2849,9 +3122,14 @@ This is your own one-time link! Error joining group No comment provided by engineer. - - Error loading %@ servers - Error loading %@ servers + + Error loading servers + Error loading servers + alert title + + + Error migrating settings + Error migrating settings No comment provided by engineer. @@ -2862,7 +3140,7 @@ This is your own one-time link! Error receiving file Error receiving file - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3162,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - Error saving %@ servers - No comment provided by engineer. - Error saving ICE servers Error saving ICE servers @@ -2909,6 +3182,11 @@ This is your own one-time link! Error saving passphrase to keychain No comment provided by engineer. + + Error saving servers + Error saving servers + alert title + Error saving settings Error saving settings @@ -2954,10 +3232,15 @@ This is your own one-time link! Error stopping chat No comment provided by engineer. + + Error switching profile + Error switching profile + No comment provided by engineer. + Error switching profile! Error switching profile! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3257,11 @@ This is your own one-time link! Error updating message No comment provided by engineer. + + Error updating server + Error updating server + alert title + Error updating settings Error updating settings @@ -3002,8 +3290,7 @@ This is your own one-time link! Error: %@ Error: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3307,11 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + Errors in servers configuration. + servers error + Even when disabled in the conversation. Even when disabled in the conversation. @@ -3090,6 +3382,13 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. File not found - most likely file was deleted or cancelled. @@ -3145,9 +3444,9 @@ This is your own one-time link! Files and media chat feature - - Files and media are prohibited in this group. - Files and media are prohibited in this group. + + Files and media are prohibited. + Files and media are prohibited. No comment provided by engineer. @@ -3215,21 +3514,61 @@ This is your own one-time link! Fix not supported by group member No comment provided by engineer. + + For chat profile %@: + For chat profile %@: + servers error + For console For console No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + For private routing + No comment provided by engineer. + + + For social media + For social media + No comment provided by engineer. + Forward Forward chat item action + + Forward %d message(s)? + Forward %d message(s)? + alert title + Forward and save messages Forward and save messages No comment provided by engineer. + + Forward messages + Forward messages + alert action + + + Forward messages without files? + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded Forwarded @@ -3240,6 +3579,11 @@ This is your own one-time link! Forwarded from No comment provided by engineer. + + Forwarding %lld messages + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. Forwarding server %@ failed to connect to destination server %@. Please try later. @@ -3289,11 +3633,6 @@ Error: %2$@ Full name (optional) No comment provided by engineer. - - Full name: - Full name: - No comment provided by engineer. - Fully decentralized – visible only to members. Fully decentralized – visible only to members. @@ -3379,41 +3718,6 @@ Error: %2$@ Group links No comment provided by engineer. - - Group members can add message reactions. - Group members can add message reactions. - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - Group members can irreversibly delete sent messages. (24 hours) - No comment provided by engineer. - - - Group members can send SimpleX links. - Group members can send SimpleX links. - No comment provided by engineer. - - - Group members can send direct messages. - Group members can send direct messages. - No comment provided by engineer. - - - Group members can send disappearing messages. - Group members can send disappearing messages. - No comment provided by engineer. - - - Group members can send files and media. - Group members can send files and media. - No comment provided by engineer. - - - Group members can send voice messages. - Group members can send voice messages. - No comment provided by engineer. - Group message: Group message: @@ -3509,9 +3813,14 @@ Error: %2$@ How SimpleX works No comment provided by engineer. - - How it works - How it works + + How it affects privacy + How it affects privacy + No comment provided by engineer. + + + How it helps privacy + How it helps privacy No comment provided by engineer. @@ -3539,6 +3848,11 @@ Error: %2$@ ICE servers (one per line) No comment provided by engineer. + + IP address + IP address + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. If you can't meet in person, show QR code in a video call, or share the link. @@ -3579,9 +3893,9 @@ Error: %2$@ Immediately No comment provided by engineer. - - Immune to spam and abuse - Immune to spam and abuse + + Immune to spam + Immune to spam No comment provided by engineer. @@ -3614,6 +3928,13 @@ Error: %2$@ Importing archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery Improved message delivery @@ -3714,6 +4035,11 @@ Error: %2$@ Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Instant + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4047,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Instantly - No comment provided by engineer. - Interface Interface @@ -3774,7 +4095,7 @@ Error: %2$@ Invalid server address! Invalid server address! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4117,11 @@ Error: %2$@ Invite members No comment provided by engineer. + + Invite to chat + Invite to chat + No comment provided by engineer. + Invite to group Invite to group @@ -3811,9 +4137,9 @@ Error: %2$@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -3902,7 +4228,7 @@ This is your link for group %@! Keep Keep - No comment provided by engineer. + alert action Keep conversation @@ -3917,7 +4243,7 @@ This is your link for group %@! Keep unused invitation? Keep unused invitation? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4280,16 @@ This is your link for group %@! Leave swipe action + + Leave chat + Leave chat + No comment provided by engineer. + + + Leave chat? + Leave chat? + No comment provided by engineer. + Leave group Leave group @@ -4004,11 +4340,6 @@ This is your link for group %@! Live messages No comment provided by engineer. - - Local - Local - No comment provided by engineer. - Local name Local name @@ -4029,11 +4360,6 @@ This is your link for group %@! Lock mode No comment provided by engineer. - - Make a private connection - Make a private connection - No comment provided by engineer. - Make one message disappear Make one message disappear @@ -4044,21 +4370,11 @@ This is your link for group %@! Make profile private! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - No comment provided by engineer. - Mark deleted for everyone Mark deleted for everyone @@ -4104,6 +4420,11 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Member role will be changed to "%@". All group members will be notified. @@ -4114,11 +4435,51 @@ This is your link for group %@! Member role will be changed to "%@". The member will receive a new invitation. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Member will be removed from group - this cannot be undone! No comment provided by engineer. + + Members can add message reactions. + Members can add message reactions. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Members can irreversibly delete sent messages. (24 hours) + No comment provided by engineer. + + + Members can send SimpleX links. + Members can send SimpleX links. + No comment provided by engineer. + + + Members can send direct messages. + Members can send direct messages. + No comment provided by engineer. + + + Members can send disappearing messages. + Members can send disappearing messages. + No comment provided by engineer. + + + Members can send files and media. + Members can send files and media. + No comment provided by engineer. + + + Members can send voice messages. + Members can send voice messages. + No comment provided by engineer. + Menus Menus @@ -4169,9 +4530,9 @@ This is your link for group %@! Message reactions are prohibited in this chat. No comment provided by engineer. - - Message reactions are prohibited in this group. - Message reactions are prohibited in this group. + + Message reactions are prohibited. + Message reactions are prohibited. No comment provided by engineer. @@ -4184,6 +4545,11 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + Message shape + No comment provided by engineer. + Message source remains private. Message source remains private. @@ -4234,6 +4600,11 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. @@ -4299,9 +4670,9 @@ This is your link for group %@! Migration is completed No comment provided by engineer. - - Migrations: %@ - Migrations: %@ + + Migrations: + Migrations: No comment provided by engineer. @@ -4329,6 +4700,11 @@ This is your link for group %@! More reliable network connection. No comment provided by engineer. + + More reliable notifications + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Most likely this connection is deleted. @@ -4364,6 +4740,11 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network decentralization + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Network issues - message expired after many attempts to send it. @@ -4374,6 +4755,11 @@ This is your link for group %@! Network management No comment provided by engineer. + + Network operator + Network operator + No comment provided by engineer. + Network settings Network settings @@ -4389,6 +4775,16 @@ This is your link for group %@! New Passcode No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat New chat @@ -4409,11 +4805,6 @@ This is your link for group %@! New contact: notification - - New database archive - New database archive - No comment provided by engineer. - New desktop app! New desktop app! @@ -4424,6 +4815,11 @@ This is your link for group %@! New display name No comment provided by engineer. + + New events + New events + notification + New in %@ New in %@ @@ -4449,6 +4845,11 @@ This is your link for group %@! New passphrase… No comment provided by engineer. + + New server + New server + No comment provided by engineer. + No No @@ -4504,21 +4905,71 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + No media & file servers. + servers error + + + No message servers. + No message servers. + servers error + No network connection No network connection No comment provided by engineer. + + No permission to record speech + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No permission to record video + No comment provided by engineer. + No permission to record voice message No permission to record voice message No comment provided by engineer. + + No push server + No push server + No comment provided by engineer. + No received or sent files No received or sent files No comment provided by engineer. + + No servers for private message routing. + No servers for private message routing. + servers error + + + No servers to receive files. + No servers to receive files. + servers error + + + No servers to receive messages. + No servers to receive messages. + servers error + + + No servers to send files. + No servers to send files. + servers error + + + No user identifiers. + No user identifiers. + No comment provided by engineer. + Not compatible! Not compatible! @@ -4529,6 +4980,11 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + Nothing to forward! + alert title + Notifications Notifications @@ -4539,6 +4995,11 @@ This is your link for group %@! Notifications are disabled! No comment provided by engineer. + + Notifications privacy + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5022,13 @@ This is your link for group %@! Ok Ok - No comment provided by engineer. + alert button Old database Old database No comment provided by engineer. - - Old database archive - Old database archive - No comment provided by engineer. - One-time invitation link One-time invitation link @@ -4597,9 +5053,14 @@ Requires compatible VPN. Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -4682,6 +5143,11 @@ Requires compatible VPN. Open Settings No comment provided by engineer. + + Open changes + Open changes + No comment provided by engineer. + Open chat Open chat @@ -4692,6 +5158,11 @@ Requires compatible VPN. Open chat console authentication reason + + Open conditions + Open conditions + No comment provided by engineer. + Open group Open group @@ -4702,26 +5173,26 @@ Requires compatible VPN. Open migration to another device authentication reason - - Open server settings - Open server settings - No comment provided by engineer. - - - Open user profiles - Open user profiles - authentication reason - - - Open-source protocol and code – anybody can run the servers. - Open-source protocol and code – anybody can run the servers. - No comment provided by engineer. - Opening app… Opening app… No comment provided by engineer. + + Operator + Operator + No comment provided by engineer. + + + Operator server + Operator server + alert title + + + Or import archive file + Or import archive file + No comment provided by engineer. + Or paste archive link Or paste archive link @@ -4742,15 +5213,22 @@ Requires compatible VPN. Or show this code No comment provided by engineer. + + Or to share privately + Or to share privately + No comment provided by engineer. + Other Other No comment provided by engineer. - - Other %@ servers - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + Other file errors: +%@ + alert message PING count @@ -4787,6 +5265,11 @@ Requires compatible VPN. Passcode set! No comment provided by engineer. + + Password + Password + No comment provided by engineer. + Password to show Password to show @@ -4822,14 +5305,9 @@ Requires compatible VPN. Pending No comment provided by engineer. - - People can connect to you only via the links you share. - People can connect to you only via the links you share. - No comment provided by engineer. - - - Periodically - Periodically + + Periodic + Periodic No comment provided by engineer. @@ -4936,6 +5414,11 @@ Error: %@ Polish interface No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Possibly, certificate fingerprint in server address is incorrect @@ -4946,16 +5429,16 @@ Error: %@ Preserve the last message draft, with attachments. No comment provided by engineer. - - Preset server - Preset server - No comment provided by engineer. - Preset server address Preset server address No comment provided by engineer. + + Preset servers + Preset servers + No comment provided by engineer. + Preview Preview @@ -4971,6 +5454,11 @@ Error: %@ Privacy & security No comment provided by engineer. + + Privacy for your customers. + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Privacy redefined @@ -5021,16 +5509,6 @@ Error: %@ Profile images No comment provided by engineer. - - Profile name - Profile name - No comment provided by engineer. - - - Profile name: - Profile name: - No comment provided by engineer. - Profile password Profile password @@ -5044,7 +5522,7 @@ Error: %@ Profile update will be sent to your contacts. Profile update will be sent to your contacts. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5133,6 +5611,11 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + Proxy requires password + No comment provided by engineer. + Push notifications Push notifications @@ -5173,26 +5656,21 @@ Enable in *Network & servers* settings. Read more No comment provided by engineer. - - Read more in [User Guide](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). - No comment provided by engineer. - Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode). Read more in [User Guide](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + No comment provided by engineer. + Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). No comment provided by engineer. - - Read more in our GitHub repository. - Read more in our GitHub repository. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). @@ -5354,6 +5832,11 @@ Enable in *Network & servers* settings. Remove No comment provided by engineer. + + Remove archive? + Remove archive? + No comment provided by engineer. + Remove image Remove image @@ -5504,6 +5987,16 @@ Enable in *Network & servers* settings. Reveal chat item action + + Review conditions + Review conditions + No comment provided by engineer. + + + Review later + Review later + No comment provided by engineer. + Revoke Revoke @@ -5534,6 +6027,11 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + SOCKS proxy + No comment provided by engineer. + Safely receive files Safely receive files @@ -5547,17 +6045,18 @@ Enable in *Network & servers* settings. Save Save - chat item action + alert button + chat item action Save (and notify contacts) Save (and notify contacts) - No comment provided by engineer. + alert button Save and notify contact Save and notify contact - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6073,6 @@ Enable in *Network & servers* settings. Save and update group profile No comment provided by engineer. - - Save archive - Save archive - No comment provided by engineer. - - - Save auto-accept settings - Save auto-accept settings - No comment provided by engineer. - Save group profile Save group profile @@ -5602,7 +6091,7 @@ Enable in *Network & servers* settings. Save preferences? Save preferences? - No comment provided by engineer. + alert title Save profile password @@ -5617,18 +6106,18 @@ Enable in *Network & servers* settings. Save servers? Save servers? - No comment provided by engineer. - - - Save settings? - Save settings? - No comment provided by engineer. + alert title Save welcome message? Save welcome message? No comment provided by engineer. + + Save your profile? + Save your profile? + alert title + Saved Saved @@ -5649,6 +6138,11 @@ Enable in *Network & servers* settings. Saved message message info title + + Saving %lld messages + Saving %lld messages + No comment provided by engineer. + Scale Scale @@ -5729,6 +6223,11 @@ Enable in *Network & servers* settings. Select chat item action + + Select chat profile + Select chat profile + No comment provided by engineer. + Selected %lld Selected %lld @@ -5819,11 +6318,6 @@ Enable in *Network & servers* settings. Send notifications No comment provided by engineer. - - Send notifications: - Send notifications: - No comment provided by engineer. - Send questions and ideas Send questions and ideas @@ -5847,7 +6341,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Sender cancelled file transfer. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5944,6 +6438,16 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + Server + No comment provided by engineer. + + + Server added to operator %@. + Server added to operator %@. + alert message + Server address Server address @@ -5959,6 +6463,21 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + Server operator changed. + alert title + + + Server operators + Server operators + No comment provided by engineer. + + + Server protocol changed. + Server protocol changed. + alert title + Server requires authorization to create queues, check password Server requires authorization to create queues, check password @@ -6064,6 +6583,11 @@ Enable in *Network & servers* settings. Settings No comment provided by engineer. + + Settings were changed. + Settings were changed. + alert message + Shape profile images Shape profile images @@ -6072,22 +6596,38 @@ Enable in *Network & servers* settings. Share Share - chat item action + alert action + chat item action Share 1-time link Share 1-time link No comment provided by engineer. + + Share 1-time link with a friend + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + Share SimpleX address on social media. + No comment provided by engineer. + Share address Share address No comment provided by engineer. + + Share address publicly + Share address publicly + No comment provided by engineer. + Share address with contacts? Share address with contacts? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6639,11 @@ Enable in *Network & servers* settings. Share link No comment provided by engineer. + + Share profile + Share profile + No comment provided by engineer. + Share this 1-time invite link Share this 1-time invite link @@ -6169,6 +6714,11 @@ Enable in *Network & servers* settings. SimpleX Address No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. SimpleX Chat security was audited by Trail of Bits. @@ -6199,6 +6749,16 @@ Enable in *Network & servers* settings. SimpleX address No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX contact address @@ -6219,9 +6779,9 @@ Enable in *Network & servers* settings. SimpleX links chat feature - - SimpleX links are prohibited in this group. - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. + SimpleX links are prohibited. No comment provided by engineer. @@ -6234,6 +6794,11 @@ Enable in *Network & servers* settings. SimpleX one-time invitation simplex link type + + SimpleX protocols reviewed by Trail of Bits. + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Simplified incognito mode @@ -6264,6 +6829,11 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: Some file(s) were not exported: @@ -6279,6 +6849,13 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + Some servers failed the test: +%@ + alert message + Somebody Somebody @@ -6329,11 +6906,6 @@ Enable in *Network & servers* settings. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - Stop chat to enable database actions - 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. Stop chat to export, import or delete chat database. You will not be able to receive and send messages while the chat is stopped. @@ -6362,12 +6934,12 @@ Enable in *Network & servers* settings. Stop sharing Stop sharing - No comment provided by engineer. + alert action Stop sharing address? Stop sharing address? - No comment provided by engineer. + alert title Stopping chat @@ -6404,6 +6976,16 @@ Enable in *Network & servers* settings. Support SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System System @@ -6439,11 +7021,21 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Tail + No comment provided by engineer. + Take picture Take picture No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Tap button @@ -6502,7 +7094,7 @@ Enable in *Network & servers* settings. Tests failed! Tests failed! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7111,6 @@ Enable in *Network & servers* settings. Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - The 1st platform without any user identifiers – private by design. - No comment provided by engineer. - 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. @@ -6536,6 +7123,11 @@ It can happen because of some bug or when the connection is compromised.The app can notify you when you receive messages or contact requests - please open settings to enable. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). The app will ask to confirm downloads from unknown file servers (except .onion). @@ -6551,6 +7143,11 @@ It can happen because of some bug or when the connection is compromised.The code you scanned is not a SimpleX link QR code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! The connection you accepted will be cancelled! @@ -6571,6 +7168,11 @@ It can happen because of some bug or when the connection is compromised.The encryption is working and the new encryption agreement is not required. It may result in connection errors! No comment provided by engineer. + + The future of messaging + The future of messaging + No comment provided by engineer. + The hash of the previous message is different. The hash of the previous message is different. @@ -6596,11 +7198,6 @@ It can happen because of some bug or when the connection is compromised.The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - The next generation of private messaging - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. The old database was not removed during the migration, it can be deleted. @@ -6611,6 +7208,21 @@ It can happen because of some bug or when the connection is compromised.The profile is only shared with your contacts. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ The second tick we missed! ✅ @@ -6626,16 +7238,31 @@ It can happen because of some bug or when the connection is compromised.The servers for new connections of your current chat profile **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + The servers for new files of your current chat profile **%@**. + No comment provided by engineer. + The text you pasted is not a SimpleX link. The text you pasted is not a SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. These settings are for your current profile **%@**. @@ -6736,9 +7363,9 @@ It can happen because of some bug or when the connection is compromised.To make a new connection 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. - To protect privacy, instead of user IDs used by all other platforms, SimpleX has identifiers for message queues, separate for each of your contacts. + + To protect against your link being replaced, you can compare contact security codes. + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6758,6 +7385,26 @@ You will be prompted to complete authentication before this feature is enabled.< You will be prompted to complete authentication before this feature is enabled. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + No comment provided by engineer. + + + To receive + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. To record voice message please grant permission to use Microphone. @@ -6768,11 +7415,21 @@ You will be prompted to complete authentication before this feature is enabled.< To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page. No comment provided by engineer. + + To send + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. To support instant push notifications the chat database has to be migrated. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. To verify end-to-end encryption with your contact compare (or scan) the code on your devices. @@ -6863,6 +7520,11 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. + + Undelivered messages + Undelivered messages + No comment provided by engineer. + Unexpected migration state Unexpected migration state @@ -6911,7 +7573,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7682,21 @@ To connect, please ask your contact to create another connection link and check Uploading archive No comment provided by engineer. + + Use %@ + Use %@ + No comment provided by engineer. + Use .onion hosts Use .onion hosts No comment provided by engineer. + + Use SOCKS proxy + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? Use SimpleX Chat servers? @@ -7040,6 +7712,16 @@ To connect, please ask your contact to create another connection link and check Use current profile No comment provided by engineer. + + Use for files + Use for files + No comment provided by engineer. + + + Use for messages + Use for messages + No comment provided by engineer. + Use for new connections Use for new connections @@ -7080,6 +7762,11 @@ To connect, please ask your contact to create another connection link and check Use server No comment provided by engineer. + + Use servers + Use servers + No comment provided by engineer. + Use the app while in the call. Use the app while in the call. @@ -7090,16 +7777,16 @@ To connect, please ask your contact to create another connection link and check Use the app with one hand. No comment provided by engineer. - - User profile - User profile - No comment provided by engineer. - User selection User selection No comment provided by engineer. + + Username + Username + No comment provided by engineer. + Using SimpleX Chat servers. Using SimpleX Chat servers. @@ -7170,11 +7857,21 @@ To connect, please ask your contact to create another connection link and check Videos and files up to 1gb No comment provided by engineer. + + View conditions + View conditions + No comment provided by engineer. + View security code View security code No comment provided by engineer. + + View updated conditions + View updated conditions + No comment provided by engineer. + Visible history Visible history @@ -7190,9 +7887,9 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. - Voice messages are prohibited in this group. + + Voice messages are prohibited. + Voice messages are prohibited. No comment provided by engineer. @@ -7285,9 +7982,9 @@ To connect, please ask your contact to create another connection link and check When connecting audio and video calls. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - When people request to connect, you can accept or reject it. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7333,7 +8030,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8057,6 @@ To connect, please ask your contact to create another connection link and check XFTP server No comment provided by engineer. - - You - You - No comment provided by engineer. - You **must not** use the same database on two devices. You **must not** use the same database on two devices. @@ -7390,6 +8082,11 @@ To connect, please ask your contact to create another connection link and check You are already connected to %@. No comment provided by engineer. + + You are already connected with %@. + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. You are already connecting to %@. @@ -7452,6 +8149,16 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + You can configure servers via settings. + No comment provided by engineer. + You can create it later You can create it later @@ -7492,6 +8199,11 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. You can set lock screen notification preview via settings. @@ -7507,11 +8219,6 @@ Repeat join request? You can share this address with your contacts to let them connect with **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - You can share your address as a link or QR code - anybody can connect to you. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app You can start chat via app Settings / Database or by restarting the app @@ -7535,23 +8242,23 @@ Repeat join request? You can view invitation link again in connection details. You can view invitation link again in connection details. - No comment provided by engineer. + alert message You can't send messages! You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. You could not be verified; please try again. No comment provided by engineer. + + You decide who can connect. + You decide who can connect. + No comment provided by engineer. + You have already requested connection via this address! You have already requested connection via this address! @@ -7654,6 +8361,11 @@ Repeat connection request? You will still receive calls and notifications from muted profiles when they are active. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. You will stop receiving messages from this group. Chat history will be preserved. @@ -7674,11 +8386,6 @@ Repeat connection request? You're using an incognito profile for this group - to prevent sharing your main profile inviting contacts is not allowed No comment provided by engineer. - - Your %@ servers - Your %@ servers - No comment provided by engineer. - Your ICE servers Your ICE servers @@ -7694,11 +8401,6 @@ Repeat connection request? Your SimpleX address No comment provided by engineer. - - Your XFTP servers - Your XFTP servers - No comment provided by engineer. - Your calls Your calls @@ -7714,11 +8416,21 @@ Repeat connection request? Your chat database is not encrypted - set passphrase to encrypt it. No comment provided by engineer. + + Your chat preferences + Your chat preferences + alert title + Your chat profiles Your chat profiles No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Your contact sent a file that is larger than currently supported maximum size (%@). @@ -7734,6 +8446,11 @@ Repeat connection request? Your contacts will remain connected. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Your current chat database will be DELETED and REPLACED with the imported one. @@ -7764,13 +8481,16 @@ Repeat connection request? Your profile **%@** will be shared. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. Your profile, contacts and delivered messages are stored on your device. @@ -7781,16 +8501,16 @@ SimpleX servers cannot see your profile. Your random profile No comment provided by engineer. - - Your server - Your server - No comment provided by engineer. - Your server address Your server address No comment provided by engineer. + + Your servers + Your servers + No comment provided by engineer. + Your settings Your settings @@ -7831,6 +8551,11 @@ SimpleX servers cannot see your profile. accepted call call status + + accepted invitation + accepted invitation + chat list item title + admin admin @@ -8019,7 +8744,7 @@ SimpleX servers cannot see your profile. connecting… connecting… - chat list item title + No comment provided by engineer. connection established @@ -8211,6 +8936,11 @@ SimpleX servers cannot see your profile. expired No comment provided by engineer. + + for better metadata privacy. + for better metadata privacy. + No comment provided by engineer. + forwarded forwarded @@ -8508,6 +9238,11 @@ SimpleX servers cannot see your profile. removed you rcv group event chat item + + requested to connect + requested to connect + chat list item title + saved saved @@ -8833,6 +9568,38 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + %d new events + notification body + + + From: %@ + From: %@ + notification body + + + New events + New events + notification + + + New messages + New messages + notification + + + New messages in %d chats + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/en.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/en.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 38d8c82fd1..08522cc617 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ está verificado No comment provided by engineer. + + %@ server + %@ servidor + No comment provided by engineer. + + + %@ servers + %@ servidores + No comment provided by engineer. + %@ uploaded %@ subido @@ -137,6 +132,11 @@ ¡ %@ quiere contactar! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ y %lld miembro(s) más @@ -154,37 +154,62 @@ %d days - %d días + %d día(s) time interval + + %d file(s) are still being downloaded. + %d archivo(s) se está(n) descargando todavía. + forward confirmation reason + + + %d file(s) failed to download. + La descarga ha fallado para %d archivo(s). + forward confirmation reason + + + %d file(s) were deleted. + %d archivo(s) ha(n) sido eliminado(s). + forward confirmation reason + + + %d file(s) were not downloaded. + %d archivo(s) no se ha(n) descargado. + forward confirmation reason + %d hours - %d horas + %d hora(s) time interval + + %d messages not forwarded + %d mensaje(s) no enviado(s) + alert title + %d min - %d minutos + %d minuto(s) time interval %d months - %d meses + %d mes(es) time interval %d sec - %d segundos + %d segundo(s) time interval %d skipped message(s) - %d mensaje(s) saltado(s + %d mensaje(s) omitido(s) integrity error chat item %d weeks - %d semanas + %d semana(s) time interval @@ -322,14 +347,9 @@ ) 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 or link for your contact. - **Añadir nuevo contacto**: para crear tu código QR o enlace de un uso para tu contacto. + + **Create 1-time link**: to create and share a new invitation link. + **Añadir contacto**: crea un enlace de invitación nuevo. No comment provided by engineer. @@ -337,13 +357,13 @@ **Crear grupo**: crea un grupo nuevo. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Más privado**: comprueba los mensajes nuevos cada 20 minutos. El token del dispositivo se comparte con el servidor de SimpleX Chat, pero no cuántos contactos o mensajes tienes. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +377,16 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + **Escanear / Pegar enlace**: para conectar mediante un enlace recibido. + 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. @@ -468,6 +493,16 @@ una semana time interval + + 1-time link + Enlace de un uso + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Los enlaces de un uso pueden ser usados *solamente con un contacto* - compártelos en persona o mediante cualquier aplicación de mensajería. + No comment provided by engineer. + 5 minutes 5 minutos @@ -507,7 +542,7 @@ A new random profile will be shared. - Se compartirá un perfil nuevo aleatorio. + Compartirás un perfil nuevo aleatorio. No comment provided by engineer. @@ -537,19 +572,14 @@ ¿Cancelar el cambio de servidor? No comment provided by engineer. - - About SimpleX - Acerca de SimpleX - No comment provided by engineer. - About SimpleX Chat Sobre SimpleX Chat No comment provided by engineer. - - About SimpleX address - Acerca de la dirección SimpleX + + About operators + Acerca de los operadores No comment provided by engineer. @@ -564,6 +594,11 @@ accept incoming call via notification swipe action + + Accept conditions + Aceptar condiciones + No comment provided by engineer. + Accept connection request? ¿Aceptar solicitud de conexión? @@ -580,6 +615,11 @@ accept contact request via notification swipe action + + Accepted conditions + Condiciones aceptadas + No comment provided by engineer. + Acknowledged Confirmaciones @@ -600,14 +640,9 @@ 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 + + Add friends + Añadir amigos No comment provided by engineer. @@ -625,6 +660,11 @@ Añadir servidores mediante el escaneo de códigos QR. No comment provided by engineer. + + Add team members + Añadir miembros del equipo + No comment provided by engineer. + Add to another device Añadir a otro dispositivo @@ -635,6 +675,21 @@ Añadir mensaje de bienvenida No comment provided by engineer. + + Add your team members to the conversations. + Añade a los miembros de tu equipo a las conversaciones. + No comment provided by engineer. + + + Added media & file servers + Servidores de archivos y multimedia añadidos + No comment provided by engineer. + + + Added message servers + Servidores de mensajes añadidos + No comment provided by engineer. + Additional accent Acento adicional @@ -660,6 +715,16 @@ El cambio de dirección se cancelará. Se usará la antigua dirección de recepción. No comment provided by engineer. + + Address or 1-time link? + ¿Dirección o enlace de un uso? + No comment provided by engineer. + + + Address settings + Configuración de dirección + No comment provided by engineer. + Admins can block a member for all. Los administradores pueden bloquear a un miembro para los demás. @@ -695,8 +760,8 @@ Al introducirlo todos los datos son eliminados. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Todos los datos son privados y están en tu dispositivo. No comment provided by engineer. @@ -705,6 +770,11 @@ Todos los miembros del grupo permanecerán conectados. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Todos los mensajes y archivos son enviados **cifrados de extremo a extremo** y con seguridad de cifrado postcuántico en mensajes directos. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Todos los mensajes serán borrados. ¡No podrá deshacerse! @@ -723,7 +793,7 @@ All profiles Todos los perfiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -802,7 +872,7 @@ Allow to send SimpleX links. - Permitir enviar enlaces SimpleX. + Se permite enviar enlaces SimpleX. No comment provided by engineer. @@ -885,6 +955,11 @@ Responder llamada No comment provided by engineer. + + Anybody can host servers. + Cualquiera puede alojar servidores. + No comment provided by engineer. + App build: %@ Compilación app: %@ @@ -915,6 +990,11 @@ El código de acceso será reemplazado por código de autodestrucción. No comment provided by engineer. + + App session + Sesión de aplicación + No comment provided by engineer. + App version Versión de la aplicación @@ -947,7 +1027,7 @@ Archive contacts to chat later. - Archivar contactos para charlar más tarde. + Archiva contactos para charlar más tarde. No comment provided by engineer. @@ -1020,6 +1100,11 @@ Aceptar imágenes automáticamente No comment provided by engineer. + + Auto-accept settings + Auto aceptar configuración + alert title + Back Volver @@ -1045,11 +1130,21 @@ Hash de mensaje incorrecto No comment provided by engineer. + + Better calls + Llamadas mejoradas + No comment provided by engineer. + Better groups Grupos mejorados No comment provided by engineer. + + Better message dates. + Sistema de fechas mejorado. + No comment provided by engineer. + Better messages Mensajes mejorados @@ -1060,6 +1155,21 @@ Uso de red mejorado No comment provided by engineer. + + Better notifications + Notificaciones mejoradas + No comment provided by engineer. + + + Better security ✅ + Seguridad mejorada ✅ + No comment provided by engineer. + + + Better user experience + Experiencia de usuario mejorada + No comment provided by engineer. + Black Negro @@ -1102,7 +1212,7 @@ Blur for better privacy. - Difuminar para más privacidad. + Difumina para mayor privacidad. No comment provided by engineer. @@ -1140,6 +1250,16 @@ Búlgaro, Finlandés, Tailandés y Ucraniano - gracias a los usuarios y [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Dirección empresarial + No comment provided by engineer. + + + Business chats + Chats empresariales + 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). Mediante perfil (predeterminado) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1193,7 +1313,8 @@ Cancel Cancelar - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1334,7 @@ Cannot receive file No se puede recibir el archivo - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1351,11 @@ Cambiar No comment provided by engineer. + + Change chat profiles + Cambiar perfil de usuario + authentication reason + Change database passphrase? ¿Cambiar contraseña de la base de datos? @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Archivo del chat + + Chat + Chat + No comment provided by engineer. + + + Chat already exists + El chat ya existe + No comment provided by engineer. + + + Chat already exists! + ¡El chat ya existe! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Preferencias de Chat No comment provided by engineer. + + Chat preferences were changed. + Las preferencias del chat han sido modificadas. + alert message + + + Chat profile + Perfil de usuario + No comment provided by engineer. + Chat theme Tema de chat No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + El chat será eliminado para todos los miembros. ¡No podrá deshacerse! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + El chat será eliminado para tí. ¡No podrá deshacerse! + No comment provided by engineer. + Chats Chats No comment provided by engineer. + + Check messages every 20 min. + Comprobar mensajes cada 20 min. + No comment provided by engineer. + + + Check messages when allowed. + Comprobar mensajes cuando se permita. + No comment provided by engineer. + Check server address and try again. Comprueba la dirección del servidor e inténtalo de nuevo. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1441,16 +1607,56 @@ Completadas No comment provided by engineer. + + Conditions accepted on: %@. + Condiciones aceptadas el: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Las condiciones se han aceptado para el(los) operador(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Las condiciones ya se han aceptado para el/los siguiente(s) operador(s): **%@**. + No comment provided by engineer. + + + Conditions of use + Condiciones de uso + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Las condiciones de los operadores habilitados serán aceptadas después de 30 días. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Las condiciones serán aceptadas para el/los operador(es): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Las condiciones serán aceptadas para el/los operador(es): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Las condiciones serán aceptadas el: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Las condiciones serán aceptadas automáticamente para los operadores habilitados el: %@. + No comment provided by engineer. + Configure ICE servers Configure servidores ICE No comment provided by engineer. - - Configured %@ servers - %@ servidores configurados - No comment provided by engineer. - Confirm Confirmar @@ -1493,7 +1699,7 @@ Confirm that you remember database passphrase to migrate it. - Para migrar confirma que recuerdas la frase de contraseña de la base de datos. + Para migrar la base de datos confirma que recuerdas la frase de contraseña. No comment provided by engineer. @@ -1617,7 +1823,7 @@ This is your own one-time link! Connection and servers status. - Estado de conexión y servidores. + Estado de tu conexión y servidores. No comment provided by engineer. @@ -1640,6 +1846,11 @@ This is your own one-time link! ¡Solicitud de conexión enviada! No comment provided by engineer. + + Connection security + Seguridad de conexión + No comment provided by engineer. + Connection terminated Conexión finalizada @@ -1740,6 +1951,11 @@ This is your own one-time link! Versión Core: v%@ No comment provided by engineer. + + Corner + Esquina + No comment provided by engineer. + Correct name to %@? ¿Corregir el nombre a %@? @@ -1750,6 +1966,11 @@ This is your own one-time link! Crear No comment provided by engineer. + + Create 1-time link + Crear enlace de un uso + No comment provided by engineer. + Create SimpleX address Crear dirección SimpleX @@ -1760,11 +1981,6 @@ This is your own one-time link! 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. - No comment provided by engineer. - Create file Crear archivo @@ -1825,11 +2041,6 @@ This is your own one-time link! Creado: %@ copied message info - - Created on %@ - Creado en %@ - No comment provided by engineer. - Creating archive link Creando enlace al archivo @@ -1845,6 +2056,11 @@ This is your own one-time link! Código de Acceso No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + El texto con las condiciones actuales no se ha podido cargar, puedes revisar las condiciones en el siguiente enlace: + No comment provided by engineer. + Current passphrase… Contraseña actual… @@ -1865,6 +2081,11 @@ This is your own one-time link! Tiempo personalizado No comment provided by engineer. + + Customizable message shape. + Forma personalizable de los mensajes. + No comment provided by engineer. + Customize theme Personalizar tema @@ -1946,7 +2167,7 @@ This is your own one-time link! Database passphrase is different from saved in the keychain. - La contraseña es distinta a la almacenada en Keychain. + La contraseña es diferente a la almacenada en Keychain. No comment provided by engineer. @@ -1996,7 +2217,8 @@ This is your own one-time link! Delete Eliminar - chat item action + alert action + chat item action swipe action @@ -2034,14 +2256,9 @@ This is your own one-time link! Eliminar y notificar contacto No comment provided by engineer. - - Delete archive - Eliminar archivo - No comment provided by engineer. - - - Delete chat archive? - ¿Eliminar archivo del chat? + + Delete chat + Eliminar chat No comment provided by engineer. @@ -2054,6 +2271,11 @@ This is your own one-time link! ¿Eliminar perfil? No comment provided by engineer. + + Delete chat? + ¿Eliminar chat? + No comment provided by engineer. + Delete connection Eliminar conexión @@ -2086,7 +2308,7 @@ This is your own one-time link! Delete files and media? - Eliminar archivos y multimedia? + ¿Eliminar archivos y multimedia? No comment provided by engineer. @@ -2159,6 +2381,11 @@ This is your own one-time link! ¿Eliminar base de datos antigua? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Borra o modera hasta 200 mensajes a la vez. + No comment provided by engineer. + Delete pending connection? ¿Eliminar conexión pendiente? @@ -2209,6 +2436,11 @@ This is your own one-time link! Errores de eliminación No comment provided by engineer. + + Delivered even when Apple drops them. + Entregados incluso cuando Apple los descarta. + No comment provided by engineer. + Delivery Entrega @@ -2309,8 +2541,13 @@ This is your own one-time link! Mensajes directos chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + Mensajes directos no permitidos entre miembros de este chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Los mensajes directos entre miembros del grupo no están permitidos. No comment provided by engineer. @@ -2349,8 +2586,8 @@ This is your own one-time link! Los mensajes temporales no están permitidos en este chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Los mensajes temporales no están permitidos en este grupo. No comment provided by engineer. @@ -2371,7 +2608,7 @@ This is your own one-time link! Disconnect desktop? - ¿Desconectar ordenador? + ¿Desconectar del ordenador? No comment provided by engineer. @@ -2406,7 +2643,12 @@ This is your own one-time link! Do not send history to new members. - No enviar historial a miembros nuevos. + No se envía el historial a los miembros nuevos. + No comment provided by engineer. + + + Do not use credentials with proxy. + No uses credenciales con proxy. No comment provided by engineer. @@ -2421,7 +2663,7 @@ This is your own one-time link! Don't show again - No mostrar de nuevo + No volver a mostrar No comment provided by engineer. @@ -2432,7 +2674,8 @@ This is your own one-time link! Download Descargar - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ This is your own one-time link! Descargar archivo server test step + + Download files + Descargar archivos + alert action + Downloaded Descargado @@ -2479,6 +2727,11 @@ This is your own one-time link! Duración No comment provided by engineer. + + E2E encrypted notifications. + Notificaciones cifradas E2E. + No comment provided by engineer. + Edit Editar @@ -2499,6 +2752,11 @@ This is your own one-time link! Activar (conservar anulaciones) No comment provided by engineer. + + Enable Flux + Habilita Flux + No comment provided by engineer. + Enable SimpleX Lock Activar Bloqueo SimpleX @@ -2704,26 +2962,36 @@ This is your own one-time link! Error al cancelar cambio de dirección No comment provided by engineer. + + Error accepting conditions + Error al aceptar las condiciones + alert title + Error accepting contact request Error al aceptar solicitud del contacto No comment provided by engineer. - - Error accessing database file - Error al acceder al archivo de la base de datos - No comment provided by engineer. - Error adding member(s) Error al añadir miembro(s) No comment provided by engineer. + + Error adding server + Error al añadir servidor + alert title + Error changing address Error al cambiar servidor No comment provided by engineer. + + Error changing connection profile + Error al cambiar el perfil de conexión + No comment provided by engineer. + Error changing role Error al cambiar rol @@ -2734,6 +3002,11 @@ This is your own one-time link! Error cambiando configuración No comment provided by engineer. + + Error changing to incognito! + ¡Error al cambiar a incógnito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Error al conectar con el servidor de reenvío %@. Por favor, inténtalo más tarde. @@ -2849,9 +3122,14 @@ This is your own one-time link! Error al unirte al grupo No comment provided by engineer. - - Error loading %@ servers - Error al cargar servidores %@ + + Error loading servers + Error al cargar servidores + alert title + + + Error migrating settings + Error al migrar la configuración No comment provided by engineer. @@ -2862,7 +3140,7 @@ This is your own one-time link! Error receiving file Error al recibir archivo - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3162,6 @@ This is your own one-time link! Error al restablecer las estadísticas No comment provided by engineer. - - Error saving %@ servers - Error al guardar servidores %@ - No comment provided by engineer. - Error saving ICE servers Error al guardar servidores ICE @@ -2909,6 +3182,11 @@ This is your own one-time link! Error al guardar contraseña en Keychain No comment provided by engineer. + + Error saving servers + Error al guardar servidores + alert title + Error saving settings Error al guardar ajustes @@ -2954,10 +3232,15 @@ This is your own one-time link! Error al parar SimpleX No comment provided by engineer. + + Error switching profile + Error al cambiar perfil + No comment provided by engineer. + Error switching profile! ¡Error al cambiar perfil! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3257,11 @@ This is your own one-time link! Error al actualizar mensaje No comment provided by engineer. + + Error updating server + Error al actualizar el servidor + alert title + Error updating settings Error al actualizar configuración @@ -3002,8 +3290,7 @@ This is your own one-time link! Error: %@ Error: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3307,11 @@ This is your own one-time link! Errores No comment provided by engineer. + + Errors in servers configuration. + Error en la configuración del servidor. + servers error + Even when disabled in the conversation. Incluso si está desactivado para la conversación. @@ -3090,6 +3382,13 @@ This is your own one-time link! Error de archivo No comment provided by engineer. + + File errors: +%@ + Error(es) de archivo +%@ + alert message + File not found - most likely file was deleted or cancelled. Archivo no encontrado, probablemente haya sido borrado o cancelado. @@ -3145,8 +3444,8 @@ This is your own one-time link! Archivos y multimedia chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Los archivos y multimedia no están permitidos en este grupo. No comment provided by engineer. @@ -3215,21 +3514,61 @@ This is your own one-time link! Corrección no compatible con miembro del grupo No comment provided by engineer. + + For chat profile %@: + Para el perfil de chat %@: + servers error + For console Para consola No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Si por ejemplo tu contacto recibe los mensajes a través de un servidor de SimpleX Chat, tu aplicación los entregará a través de un servidor de Flux. + No comment provided by engineer. + + + For private routing + Para el enrutamiento privado + No comment provided by engineer. + + + For social media + Para redes sociales + No comment provided by engineer. + Forward Reenviar chat item action + + Forward %d message(s)? + ¿Reenviar %d mensaje(s)? + alert title + Forward and save messages Reenviar y guardar mensajes No comment provided by engineer. + + Forward messages + Reenviar mensajes + alert action + + + Forward messages without files? + ¿Reenviar mensajes sin los archivos? + alert message + + + Forward up to 20 messages at once. + Desplazamiento de hasta 20 mensajes. + No comment provided by engineer. + Forwarded Reenviado @@ -3240,6 +3579,11 @@ This is your own one-time link! Reenviado por No comment provided by engineer. + + Forwarding %lld messages + Reenviando %lld mensajes + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. El servidor de reenvío %@ no ha podido conectarse al servidor de destino %@. Por favor, intentalo más tarde. @@ -3289,19 +3633,14 @@ Error: %2$@ Nombre completo (opcional) No comment provided by engineer. - - Full name: - Nombre completo: - No comment provided by engineer. - Fully decentralized – visible only to members. - Completamente descentralizado y sólo visible para los miembros. + Totalmente descentralizado. Visible sólo para los miembros. No comment provided by engineer. Fully re-implemented - work in background! - Completamente reimplementado: ¡funciona en segundo plano! + Totalmente revisado. ¡Funciona en segundo plano! No comment provided by engineer. @@ -3379,41 +3718,6 @@ Error: %2$@ Enlaces de grupo No comment provided by engineer. - - 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. (24 hours) - Los miembros del grupo pueden eliminar mensajes de forma irreversible. (24 horas) - No comment provided by engineer. - - - Group members can send SimpleX links. - Los miembros del grupo pueden enviar enlaces SimpleX. - No comment provided by engineer. - - - Group members can send direct messages. - Los miembros del grupo pueden enviar mensajes directos. - No comment provided by engineer. - - - Group members can send disappearing messages. - Los miembros del grupo pueden enviar mensajes temporales. - No comment provided by engineer. - - - Group members can send files and media. - Los miembros del grupo pueden enviar archivos y multimedia. - No comment provided by engineer. - - - Group members can send voice messages. - Los miembros del grupo pueden enviar mensajes de voz. - No comment provided by engineer. - Group message: Mensaje de grupo: @@ -3509,9 +3813,14 @@ Error: %2$@ Cómo funciona SimpleX No comment provided by engineer. - - How it works - Cómo funciona + + How it affects privacy + Cómo afecta a la privacidad + No comment provided by engineer. + + + How it helps privacy + Cómo ayuda a la privacidad No comment provided by engineer. @@ -3539,6 +3848,11 @@ Error: %2$@ Servidores ICE (uno por línea) No comment provided by engineer. + + IP address + Dirección IP + 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. @@ -3579,8 +3893,8 @@ Error: %2$@ Inmediatamente No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Inmune a spam y abuso No comment provided by engineer. @@ -3614,6 +3928,13 @@ Error: %2$@ Importando archivo No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Reducción del tráfico y entrega mejorada. +¡Pronto habrá nuevas mejoras! + No comment provided by engineer. + Improved message delivery Entrega de mensajes mejorada @@ -3714,6 +4035,11 @@ Error: %2$@ Instalar terminal para [SimpleX Chat](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Al instante + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4047,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Al instante - No comment provided by engineer. - Interface Interfaz @@ -3774,7 +4095,7 @@ Error: %2$@ Invalid server address! ¡Dirección de servidor no válida! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4117,11 @@ Error: %2$@ Invitar miembros No comment provided by engineer. + + Invite to chat + Invitar al chat + No comment provided by engineer. + Invite to group Invitar al grupo @@ -3811,8 +4137,8 @@ Error: %2$@ La eliminación irreversible de mensajes no está permitida en este chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. La eliminación irreversible de mensajes no está permitida en este grupo. No comment provided by engineer. @@ -3902,7 +4228,7 @@ This is your link for group %@! Keep Guardar - No comment provided by engineer. + alert action Keep conversation @@ -3917,7 +4243,7 @@ This is your link for group %@! Keep unused invitation? ¿Guardar invitación no usada? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4280,16 @@ This is your link for group %@! Salir swipe action + + Leave chat + Salir del chat + No comment provided by engineer. + + + Leave chat? + ¿Salir del chat? + No comment provided by engineer. + Leave group Salir del grupo @@ -4004,11 +4340,6 @@ This is your link for group %@! Mensajes en vivo No comment provided by engineer. - - Local - Local - No comment provided by engineer. - Local name Nombre local @@ -4016,7 +4347,7 @@ This is your link for group %@! Local profile data only - Sólo datos del perfil local + Eliminar sólo el perfil No comment provided by engineer. @@ -4029,11 +4360,6 @@ This is your link for group %@! Modo bloqueo No comment provided by engineer. - - Make a private connection - Establecer una conexión privada - No comment provided by engineer. - Make one message disappear Escribir un mensaje temporal @@ -4044,21 +4370,11 @@ This is your link for group %@! ¡Hacer perfil privado! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Asegúrate de que las direcciones del servidor %@ tienen el formato correcto, están separadas por líneas y no duplicadas (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Asegúrate de que las direcciones del servidor WebRTC ICE tienen el formato correcto, están separadas por líneas y no duplicadas. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Muchos se preguntarán: *si SimpleX no tiene identificadores de usuario, ¿cómo puede entregar los mensajes?* - No comment provided by engineer. - Mark deleted for everyone Marcar como eliminado para todos @@ -4104,6 +4420,11 @@ This is your link for group %@! Miembro inactivo item status text + + Member role will be changed to "%@". All chat members will be notified. + El rol del miembro cambiará a "%@" y todos serán notificados. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. El rol del miembro cambiará a "%@" y se notificará al grupo. @@ -4114,11 +4435,51 @@ This is your link for group %@! El rol del miembro cambiará a "%@" y recibirá una invitación nueva. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + El miembro será eliminado del chat. ¡No podrá deshacerse! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! El miembro será expulsado del grupo. ¡No podrá deshacerse! No comment provided by engineer. + + Members can add message reactions. + Los miembros pueden añadir reacciones a los mensajes. + No comment provided by engineer. + + + 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. + + + Members can send SimpleX links. + Los miembros del grupo pueden enviar enlaces SimpleX. + No comment provided by engineer. + + + Members can send direct messages. + Los miembros del grupo pueden enviar mensajes directos. + No comment provided by engineer. + + + Members can send disappearing messages. + Los miembros del grupo pueden enviar mensajes temporales. + No comment provided by engineer. + + + Members can send files and media. + Los miembros del grupo pueden enviar archivos y multimedia. + No comment provided by engineer. + + + Members can send voice messages. + Los miembros del grupo pueden enviar mensajes de voz. + No comment provided by engineer. + Menus Menus @@ -4169,8 +4530,8 @@ This is your link for group %@! Las reacciones a los mensajes no están permitidas en este chat. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Las reacciones a los mensajes no están permitidas en este grupo. No comment provided by engineer. @@ -4184,6 +4545,11 @@ This is your link for group %@! Servidores de mensajes No comment provided by engineer. + + Message shape + Forma del mensaje + No comment provided by engineer. + Message source remains private. El autor del mensaje se mantiene privado. @@ -4234,6 +4600,11 @@ This is your link for group %@! Mensajes enviados No comment provided by engineer. + + Messages were deleted after you selected them. + Los mensajes han sido borrados después de seleccionarlos. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Los mensajes, archivos y llamadas están protegidos mediante **cifrado de extremo a extremo** con secreto perfecto hacía adelante, repudio y recuperación tras ataque. @@ -4299,9 +4670,9 @@ This is your link for group %@! Migración completada No comment provided by engineer. - - Migrations: %@ - Migraciones: %@ + + Migrations: + Migraciones: No comment provided by engineer. @@ -4329,6 +4700,11 @@ This is your link for group %@! Conexión de red más fiable. No comment provided by engineer. + + More reliable notifications + Notificaciones más fiables + No comment provided by engineer. + Most likely this connection is deleted. Probablemente la conexión ha sido eliminada. @@ -4364,6 +4740,11 @@ This is your link for group %@! Conexión de red No comment provided by engineer. + + Network decentralization + Descentralización de la red + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Problema en la red - el mensaje ha expirado tras muchos intentos de envío. @@ -4374,6 +4755,11 @@ This is your link for group %@! Gestión de la red No comment provided by engineer. + + Network operator + Operador de red + No comment provided by engineer. + Network settings Configuración de red @@ -4389,6 +4775,16 @@ This is your link for group %@! Código Nuevo No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Se usarán credenciales SOCKS nuevas cada vez que inicies la aplicación. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Se usarán credenciales SOCKS nuevas por cada servidor. + No comment provided by engineer. + New chat Nuevo chat @@ -4409,11 +4805,6 @@ This is your link for group %@! Contacto nuevo: notification - - New database archive - Nuevo archivo de bases de datos - No comment provided by engineer. - New desktop app! Nueva aplicación para PC! @@ -4424,6 +4815,11 @@ This is your link for group %@! Nuevo nombre mostrado No comment provided by engineer. + + New events + Eventos nuevos + notification + New in %@ Nuevo en %@ @@ -4449,6 +4845,11 @@ This is your link for group %@! Contraseña nueva… No comment provided by engineer. + + New server + Servidor nuevo + No comment provided by engineer. + No No @@ -4504,21 +4905,71 @@ This is your link for group %@! No hay información, intenta recargar No comment provided by engineer. + + No media & file servers. + Ningún servidor de archivos y multimedia. + servers error + + + No message servers. + Ningún servidor de mensajes. + servers error + No network connection Sin conexión de red No comment provided by engineer. + + No permission to record speech + Sin permiso para grabación de voz + No comment provided by engineer. + + + No permission to record video + Sin permiso para grabación de vídeo + No comment provided by engineer. + No permission to record voice message Sin permiso para grabar mensajes de voz No comment provided by engineer. + + No push server + Ningún servidor push + No comment provided by engineer. + No received or sent files Sin archivos recibidos o enviados No comment provided by engineer. + + No servers for private message routing. + Ningún servidor para enrutamiento privado. + servers error + + + No servers to receive files. + Ningún servidor para recibir archivos. + servers error + + + No servers to receive messages. + Ningún servidor para recibir mensajes. + servers error + + + No servers to send files. + Ningún servidor para enviar archivos. + servers error + + + No user identifiers. + Sin identificadores de usuario. + No comment provided by engineer. + Not compatible! ¡No compatible! @@ -4529,6 +4980,11 @@ This is your link for group %@! Nada seleccionado No comment provided by engineer. + + Nothing to forward! + ¡Nada para reenviar! + alert title + Notifications Notificaciones @@ -4539,6 +4995,11 @@ This is your link for group %@! ¡Las notificaciones están desactivadas! No comment provided by engineer. + + Notifications privacy + Privacidad en las notificaciones + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5022,13 @@ This is your link for group %@! Ok Ok - No comment provided by engineer. + alert button Old database Base de datos antigua No comment provided by engineer. - - Old database archive - Archivo de bases de datos antiguas - No comment provided by engineer. - One-time invitation link Enlace de invitación de un solo uso @@ -4597,8 +5053,13 @@ Requiere activación de la VPN. No se usarán hosts .onion. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + Sólo los propietarios del chat pueden cambiar las preferencias. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. 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. @@ -4682,6 +5143,11 @@ Requiere activación de la VPN. Abrir Configuración No comment provided by engineer. + + Open changes + Abrir cambios + No comment provided by engineer. + Open chat Abrir chat @@ -4692,6 +5158,11 @@ Requiere activación de la VPN. Abrir consola de Chat authentication reason + + Open conditions + Abrir condiciones + No comment provided by engineer. + Open group Grupo abierto @@ -4702,26 +5173,26 @@ Requiere activación de la VPN. Abrir menú migración a otro dispositivo authentication reason - - Open server settings - Abrir configuración del servidor - No comment provided by engineer. - - - Open user profiles - Abrir perfil de usuario - authentication reason - - - 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 app… Iniciando aplicación… No comment provided by engineer. + + Operator + Operador + No comment provided by engineer. + + + Operator server + Servidor del operador + alert title + + + Or import archive file + O importa desde un archivo + No comment provided by engineer. + Or paste archive link O pegar enlace del archivo @@ -4742,15 +5213,22 @@ Requiere activación de la VPN. O muestra este código QR No comment provided by engineer. + + Or to share privately + O para compartir en privado + No comment provided by engineer. + Other Otro No comment provided by engineer. - - Other %@ servers - Otros servidores %@ - No comment provided by engineer. + + Other file errors: +%@ + Otro(s) error(es) de archivo. +%@ + alert message PING count @@ -4787,6 +5265,11 @@ Requiere activación de la VPN. ¡Código de acceso guardado! No comment provided by engineer. + + Password + Contraseña + No comment provided by engineer. + Password to show Contraseña para hacerlo visible @@ -4819,16 +5302,11 @@ Requiere activación de la VPN. Pending - Pendiente + Pendientes No comment provided by engineer. - - People can connect to you only via the links you share. - Las personas pueden conectarse contigo solo mediante los enlaces que compartes. - No comment provided by engineer. - - - Periodically + + Periodic Periódicamente No comment provided by engineer. @@ -4936,9 +5414,14 @@ Error: %@ Interfaz en polaco No comment provided by engineer. + + Port + Puerto + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect - Posiblemente la huella digital del certificado en la dirección del servidor es incorrecta + Posiblemente la huella del certificado en la dirección del servidor es incorrecta server test error @@ -4946,14 +5429,14 @@ Error: %@ Conserva el último borrador del mensaje con los datos adjuntos. No comment provided by engineer. - - Preset server - Servidor predefinido - No comment provided by engineer. - Preset server address - Dirección del servidor predefinida + Dirección predefinida del servidor + No comment provided by engineer. + + + Preset servers + Servidores predefinidos No comment provided by engineer. @@ -4971,6 +5454,11 @@ Error: %@ Seguridad y Privacidad No comment provided by engineer. + + Privacy for your customers. + Privacidad para tus clientes. + No comment provided by engineer. + Privacy redefined Privacidad redefinida @@ -5008,7 +5496,7 @@ Error: %@ Profile and server connections - Datos del perfil y conexiones + Eliminar perfil y conexiones No comment provided by engineer. @@ -5021,16 +5509,6 @@ Error: %@ Forma de los perfiles 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 @@ -5044,7 +5522,7 @@ Error: %@ Profile update will be sent to your contacts. La actualización del perfil se enviará a tus contactos. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5068,7 +5546,7 @@ Error: %@ Prohibit sending SimpleX links. - No permitir el envío de enlaces SimpleX. + No se permite enviar enlaces SimpleX. No comment provided by engineer. @@ -5125,7 +5603,7 @@ Actívalo en ajustes de *Servidores y Redes*. Proxied - Con proxy + Como proxy No comment provided by engineer. @@ -5133,9 +5611,14 @@ Actívalo en ajustes de *Servidores y Redes*. Servidores con proxy No comment provided by engineer. + + Proxy requires password + El proxy requiere contraseña + No comment provided by engineer. + Push notifications - Notificaciones automáticas + Notificaciones push No comment provided by engineer. @@ -5170,12 +5653,7 @@ Actívalo en ajustes de *Servidores y Redes*. Read more - Conoce más - No comment provided by engineer. - - - Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). - Conoce más en el [Manual del Usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). + Saber más No comment provided by engineer. @@ -5183,16 +5661,16 @@ Actívalo en ajustes de *Servidores y Redes*. Conoce más en la [Guía del Usuario](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Conoce más en el [Manual del Usuario](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + No comment provided by engineer. + Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). Conoce 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. - Conoce más en nuestro repositorio GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Conoce más en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme). @@ -5354,6 +5832,11 @@ Actívalo en ajustes de *Servidores y Redes*. Eliminar No comment provided by engineer. + + Remove archive? + ¿Eliminar archivo? + No comment provided by engineer. + Remove image Eliminar imagen @@ -5504,6 +5987,16 @@ Actívalo en ajustes de *Servidores y Redes*. Revelar chat item action + + Review conditions + Revisar condiciones + No comment provided by engineer. + + + Review later + Revisar más tarde + No comment provided by engineer. + Revoke Revocar @@ -5534,6 +6027,11 @@ Actívalo en ajustes de *Servidores y Redes*. Servidor SMP No comment provided by engineer. + + SOCKS proxy + Proxy SOCKS + No comment provided by engineer. + Safely receive files Recibe archivos de forma segura @@ -5547,17 +6045,18 @@ Actívalo en ajustes de *Servidores y Redes*. Save Guardar - chat item action + alert button + chat item action Save (and notify contacts) Guardar (y notificar contactos) - No comment provided by engineer. + alert button Save and notify contact Guardar y notificar contacto - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6073,6 @@ Actívalo en ajustes de *Servidores y Redes*. Guardar y actualizar perfil del grupo No comment provided by engineer. - - Save archive - Guardar archivo - No comment provided by engineer. - - - Save auto-accept settings - Guardar configuración de auto aceptar - No comment provided by engineer. - Save group profile Guardar perfil de grupo @@ -5602,7 +6091,7 @@ Actívalo en ajustes de *Servidores y Redes*. Save preferences? ¿Guardar preferencias? - No comment provided by engineer. + alert title Save profile password @@ -5617,18 +6106,18 @@ Actívalo en ajustes de *Servidores y Redes*. Save servers? ¿Guardar servidores? - No comment provided by engineer. - - - Save settings? - ¿Guardar configuración? - No comment provided by engineer. + alert title Save welcome message? ¿Guardar mensaje de bienvenida? No comment provided by engineer. + + Save your profile? + ¿Guardar tu perfil? + alert title + Saved Guardado @@ -5649,6 +6138,11 @@ Actívalo en ajustes de *Servidores y Redes*. Mensaje guardado message info title + + Saving %lld messages + Guardando %lld mensajes + No comment provided by engineer. + Scale Escala @@ -5729,6 +6223,11 @@ Actívalo en ajustes de *Servidores y Redes*. Seleccionar chat item action + + Select chat profile + Selecciona perfil de chat + No comment provided by engineer. + Selected %lld Seleccionados %lld @@ -5776,7 +6275,7 @@ Actívalo en ajustes de *Servidores y Redes*. Send direct message to connect - Envia un mensaje para conectar + Envía un mensaje para conectar No comment provided by engineer. @@ -5819,11 +6318,6 @@ Actívalo en ajustes de *Servidores y Redes*. Enviar notificaciones No comment provided by engineer. - - Send notifications: - Enviar notificaciones: - No comment provided by engineer. - Send questions and ideas Consultas y sugerencias @@ -5841,13 +6335,13 @@ Actívalo en ajustes de *Servidores y Redes*. Send up to 100 last messages to new members. - Enviar hasta 100 últimos mensajes a los miembros nuevos. + Se envían hasta 100 mensajes más recientes a los miembros nuevos. No comment provided by engineer. Sender cancelled file transfer. El remitente ha cancelado la transferencia de archivos. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5906,7 +6400,7 @@ Actívalo en ajustes de *Servidores y Redes*. Sent directly - Enviado directamente + Directamente No comment provided by engineer. @@ -5941,9 +6435,19 @@ Actívalo en ajustes de *Servidores y Redes*. Sent via proxy - Enviado vía proxy + Mediante proxy No comment provided by engineer. + + Server + Servidor + No comment provided by engineer. + + + Server added to operator %@. + Servidor añadido al operador %@. + alert message + Server address Dirección del servidor @@ -5959,6 +6463,21 @@ Actívalo en ajustes de *Servidores y Redes*. La dirección del servidor es incompatible con la configuración de la red: %@. No comment provided by engineer. + + Server operator changed. + El operador del servidor ha cambiado. + alert title + + + Server operators + Operadores de servidores + No comment provided by engineer. + + + Server protocol changed. + El protocolo del servidor ha cambiado. + alert title + Server requires authorization to create queues, check password El servidor requiere autorización para crear colas, comprueba la contraseña @@ -5971,7 +6490,7 @@ Actívalo en ajustes de *Servidores y Redes*. Server test failed! - ¡Error en prueba del servidor! + ¡Prueba no superada! No comment provided by engineer. @@ -6064,6 +6583,11 @@ Actívalo en ajustes de *Servidores y Redes*. Configuración No comment provided by engineer. + + Settings were changed. + La configuración ha sido modificada. + alert message + Shape profile images Dar forma a las imágenes de perfil @@ -6072,22 +6596,38 @@ Actívalo en ajustes de *Servidores y Redes*. Share Compartir - chat item action + alert action + chat item action Share 1-time link Compartir enlace de un uso No comment provided by engineer. + + Share 1-time link with a friend + Compartir enlace de un uso con un amigo + No comment provided by engineer. + + + Share SimpleX address on social media. + Comparte tu dirección SimpleX en redes sociales. + No comment provided by engineer. + Share address Compartir dirección No comment provided by engineer. + + Share address publicly + Campartir dirección públicamente + No comment provided by engineer. + Share address with contacts? ¿Compartir la dirección con los contactos? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6639,11 @@ Actívalo en ajustes de *Servidores y Redes*. Compartir enlace No comment provided by engineer. + + Share profile + Comparte perfil + No comment provided by engineer. + Share this 1-time invite link Comparte este enlace de un solo uso @@ -6169,6 +6714,11 @@ Actívalo en ajustes de *Servidores y Redes*. Dirección SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + Simplex Chat y Flux han acordado incluir servidores operados por Flux en la aplicación + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. La seguridad de SimpleX Chat ha sido auditada por Trail of Bits. @@ -6199,6 +6749,16 @@ Actívalo en ajustes de *Servidores y Redes*. Dirección SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + Compartir los enlaces de un uso y las direcciones SimpleX es seguro a través de cualquier medio. + No comment provided by engineer. + + + SimpleX address or 1-time link? + ¿Dirección SimpleX o enlace de un uso? + No comment provided by engineer. + SimpleX contact address Dirección de contacto SimpleX @@ -6219,8 +6779,8 @@ Actívalo en ajustes de *Servidores y Redes*. Enlaces SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. Los enlaces SimpleX no se permiten en este grupo. No comment provided by engineer. @@ -6234,6 +6794,11 @@ Actívalo en ajustes de *Servidores y Redes*. Invitación SimpleX de un uso simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Protocolos de SimpleX auditados por Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Modo incógnito simplificado @@ -6264,6 +6829,11 @@ Actívalo en ajustes de *Servidores y Redes*. Suave blur media + + Some app settings were not migrated. + Algunas configuraciones de la app no han sido migradas. + No comment provided by engineer. + Some file(s) were not exported: Algunos archivos no han sido exportados: @@ -6279,6 +6849,13 @@ Actívalo en ajustes de *Servidores y Redes*. Han ocurrido algunos errores no críticos durante la importación: No comment provided by engineer. + + Some servers failed the test: +%@ + Algunos servidores no han superado la prueba: +%@ + alert message + Somebody Alguien @@ -6329,11 +6906,6 @@ Actívalo en ajustes de *Servidores y Redes*. Parar SimpleX No comment provided by engineer. - - Stop chat to enable database actions - Para habilitar las acciones sobre la base de datos, debes parar SimpleX - 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. Para poder exportar, importar o eliminar la base de datos primero debes parar SimpleX. Mientras tanto no podrás recibir ni enviar mensajes. @@ -6362,12 +6934,12 @@ Actívalo en ajustes de *Servidores y Redes*. Stop sharing Dejar de compartir - No comment provided by engineer. + alert action Stop sharing address? ¿Dejar de compartir la dirección? - No comment provided by engineer. + alert title Stopping chat @@ -6404,6 +6976,16 @@ Actívalo en ajustes de *Servidores y Redes*. Soporte SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Intercambia audio y video durante la llamada. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Cambia el perfil de chat para invitaciones de un solo uso. + No comment provided by engineer. + System Sistema @@ -6439,11 +7021,21 @@ Actívalo en ajustes de *Servidores y Redes*. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Cola + No comment provided by engineer. + Take picture Tomar foto No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Pulsa Crear dirección SimpleX en el menú para crearla más tarde. + No comment provided by engineer. + Tap button Pulsa el botón @@ -6486,7 +7078,7 @@ Actívalo en ajustes de *Servidores y Redes*. Test failed at step %@. - La prueba ha fallado en el paso %@. + Prueba no superada en el paso %@. server test failure @@ -6501,8 +7093,8 @@ Actívalo en ajustes de *Servidores y Redes*. Tests failed! - ¡Pruebas fallidas! - No comment provided by engineer. + ¡Pruebas no superadas! + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7111,6 @@ Actívalo en ajustes de *Servidores y Redes*. ¡Nuestro agradecimiento a todos los colaboradores! Puedes contribuir a través de Weblate No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - La primera plataforma sin identificadores de usuario: diseñada para la privacidad. - No comment provided by engineer. - 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. @@ -6536,9 +7123,14 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. La aplicación puede notificarte cuando recibas mensajes o solicitudes de contacto: por favor, abre la configuración para activarlo. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + La aplicación protege tu privacidad mediante el uso de diferentes operadores en cada conversación. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). - La aplicación pedirá que confirmes las descargas desde servidores de archivos desconocidos (excepto .onion). + La aplicación pedirá que confirmes las descargas desde servidores de archivos desconocidos (excepto si son .onion). No comment provided by engineer. @@ -6551,6 +7143,11 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. El código QR escaneado no es un enlace SimpleX. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + La conexión ha alcanzado el límite de mensajes no entregados. es posible que tu contacto esté desconectado. + No comment provided by engineer. + The connection you accepted will be cancelled! ¡La conexión que has aceptado se cancelará! @@ -6571,6 +7168,11 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. El cifrado funciona y un cifrado nuevo no es necesario. ¡Podría dar lugar a errores de conexión! No comment provided by engineer. + + The future of messaging + La nueva generación de mensajería privada + No comment provided by engineer. + The hash of the previous message is different. El hash del mensaje anterior es diferente. @@ -6596,11 +7198,6 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. Los mensajes serán marcados como moderados para todos los miembros. No comment provided by engineer. - - The next generation of private messaging - La nueva generación de mensajería privada - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. La base de datos antigua no se eliminó durante la migración, puede eliminarse. @@ -6611,6 +7208,21 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. El perfil sólo se comparte con tus contactos. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Las mismas condiciones se aplicarán al operador **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Las mismas condiciones se aplicarán a el/los operador(es) **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + ¡Segundo operador predefinido! + No comment provided by engineer. + The second tick we missed! ✅ ¡El doble check que nos faltaba! ✅ @@ -6623,7 +7235,12 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. The servers for new connections of your current chat profile **%@**. - Lista de servidores para las conexiones nuevas de tu perfil actual **%@**. + Lista de servidores para las conexiones nuevas del perfil **%@**. + No comment provided by engineer. + + + The servers for new files of your current chat profile **%@**. + Los servidores para archivos nuevos en tu perfil actual **%@**. No comment provided by engineer. @@ -6631,11 +7248,21 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. El texto pegado no es un enlace SimpleX. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + El archivo de bases de datos subido será eliminado permanentemente de los servidores. + No comment provided by engineer. + Themes Temas No comment provided by engineer. + + These conditions will also apply for: **%@**. + Estas condiciones también se aplican para: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Esta configuración afecta a tu perfil actual **%@**. @@ -6736,9 +7363,9 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida. 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 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. + + To protect against your link being replaced, you can compare contact security codes. + Para protegerte contra una sustitución del enlace, puedes comparar los códigos de seguridad con tu contacto. No comment provided by engineer. @@ -6758,6 +7385,26 @@ You will be prompted to complete authentication before this feature is enabled.< Se te pedirá que completes la autenticación antes de activar esta función. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs 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 receive + Para recibir + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Para grabación de voz, por favor concede el permiso para usar el micrófono. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Para grabación de vídeo, por favor concede el permiso para usar la cámara. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Para grabar el mensaje de voz concede permiso para usar el micrófono. @@ -6768,11 +7415,21 @@ Se te pedirá que completes la autenticación antes de activar esta función.Para hacer visible tu perfil oculto, introduce la contraseña en el campo de búsqueda del menú **Mis perfiles**. No comment provided by engineer. + + To send + Para enviar + No comment provided by engineer. + 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 use the servers of **%@**, accept conditions of use. + Para usar los servidores de **%@**, acepta las condiciones de uso. + No comment provided by engineer. + 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. @@ -6863,6 +7520,11 @@ Se te pedirá que completes la autenticación antes de activar esta función.¿Desbloquear miembro? No comment provided by engineer. + + Undelivered messages + Mensajes no entregados + No comment provided by engineer. + Unexpected migration state Estado de migración inesperado @@ -6911,7 +7573,7 @@ Se te pedirá que completes la autenticación antes de activar esta función. Unknown servers! ¡Servidores desconocidos! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7682,21 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Subiendo archivo No comment provided by engineer. + + Use %@ + Usar %@ + No comment provided by engineer. + Use .onion hosts Usar hosts .onion No comment provided by engineer. + + Use SOCKS proxy + Usar proxy SOCKS + No comment provided by engineer. + Use SimpleX Chat servers? ¿Usar servidores SimpleX Chat? @@ -7040,6 +7712,16 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Usar perfil actual No comment provided by engineer. + + Use for files + Usar para archivos + No comment provided by engineer. + + + Use for messages + Usar para mensajes + No comment provided by engineer. + Use for new connections Usar para conexiones nuevas @@ -7080,6 +7762,11 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Usar servidor No comment provided by engineer. + + Use servers + Usar servidores + No comment provided by engineer. + Use the app while in the call. Usar la aplicación durante la llamada. @@ -7087,12 +7774,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Use the app with one hand. - Usa la aplicación con una mano. - No comment provided by engineer. - - - User profile - Perfil de usuario + Usa la aplicación con una sola mano. No comment provided by engineer. @@ -7100,6 +7782,11 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Selección de usuarios No comment provided by engineer. + + Username + Nombre de usuario + No comment provided by engineer. + Using SimpleX Chat servers. Usar servidores SimpleX Chat. @@ -7170,11 +7857,21 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Vídeos y archivos de hasta 1Gb No comment provided by engineer. + + View conditions + Ver condiciones + No comment provided by engineer. + View security code Mostrar código de seguridad No comment provided by engineer. + + View updated conditions + Ver condiciones actualizadas + No comment provided by engineer. + Visible history Historial visible @@ -7190,8 +7887,8 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Los mensajes de voz no están permitidos en este chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Los mensajes de voz no están permitidos en este grupo. No comment provided by engineer. @@ -7285,9 +7982,9 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Al iniciar llamadas de audio y vídeo. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Cuando alguien solicite conectarse podrás aceptar o rechazar la solicitud. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Cuando está habilitado más de un operador, ninguno dispone de los metadatos para conocer quién se comunica con quién. No comment provided by engineer. @@ -7333,7 +8030,7 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Sin Tor o VPN, tu dirección IP será visible para estos servidores XFTP: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8057,6 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión Servidor XFTP No comment provided by engineer. - - You - - No comment provided by engineer. - You **must not** use the same database on two devices. **No debes** usar la misma base de datos en dos dispositivos. @@ -7387,7 +8079,12 @@ Para conectarte pide a tu contacto que cree otro enlace y comprueba la conexión You are already connected to %@. - Ya estás conectado a %@. + Ya estás conectado con %@. + No comment provided by engineer. + + + You are already connected with %@. + Ya estás conectado con %@. No comment provided by engineer. @@ -7449,7 +8146,17 @@ Repeat join request? You can change it in Appearance settings. - Puede cambiarlo desde el menú Apariencia. + Puedes cambiar la posición de la barra desde el menú Apariencia. + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + Puedes configurar los operadores desde Servidores y Redes. + No comment provided by engineer. + + + You can configure servers via settings. + Puedes configurar los servidores a través de su configuración. No comment provided by engineer. @@ -7492,6 +8199,11 @@ Repeat join request? Puedes enviar mensajes a %@ desde Contactos archivados. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + Puedes añadir un nombre a la conexión para recordar a quién corresponde. + No comment provided by engineer. + You can set lock screen notification preview via settings. Puedes configurar las notificaciones de la pantalla de bloqueo desde Configuración. @@ -7507,11 +8219,6 @@ Repeat join request? 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 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 @@ -7535,23 +8242,23 @@ Repeat join request? 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. + alert message You can't send messages! ¡No puedes enviar mensajes! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Tú controlas a través de qué servidor(es) **recibes** los mensajes. Tus contactos controlan a través de qué servidor(es) **envías** tus mensajes. - 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 decide who can connect. + Tu decides quién se conecta. + No comment provided by engineer. + You have already requested connection via this address! ¡Ya has solicitado la conexión mediante esta dirección! @@ -7654,6 +8361,11 @@ Repeat connection request? Seguirás recibiendo llamadas y notificaciones de los perfiles silenciados cuando estén activos. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + Dejarás de recibir mensajes de este chat. El historial del chat se conserva. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Dejarás de recibir mensajes de este grupo. El historial del chat se conservará. @@ -7674,11 +8386,6 @@ Repeat connection request? 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 %@ - No comment provided by engineer. - Your ICE servers Servidores ICE @@ -7694,11 +8401,6 @@ Repeat connection request? Mi dirección SimpleX No comment provided by engineer. - - Your XFTP servers - Servidores XFTP - No comment provided by engineer. - Your calls Llamadas @@ -7714,11 +8416,21 @@ Repeat connection request? La base de datos no está cifrada - establece una contraseña para cifrarla. No comment provided by engineer. + + Your chat preferences + Tus preferencias de chat + alert title + Your chat profiles Mis perfiles No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). El contacto ha enviado un archivo mayor al máximo admitido (%@). @@ -7734,6 +8446,11 @@ Repeat connection request? Tus contactos permanecerán conectados. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Tus credenciales podrían ser enviadas sin cifrar. + No comment provided by engineer. + 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. @@ -7764,13 +8481,16 @@ Repeat connection request? El perfil **%@** será compartido. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. -Los servidores SimpleX no pueden ver tu perfil. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos. + alert message + Your profile, contacts and delivered messages are stored on your device. Tu perfil, contactos y mensajes se almacenan en tu dispositivo. @@ -7781,14 +8501,14 @@ Los servidores SimpleX no pueden ver tu perfil. Tu perfil aleatorio No comment provided by engineer. - - Your server - Tu servidor - No comment provided by engineer. - Your server address - Dirección de tu servidor + Dirección del servidor + No comment provided by engineer. + + + Your servers + Tus servidores No comment provided by engineer. @@ -7831,6 +8551,11 @@ Los servidores SimpleX no pueden ver tu perfil. llamada aceptada call status + + accepted invitation + invitación aceptada + chat list item title + admin administrador @@ -8019,7 +8744,7 @@ Los servidores SimpleX no pueden ver tu perfil. connecting… conectando… - chat list item title + No comment provided by engineer. connection established @@ -8208,7 +8933,12 @@ Los servidores SimpleX no pueden ver tu perfil. expired - expirado + expirados + No comment provided by engineer. + + + for better metadata privacy. + para mejorar la privacidad de los metadatos. No comment provided by engineer. @@ -8500,7 +9230,7 @@ Los servidores SimpleX no pueden ver tu perfil. removed profile picture - imagen de perfil eliminada + ha eliminado la imagen del perfil profile update event chat item @@ -8508,6 +9238,11 @@ Los servidores SimpleX no pueden ver tu perfil. te ha expulsado rcv group event chat item + + requested to connect + solicitado para conectar + chat list item title + saved guardado @@ -8564,7 +9299,7 @@ last received msg: %2$@ set new profile picture - nueva imagen de perfil + tiene nueva imagen del perfil profile update event chat item @@ -8833,6 +9568,38 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + %d evento(s) nuevo(s) + notification body + + + From: %@ + De: %@ + notification body + + + New events + Eventos nuevos + notification + + + New messages + Mensajes nuevos + notification + + + New messages in %d chats + Mensajes nuevos en %d chat(s) + notification body + + +
@@ -8912,7 +9679,7 @@ last received msg: %2$@ Database passphrase is different from saved in the keychain. - La contraseña de la base de datos es distinta a la almacenada en keychain. + La contraseña de la base de datos es diferente a la almacenada en keychain. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/es.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/es.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 211e512a1e..2caa98e25b 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -124,6 +109,14 @@ %@ on vahvistettu No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded No comment provided by engineer. @@ -133,6 +126,10 @@ %@ haluaa muodostaa yhteyden! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members No comment provided by engineer. @@ -152,11 +149,31 @@ %d päivää time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d tuntia time interval + + %d messages not forwarded + alert title + %d min %d min @@ -310,26 +327,21 @@ ) 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 or link for your contact. - **Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille. + + **Create 1-time link**: to create and share a new invitation link. No comment provided by engineer. **Create group**: to create a new group. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Yksityisempi**: tarkista uudet viestit 20 minuutin välein. Laitetunnus jaetaan SimpleX Chat -palvelimen kanssa, mutta ei sitä, kuinka monta yhteystietoa tai viestiä sinulla on. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -342,11 +354,15 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + 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. @@ -445,6 +461,14 @@ 1 viikko time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 minuuttia @@ -514,19 +538,13 @@ Keskeytä osoitteenvaihto? No comment provided by engineer. - - About SimpleX - Tietoja SimpleX:stä - No comment provided by engineer. - About SimpleX Chat Tietoja SimpleX Chatistä No comment provided by engineer. - - About SimpleX address - Tietoja SimpleX osoitteesta + + About operators No comment provided by engineer. @@ -540,6 +558,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Hyväksy yhteyspyyntö? @@ -556,6 +578,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged No comment provided by engineer. @@ -573,13 +599,8 @@ Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi. No comment provided by engineer. - - Add contact - No comment provided by engineer. - - - Add preset servers - Lisää esiasetettuja palvelimia + + Add friends No comment provided by engineer. @@ -597,6 +618,10 @@ Lisää palvelimia skannaamalla QR-koodeja. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Lisää toiseen laitteeseen @@ -607,6 +632,18 @@ Lisää tervetuloviesti No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent No comment provided by engineer. @@ -629,6 +666,14 @@ Osoitteenmuutos keskeytetään. Käytetään vanhaa vastaanotto-osoitetta. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. No comment provided by engineer. @@ -662,8 +707,8 @@ Kaikki tiedot poistetaan, kun se syötetään. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. No comment provided by engineer. @@ -671,6 +716,10 @@ Kaikki ryhmän jäsenet pysyvät yhteydessä. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! No comment provided by engineer. @@ -686,7 +735,7 @@ All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -840,6 +889,11 @@ Vastaa puheluun No comment provided by engineer. + + Anybody can host servers. + Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia. + No comment provided by engineer. + App build: %@ Sovellusversio: %@ @@ -868,6 +922,10 @@ Sovelluksen pääsykoodi korvataan itsetuhoutuvalla pääsykoodilla. No comment provided by engineer. + + App session + No comment provided by engineer. + App version Sovellusversio @@ -967,6 +1025,10 @@ Hyväksy kuvat automaattisesti No comment provided by engineer. + + Auto-accept settings + alert title + Back Takaisin @@ -990,10 +1052,18 @@ Virheellinen viestin tarkiste No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages Parempia viestejä @@ -1003,6 +1073,18 @@ Better networking No comment provided by engineer. + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience + No comment provided by engineer. + Black No comment provided by engineer. @@ -1072,6 +1154,14 @@ Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). Chat-profiilin mukaan (oletus) tai [yhteyden mukaan](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1120,7 +1210,8 @@ Cancel Peruuta - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1138,7 +1229,7 @@ Cannot receive file Tiedostoa ei voi vastaanottaa - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1153,6 +1244,10 @@ Muuta No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Muutetaanko tietokannan tunnuslause? @@ -1199,9 +1294,16 @@ authentication reason set passcode view - - Chat archive - Chat-arkisto + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1259,19 +1361,44 @@ Chat-asetukset No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + Käyttäjäprofiili + No comment provided by engineer. + Chat theme No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Keskustelut No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Tarkista palvelimen osoite ja yritä uudelleen. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1350,15 +1477,47 @@ Completed No comment provided by engineer. + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers Määritä ICE-palvelimet No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm Vahvista @@ -1524,6 +1683,10 @@ This is your own one-time link! Yhteyspyyntö lähetetty! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated No comment provided by engineer. @@ -1616,6 +1779,10 @@ This is your own one-time link! Ydinversio: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? No comment provided by engineer. @@ -1625,6 +1792,10 @@ This is your own one-time link! Luo No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address Luo SimpleX-osoite @@ -1634,11 +1805,6 @@ This is your own one-time link! Create a group using a random profile. No comment provided by engineer. - - Create an address to let people connect with you. - Luo osoite, jolla ihmiset voivat ottaa sinuun yhteyttä. - No comment provided by engineer. - Create file Luo tiedosto @@ -1694,11 +1860,6 @@ This is your own one-time link! Created at: %@ copied message info - - Created on %@ - Luotu %@ - No comment provided by engineer. - Creating archive link No comment provided by engineer. @@ -1712,6 +1873,10 @@ This is your own one-time link! Nykyinen pääsykoodi No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Nykyinen tunnuslause… @@ -1731,6 +1896,10 @@ This is your own one-time link! Mukautettu aika No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme No comment provided by engineer. @@ -1859,7 +2028,8 @@ This is your own one-time link! Delete Poista - chat item action + alert action + chat item action swipe action @@ -1894,14 +2064,8 @@ This is your own one-time link! Delete and notify contact No comment provided by engineer. - - Delete archive - Poista arkisto - No comment provided by engineer. - - - Delete chat archive? - Poista keskusteluarkisto? + + Delete chat No comment provided by engineer. @@ -1914,6 +2078,10 @@ This is your own one-time link! Poista keskusteluprofiili? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Poista yhteys @@ -2017,6 +2185,10 @@ This is your own one-time link! Poista vanha tietokanta? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? Poistetaanko odottava yhteys? @@ -2063,6 +2235,10 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Toimitus @@ -2154,8 +2330,12 @@ This is your own one-time link! Yksityisviestit chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Yksityisviestit jäsenten välillä ovat kiellettyjä tässä ryhmässä. No comment provided by engineer. @@ -2193,8 +2373,8 @@ This is your own one-time link! Katoavat viestit ovat kiellettyjä tässä keskustelussa. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Katoavat viestit ovat kiellettyjä tässä ryhmässä. No comment provided by engineer. @@ -2248,6 +2428,10 @@ This is your own one-time link! Do not send history to new members. No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address Älä luo osoitetta @@ -2270,7 +2454,8 @@ This is your own one-time link! Download - chat item action + alert button + chat item action Download errors @@ -2285,6 +2470,10 @@ This is your own one-time link! Lataa tiedosto server test step + + Download files + alert action + Downloaded No comment provided by engineer. @@ -2311,6 +2500,10 @@ This is your own one-time link! Kesto No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Muokkaa @@ -2331,6 +2524,10 @@ This is your own one-time link! Salli (pidä ohitukset) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Ota SimpleX Lock käyttöön @@ -2524,26 +2721,33 @@ This is your own one-time link! Virhe osoitteenmuutoksen keskeytyksessä No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request Virhe kontaktipyynnön hyväksymisessä No comment provided by engineer. - - Error accessing database file - Virhe tietokantatiedoston käyttämisessä - No comment provided by engineer. - Error adding member(s) Virhe lisättäessä jäseniä No comment provided by engineer. + + Error adding server + alert title + Error changing address Virhe osoitteenvaihdossa No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role Virhe roolin vaihdossa @@ -2554,6 +2758,10 @@ This is your own one-time link! Virhe asetuksen muuttamisessa No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. No comment provided by engineer. @@ -2664,9 +2872,12 @@ This is your own one-time link! Virhe ryhmään liittymisessä No comment provided by engineer. - - Error loading %@ servers - Virhe %@-palvelimien lataamisessa + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. @@ -2676,7 +2887,7 @@ This is your own one-time link! Error receiving file Virhe tiedoston vastaanottamisessa - No comment provided by engineer. + alert title Error reconnecting server @@ -2695,11 +2906,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - Virhe %@ palvelimien tallentamisessa - No comment provided by engineer. - Error saving ICE servers Virhe ICE-palvelimien tallentamisessa @@ -2720,6 +2926,10 @@ This is your own one-time link! Virhe tunnuslauseen tallentamisessa avainnippuun No comment provided by engineer. + + Error saving servers + alert title + Error saving settings when migrating @@ -2762,10 +2972,14 @@ This is your own one-time link! Virhe keskustelun lopettamisessa No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! Virhe profiilin vaihdossa! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2782,6 +2996,10 @@ This is your own one-time link! Virhe viestin päivityksessä No comment provided by engineer. + + Error updating server + alert title + Error updating settings Virhe asetusten päivittämisessä @@ -2808,8 +3026,7 @@ This is your own one-time link! Error: %@ Virhe: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2825,6 +3042,10 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. Jopa kun ei käytössä keskustelussa. @@ -2890,6 +3111,11 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. file error text @@ -2940,8 +3166,8 @@ This is your own one-time link! Tiedostot ja media chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Tiedostot ja media ovat tässä ryhmässä kiellettyjä. No comment provided by engineer. @@ -3007,19 +3233,51 @@ This is your own one-time link! Ryhmän jäsen ei tue korjausta No comment provided by engineer. + + For chat profile %@: + servers error + For console Konsoliin No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward chat item action + + Forward %d message(s)? + alert title + Forward and save messages No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded No comment provided by engineer. @@ -3028,6 +3286,10 @@ This is your own one-time link! Forwarded from No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. No comment provided by engineer. @@ -3069,11 +3331,6 @@ Error: %2$@ Koko nimi (valinnainen) No comment provided by engineer. - - Full name: - Koko nimi: - No comment provided by engineer. - Fully decentralized – visible only to members. No comment provided by engineer. @@ -3154,40 +3411,6 @@ Error: %2$@ Ryhmälinkit No comment provided by engineer. - - 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. (24 hours) - Ryhmän jäsenet voivat poistaa lähetetyt viestit peruuttamattomasti. (24 tuntia) - No comment provided by engineer. - - - Group members can send SimpleX links. - No comment provided by engineer. - - - Group members can send direct messages. - Ryhmän jäsenet voivat lähettää suoraviestejä. - No comment provided by engineer. - - - Group members can send disappearing messages. - Ryhmän jäsenet voivat lähettää katoavia viestejä. - No comment provided by engineer. - - - Group members can send files and media. - Ryhmän jäsenet voivat lähettää tiedostoja ja mediaa. - No comment provided by engineer. - - - Group members can send voice messages. - Ryhmän jäsenet voivat lähettää ääniviestejä. - No comment provided by engineer. - Group message: Ryhmäviesti: @@ -3282,9 +3505,12 @@ Error: %2$@ Miten SimpleX toimii No comment provided by engineer. - - How it works - Kuinka se toimii + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3311,6 +3537,10 @@ Error: %2$@ ICE-palvelimet (yksi per rivi) No comment provided by engineer. + + IP address + 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. @@ -3351,8 +3581,8 @@ Error: %2$@ Heti No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Immuuni roskapostille ja väärinkäytöksille No comment provided by engineer. @@ -3383,6 +3613,11 @@ Error: %2$@ Importing archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery No comment provided by engineer. @@ -3478,6 +3713,11 @@ Error: %2$@ Asenna [SimpleX Chat terminaalille](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Heti + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3485,11 +3725,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Heti - No comment provided by engineer. - Interface Käyttöliittymä @@ -3531,7 +3766,7 @@ Error: %2$@ Invalid server address! Virheellinen palvelinosoite! - No comment provided by engineer. + alert title Invalid status @@ -3553,6 +3788,10 @@ Error: %2$@ Kutsu jäseniä No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Kutsu ryhmään @@ -3568,8 +3807,8 @@ Error: %2$@ Viestien peruuttamaton poisto on kielletty tässä keskustelussa. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Viestien peruuttamaton poisto on kielletty tässä ryhmässä. No comment provided by engineer. @@ -3652,7 +3891,7 @@ This is your link for group %@! Keep - No comment provided by engineer. + alert action Keep conversation @@ -3664,7 +3903,7 @@ This is your link for group %@! Keep unused invitation? - No comment provided by engineer. + alert title Keep your connections @@ -3701,6 +3940,14 @@ This is your link for group %@! Poistu swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Poistu ryhmästä @@ -3748,11 +3995,6 @@ This is your link for group %@! Live-viestit No comment provided by engineer. - - Local - Paikallinen - No comment provided by engineer. - Local name Paikallinen nimi @@ -3773,11 +4015,6 @@ This is your link for group %@! Lukitustila No comment provided by engineer. - - Make a private connection - Luo yksityinen yhteys - No comment provided by engineer. - Make one message disappear Hävitä yksi viesti @@ -3788,21 +4025,11 @@ This is your link for group %@! Tee profiilista yksityinen! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Varmista, että %@-palvelinosoitteet ovat oikeassa muodossa, että ne on erotettu toisistaan riveittäin ja että ne eivät ole päällekkäisiä (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Varmista, että WebRTC ICE -palvelinosoitteet ovat oikeassa muodossa, rivieroteltuina ja että ne eivät ole päällekkäisiä. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Monet ihmiset kysyivät: *Jos SimpleX:llä ei ole käyttäjätunnuksia, miten se voi toimittaa viestejä?* - No comment provided by engineer. - Mark deleted for everyone Merkitse poistetuksi kaikilta @@ -3845,6 +4072,10 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Jäsenen rooli muuttuu muotoon "%@". Kaikille ryhmän jäsenille ilmoitetaan asiasta. @@ -3855,11 +4086,49 @@ This is your link for group %@! Jäsenen rooli muutetaan muotoon "%@". Jäsen saa uuden kutsun. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Jäsen poistetaan ryhmästä - tätä ei voi perua! No comment provided by engineer. + + Members can add message reactions. + Ryhmän jäsenet voivat lisätä viestireaktioita. + No comment provided by engineer. + + + 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. + + + Members can send SimpleX links. + No comment provided by engineer. + + + Members can send direct messages. + Ryhmän jäsenet voivat lähettää suoraviestejä. + No comment provided by engineer. + + + Members can send disappearing messages. + Ryhmän jäsenet voivat lähettää katoavia viestejä. + No comment provided by engineer. + + + Members can send files and media. + Ryhmän jäsenet voivat lähettää tiedostoja ja mediaa. + No comment provided by engineer. + + + Members can send voice messages. + Ryhmän jäsenet voivat lähettää ääniviestejä. + No comment provided by engineer. + Menus No comment provided by engineer. @@ -3905,8 +4174,8 @@ This is your link for group %@! Viestireaktiot ovat kiellettyjä tässä keskustelussa. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Viestireaktiot ovat kiellettyjä tässä ryhmässä. No comment provided by engineer. @@ -3918,6 +4187,10 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3961,6 +4234,10 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. No comment provided by engineer. @@ -4017,9 +4294,9 @@ This is your link for group %@! Siirto on valmis No comment provided by engineer. - - Migrations: %@ - Siirrot: %@ + + Migrations: + Siirrot: No comment provided by engineer. @@ -4046,6 +4323,10 @@ This is your link for group %@! More reliable network connection. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Todennäköisesti tämä yhteys on poistettu. @@ -4080,6 +4361,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. snd error text @@ -4088,6 +4373,10 @@ This is your link for group %@! Network management No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Verkkoasetukset @@ -4103,6 +4392,14 @@ This is your link for group %@! Uusi pääsykoodi No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat No comment provided by engineer. @@ -4121,11 +4418,6 @@ This is your link for group %@! Uusi kontakti: notification - - New database archive - Uusi tietokanta-arkisto - No comment provided by engineer. - New desktop app! No comment provided by engineer. @@ -4135,6 +4427,10 @@ This is your link for group %@! Uusi näyttönimi No comment provided by engineer. + + New events + notification + New in %@ Uutta %@ @@ -4159,6 +4455,10 @@ This is your link for group %@! Uusi tunnuslause… No comment provided by engineer. + + New server + No comment provided by engineer. + No Ei @@ -4212,20 +4512,62 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message Ei lupaa ääniviestin tallentamiseen No comment provided by engineer. + + No push server + Paikallinen + No comment provided by engineer. + No received or sent files Ei vastaanotettuja tai lähetettyjä tiedostoja No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Ensimmäinen alusta ilman käyttäjätunnisteita – suunniteltu yksityiseksi. + No comment provided by engineer. + Not compatible! No comment provided by engineer. @@ -4234,6 +4576,10 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + alert title + Notifications Ilmoitukset @@ -4244,6 +4590,10 @@ This is your link for group %@! Ilmoitukset on poistettu käytöstä! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4265,18 +4615,13 @@ This is your link for group %@! Ok Ok - No comment provided by engineer. + alert button Old database Vanha tietokanta No comment provided by engineer. - - Old database archive - Vanha tietokanta-arkisto - No comment provided by engineer. - One-time invitation link Kertakutsulinkki @@ -4301,8 +4646,12 @@ Edellyttää VPN:n sallimista. Onion-isäntiä ei käytetä. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Vain asiakaslaitteet tallentavat käyttäjäprofiileja, yhteystietoja, ryhmiä ja viestejä, jotka on lähetetty **kaksinkertaisella päästä päähän -salauksella**. No comment provided by engineer. @@ -4384,6 +4733,10 @@ Edellyttää VPN:n sallimista. Avaa Asetukset No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Avaa keskustelu @@ -4394,6 +4747,10 @@ Edellyttää VPN:n sallimista. Avaa keskustelukonsoli authentication reason + + Open conditions + No comment provided by engineer. + Open group No comment provided by engineer. @@ -4402,24 +4759,22 @@ Edellyttää VPN:n sallimista. Open migration to another device authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - Avaa käyttäjäprofiilit - authentication reason - - - 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 app… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link No comment provided by engineer. @@ -4436,13 +4791,18 @@ Edellyttää VPN:n sallimista. Or show this code No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4479,6 +4839,10 @@ Edellyttää VPN:n sallimista. Pääsykoodi asetettu! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show Salasana näytettäväksi @@ -4509,13 +4873,8 @@ Edellyttää VPN:n sallimista. Pending No comment provided by engineer. - - People can connect to you only via the links you share. - Ihmiset voivat ottaa sinuun yhteyttä vain jakamiesi linkkien kautta. - No comment provided by engineer. - - - Periodically + + Periodic Ajoittain No comment provided by engineer. @@ -4615,6 +4974,10 @@ Error: %@ Puolalainen käyttöliittymä No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Palvelimen osoitteen varmenteen sormenjälki on mahdollisesti virheellinen @@ -4625,16 +4988,15 @@ Error: %@ Säilytä viimeinen viestiluonnos liitteineen. No comment provided by engineer. - - Preset server - Esiasetettu palvelin - No comment provided by engineer. - Preset server address Esiasetettu palvelimen osoite No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview Esikatselu @@ -4649,6 +5011,10 @@ Error: %@ Yksityisyys ja turvallisuus No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Yksityisyys uudelleen määritettynä @@ -4693,14 +5059,6 @@ Error: %@ Profile images No comment provided by engineer. - - Profile name - No comment provided by engineer. - - - Profile name: - No comment provided by engineer. - Profile password Profiilin salasana @@ -4713,7 +5071,7 @@ Error: %@ Profile update will be sent to your contacts. Profiilipäivitys lähetetään kontakteillesi. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4796,6 +5154,10 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + No comment provided by engineer. + Push notifications Push-ilmoitukset @@ -4833,25 +5195,20 @@ Enable in *Network & servers* settings. Lue lisää No comment provided by engineer. - - Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). - Lue lisää [Käyttöoppaasta](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). No comment provided by engineer. + + Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + No comment provided by engineer. + Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/readme.html#connect-to-friends). No comment provided by engineer. - - Read more in our GitHub repository. - Lue lisää GitHub-tietovarastostamme. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Lue lisää [GitHub-arkistosta](https://github.com/simplex-chat/simplex-chat#readme). @@ -5002,6 +5359,10 @@ Enable in *Network & servers* settings. Poista No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image No comment provided by engineer. @@ -5140,6 +5501,14 @@ Enable in *Network & servers* settings. Paljasta chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke Peruuta @@ -5169,6 +5538,10 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + No comment provided by engineer. + Safely receive files No comment provided by engineer. @@ -5180,17 +5553,18 @@ Enable in *Network & servers* settings. Save Tallenna - chat item action + alert button + chat item action Save (and notify contacts) Tallenna (ja ilmoita kontakteille) - No comment provided by engineer. + alert button Save and notify contact Tallenna ja ilmoita kontaktille - No comment provided by engineer. + alert button Save and notify group members @@ -5206,16 +5580,6 @@ Enable in *Network & servers* settings. Tallenna ja päivitä ryhmäprofiili No comment provided by engineer. - - Save archive - Tallenna arkisto - No comment provided by engineer. - - - Save auto-accept settings - Tallenna automaattisen hyväksynnän asetukset - No comment provided by engineer. - Save group profile Tallenna ryhmäprofiili @@ -5234,7 +5598,7 @@ Enable in *Network & servers* settings. Save preferences? Tallenna asetukset? - No comment provided by engineer. + alert title Save profile password @@ -5249,18 +5613,17 @@ Enable in *Network & servers* settings. Save servers? Tallenna palvelimet? - No comment provided by engineer. - - - Save settings? - Tallenna asetukset? - No comment provided by engineer. + alert title Save welcome message? Tallenna tervetuloviesti? No comment provided by engineer. + + Save your profile? + alert title + Saved No comment provided by engineer. @@ -5278,6 +5641,10 @@ Enable in *Network & servers* settings. Saved message message info title + + Saving %lld messages + No comment provided by engineer. + Scale No comment provided by engineer. @@ -5351,6 +5718,10 @@ Enable in *Network & servers* settings. Valitse chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld No comment provided by engineer. @@ -5434,11 +5805,6 @@ Enable in *Network & servers* settings. Lähetys ilmoitukset No comment provided by engineer. - - Send notifications: - Lähetys ilmoitukset: - No comment provided by engineer. - Send questions and ideas Lähetä kysymyksiä ja ideoita @@ -5461,7 +5827,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Lähettäjä peruutti tiedoston siirron. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5553,6 +5919,14 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address No comment provided by engineer. @@ -5565,6 +5939,18 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Palvelin vaatii valtuutuksen jonojen luomiseen, tarkista salasana @@ -5662,6 +6048,10 @@ Enable in *Network & servers* settings. Asetukset No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images No comment provided by engineer. @@ -5669,22 +6059,35 @@ Enable in *Network & servers* settings. Share Jaa - chat item action + alert action + chat item action Share 1-time link Jaa kertakäyttölinkki No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Jaa osoite No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Jaa osoite kontakteille? - No comment provided by engineer. + alert title Share from other apps. @@ -5695,6 +6098,10 @@ Enable in *Network & servers* settings. Jaa linkki No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link No comment provided by engineer. @@ -5758,6 +6165,10 @@ Enable in *Network & servers* settings. SimpleX-osoite No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Trail of Bits on tarkastanut SimpleX Chatin tietoturvan. @@ -5788,6 +6199,14 @@ Enable in *Network & servers* settings. SimpleX-osoite No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX-yhteystiedot @@ -5808,8 +6227,8 @@ Enable in *Network & servers* settings. SimpleX-linkit chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. No comment provided by engineer. @@ -5821,6 +6240,10 @@ Enable in *Network & servers* settings. SimpleX-kertakutsu simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode No comment provided by engineer. @@ -5848,6 +6271,10 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: No comment provided by engineer. @@ -5861,6 +6288,11 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Joku @@ -5906,11 +6338,6 @@ Enable in *Network & servers* settings. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - Pysäytä keskustelu tietokantatoimien mahdollistamiseksi - 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. Pysäytä keskustelut viedäksesi, tuodaksesi tai poistaaksesi keskustelujen tietokannan. Et voi vastaanottaa ja lähettää viestejä, kun keskustelut on pysäytetty. @@ -5939,12 +6366,12 @@ Enable in *Network & servers* settings. Stop sharing Lopeta jakaminen - No comment provided by engineer. + alert action Stop sharing address? Lopeta osoitteen jakaminen? - No comment provided by engineer. + alert title Stopping chat @@ -5976,6 +6403,14 @@ Enable in *Network & servers* settings. SimpleX Chat tuki No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System Järjestelmä @@ -6010,11 +6445,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture Ota kuva No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Napauta painiketta @@ -6069,7 +6512,7 @@ Enable in *Network & servers* settings. Tests failed! Testit epäonnistuivat! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6086,11 +6529,6 @@ Enable in *Network & servers* settings. Kiitokset käyttäjille – osallistu Weblaten kautta! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Ensimmäinen alusta ilman käyttäjätunnisteita – suunniteltu yksityiseksi. - No comment provided by engineer. - 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. @@ -6103,6 +6541,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Sovellus voi ilmoittaa sinulle, kun saat viestejä tai yhteydenottopyyntöjä - avaa asetukset ottaaksesi ne käyttöön. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). No comment provided by engineer. @@ -6116,6 +6558,10 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.The code you scanned is not a SimpleX link QR code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Hyväksymäsi yhteys peruuntuu! @@ -6136,6 +6582,11 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Salaus toimii ja uutta salaussopimusta ei tarvita. Tämä voi johtaa yhteysvirheisiin! No comment provided by engineer. + + The future of messaging + Seuraavan sukupolven yksityisviestit + No comment provided by engineer. + The hash of the previous message is different. Edellisen viestin tarkiste on erilainen. @@ -6159,11 +6610,6 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - Seuraavan sukupolven yksityisviestit - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa. @@ -6174,6 +6620,18 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Profiili jaetaan vain kontaktiesi kanssa. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Toinen kuittaus, joka uupui! ✅ @@ -6189,14 +6647,26 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Palvelimet nykyisen keskusteluprofiilisi uusille yhteyksille **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + No comment provided by engineer. + The text you pasted is not a SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Nämä asetukset koskevat nykyistä profiiliasi **%@**. @@ -6288,9 +6758,8 @@ Tämä voi johtua jostain virheestä tai siitä, että yhteys on vaarantunut.Uuden yhteyden luominen 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. - Yksityisyyden suojaamiseksi kaikkien muiden alustojen käyttämien käyttäjätunnusten sijaan SimpleX käyttää viestijonojen tunnisteita, jotka ovat kaikille kontakteille erillisiä. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6309,6 +6778,23 @@ You will be prompted to complete authentication before this feature is enabled.< Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus otetaan käyttöön. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Yksityisyyden suojaamiseksi kaikkien muiden alustojen käyttämien käyttäjätunnusten sijaan SimpleX käyttää viestijonojen tunnisteita, jotka ovat kaikille kontakteille erillisiä. + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Jos haluat nauhoittaa ääniviestin, anna lupa käyttää mikrofonia. @@ -6319,11 +6805,19 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Voit paljastaa piilotetun profiilisi syöttämällä koko salasanan hakukenttään **Keskusteluprofiilisi** -sivulla. No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Keskustelujen-tietokanta on siirrettävä välittömien push-ilmoitusten tukemiseksi. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Voit tarkistaa päästä päähän -salauksen kontaktisi kanssa vertaamalla (tai skannaamalla) laitteidenne koodia. @@ -6403,6 +6897,10 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Unblock member? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state Odottamaton siirtotila @@ -6450,7 +6948,7 @@ Sinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus ote Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6550,11 +7048,19 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Uploading archive No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts Käytä .onion-isäntiä No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? Käytä SimpleX Chat palvelimia? @@ -6570,6 +7076,14 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Käytä nykyistä profiilia No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Käytä uusiin yhteyksiin @@ -6606,6 +7120,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Käytä palvelinta No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. No comment provided by engineer. @@ -6614,15 +7132,14 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Use the app with one hand. No comment provided by engineer. - - User profile - Käyttäjäprofiili - No comment provided by engineer. - User selection No comment provided by engineer. + + Username + No comment provided by engineer. + Using SimpleX Chat servers. Käyttää SimpleX Chat -palvelimia. @@ -6687,11 +7204,19 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Videot ja tiedostot 1 Gt asti No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Näytä turvakoodi No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history chat feature @@ -6706,8 +7231,8 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Ääniviestit ovat kiellettyjä tässä keskustelussa. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Ääniviestit ovat kiellettyjä tässä ryhmässä. No comment provided by engineer. @@ -6794,9 +7319,8 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja When connecting audio and video calls. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Kun ihmiset pyytävät yhteyden muodostamista, voit hyväksyä tai hylätä sen. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -6835,7 +7359,7 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -6859,11 +7383,6 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja XFTP server No comment provided by engineer. - - You - Sinä - No comment provided by engineer. - You **must not** use the same database on two devices. No comment provided by engineer. @@ -6888,6 +7407,10 @@ Jos haluat muodostaa yhteyden, pyydä kontaktiasi luomaan toinen yhteyslinkki ja Olet jo muodostanut yhteyden %@:n kanssa. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. No comment provided by engineer. @@ -6940,6 +7463,14 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + No comment provided by engineer. + You can create it later Voit luoda sen myöhemmin @@ -6977,6 +7508,10 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. Voit määrittää lukitusnäytön ilmoituksen esikatselun asetuksista. @@ -6992,11 +7527,6 @@ Repeat join request? Voit jakaa tämän osoitteen kontaktiesi kanssa, jotta ne voivat muodostaa yhteyden **%@** kanssa. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Voit jakaa osoitteesi linkkinä tai QR-koodina - kuka tahansa voi muodostaa yhteyden sinuun. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Voit aloittaa keskustelun sovelluksen Asetukset / Tietokanta kautta tai käynnistämällä sovelluksen uudelleen @@ -7018,23 +7548,23 @@ Repeat join request? You can view invitation link again in connection details. - No comment provided by engineer. + alert message You can't send messages! Et voi lähettää viestejä! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Sinä hallitset, minkä palvelim(i)en kautta **viestit vastaanotetaan**, kontaktisi - palvelimet, joita käytät viestien lähettämiseen niille. - No comment provided by engineer. - You could not be verified; please try again. Sinua ei voitu todentaa; yritä uudelleen. No comment provided by engineer. + + You decide who can connect. + Kimin bağlanabileceğine siz karar verirsiniz. + No comment provided by engineer. + You have already requested connection via this address! No comment provided by engineer. @@ -7129,6 +7659,10 @@ Repeat connection request? Saat edelleen puheluita ja ilmoituksia mykistetyiltä profiileilta, kun ne ovat aktiivisia. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Et enää saa viestejä tästä ryhmästä. Keskusteluhistoria säilytetään. @@ -7149,11 +7683,6 @@ Repeat connection request? Käytät tässä ryhmässä incognito-profiilia. Kontaktien kutsuminen ei ole sallittua, jotta pääprofiilisi ei tule jaetuksi No comment provided by engineer. - - Your %@ servers - %@-palvelimesi - No comment provided by engineer. - Your ICE servers ICE-palvelimesi @@ -7169,11 +7698,6 @@ Repeat connection request? SimpleX-osoitteesi No comment provided by engineer. - - Your XFTP servers - XFTP-palvelimesi - No comment provided by engineer. - Your calls Puhelusi @@ -7189,11 +7713,19 @@ Repeat connection request? Keskustelut-tietokantasi ei ole salattu - aseta tunnuslause sen salaamiseksi. No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles Keskusteluprofiilisi No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Yhteyshenkilösi lähetti tiedoston, joka on suurempi kuin tällä hetkellä tuettu enimmäiskoko (%@). @@ -7209,6 +7741,10 @@ Repeat connection request? Kontaktisi pysyvät yhdistettyinä. No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Nykyinen keskustelut-tietokantasi poistetaan ja korvataan tuodulla tietokannalla. @@ -7238,13 +7774,15 @@ Repeat connection request? Profiilisi **%@** jaetaan. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. -SimpleX-palvelimet eivät näe profiiliasi. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. Profiilisi, kontaktisi ja toimitetut viestit tallennetaan laitteellesi. @@ -7255,16 +7793,15 @@ SimpleX-palvelimet eivät näe profiiliasi. Satunnainen profiilisi No comment provided by engineer. - - Your server - Palvelimesi - No comment provided by engineer. - Your server address Palvelimesi osoite No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings Asetuksesi @@ -7305,6 +7842,10 @@ SimpleX-palvelimet eivät näe profiiliasi. hyväksytty puhelu call status + + accepted invitation + chat list item title + admin ylläpitäjä @@ -7483,7 +8024,7 @@ SimpleX-palvelimet eivät näe profiiliasi. connecting… yhdistää… - chat list item title + No comment provided by engineer. connection established @@ -7670,6 +8211,10 @@ SimpleX-palvelimet eivät näe profiiliasi. expired No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded No comment provided by engineer. @@ -7955,6 +8500,10 @@ SimpleX-palvelimet eivät näe profiiliasi. poisti sinut rcv group event chat item + + requested to connect + chat list item title + saved No comment provided by engineer. @@ -8257,6 +8806,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/fi.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 48a58b075e..148156b07c 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,14 @@ %@ est vérifié·e No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded %@ envoyé @@ -137,6 +130,11 @@ %@ veut se connecter ! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ et %lld membres @@ -157,11 +155,36 @@ %d jours time interval + + %d file(s) are still being downloaded. + %d fichier(s) en cours de téléchargement. + forward confirmation reason + + + %d file(s) failed to download. + Le téléchargement de %d fichier(s) a échoué. + forward confirmation reason + + + %d file(s) were deleted. + Le(s) fichier(s) %d a(ont) été supprimé(s). + forward confirmation reason + + + %d file(s) were not downloaded. + Le(s) fichier(s) %d n'a (n'ont) pas été téléchargé(s). + forward confirmation reason + %d hours %d heures time interval + + %d messages not forwarded + %d messages non transférés + alert title + %d min %d min @@ -322,14 +345,9 @@ ) 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 or link for your contact. - **Ajouter un nouveau contact** : pour créer un lien ou code QR unique pour votre contact. + + **Create 1-time link**: to create and share a new invitation link. + **Ajouter un contact** : pour créer un nouveau lien d'invitation. No comment provided by engineer. @@ -337,13 +355,13 @@ **Créer un groupe** : pour créer un nouveau groupe. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Vie privée** : vérification de nouveaux messages toute les 20 minutes. Le token de l'appareil est partagé avec le serveur SimpleX, mais pas le nombre de messages ou de contacts. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +375,15 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + 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. @@ -468,6 +490,14 @@ 1 semaine time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 minutes @@ -524,7 +554,7 @@ Abort - Annuler + Abandonner No comment provided by engineer. @@ -537,19 +567,13 @@ Abandonner le changement d'adresse ? No comment provided by engineer. - - About SimpleX - À propos de SimpleX - No comment provided by engineer. - About SimpleX Chat À propos de SimpleX Chat No comment provided by engineer. - - About SimpleX address - À propos de l'adresse SimpleX + + About operators No comment provided by engineer. @@ -564,6 +588,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Accepter la demande de connexion ? @@ -580,6 +608,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged Reçu avec accusé de réception @@ -600,14 +632,8 @@ 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 + + Add friends No comment provided by engineer. @@ -625,6 +651,10 @@ Ajoutez des serveurs en scannant des codes QR. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Ajouter à un autre appareil @@ -635,6 +665,18 @@ Ajouter un message d'accueil No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent Accent additionnel @@ -660,6 +702,14 @@ Le changement d'adresse sera annulé. L'ancienne adresse de réception sera utilisée. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. Les admins peuvent bloquer un membre pour tous. @@ -695,8 +745,8 @@ Toutes les données sont effacées lorsqu'il est saisi. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Toutes les données restent confinées dans votre appareil. No comment provided by engineer. @@ -705,6 +755,10 @@ Tous les membres du groupe resteront connectés. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + 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 ! @@ -723,7 +777,7 @@ All profiles Tous les profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -752,6 +806,7 @@ Allow calls? + Autoriser les appels ? No comment provided by engineer. @@ -884,6 +939,11 @@ Répondre à l'appel No comment provided by engineer. + + Anybody can host servers. + N'importe qui peut heberger un serveur. + No comment provided by engineer. + App build: %@ Build de l'app : %@ @@ -914,6 +974,11 @@ Le code d'accès de l'application est remplacé par un code d'autodestruction. No comment provided by engineer. + + App session + Session de l'app + No comment provided by engineer. + App version Version de l'app @@ -941,15 +1006,17 @@ Archive and upload - Archiver et transférer + Archiver et téléverser No comment provided by engineer. Archive contacts to chat later. + Archiver les contacts pour discuter plus tard. No comment provided by engineer. Archived contacts + Contacts archivés No comment provided by engineer. @@ -1017,6 +1084,11 @@ Images auto-acceptées No comment provided by engineer. + + Auto-accept settings + Paramètres de réception automatique + alert title + Back Retour @@ -1042,11 +1114,21 @@ Mauvais hash de message No comment provided by engineer. + + Better calls + Appels améliorés + No comment provided by engineer. + Better groups Des groupes plus performants No comment provided by engineer. + + Better message dates. + Meilleures dates de messages. + No comment provided by engineer. + Better messages Meilleurs messages @@ -1054,6 +1136,22 @@ Better networking + Meilleure gestion de réseau + No comment provided by engineer. + + + Better notifications + Notifications améliorées + No comment provided by engineer. + + + Better security ✅ + Sécurité accrue ✅ + No comment provided by engineer. + + + Better user experience + Une meilleure expérience pour l'utilisateur No comment provided by engineer. @@ -1098,6 +1196,7 @@ Blur for better privacy. + Rendez les images floues et protégez-les contre les regards indiscrets. No comment provided by engineer. @@ -1135,6 +1234,14 @@ Bulgare, finnois, thaïlandais et ukrainien - grâce aux utilisateurs et à [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat) ! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). Par profil de chat (par défaut) ou [par connexion](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1152,6 +1259,7 @@ Calls prohibited! + Les appels ne sont pas autorisés ! No comment provided by engineer. @@ -1161,10 +1269,12 @@ Can't call contact + Impossible d'appeler le contact No comment provided by engineer. Can't call member + Impossible d'appeler le membre No comment provided by engineer. @@ -1179,12 +1289,14 @@ Can't message member + Impossible d'envoyer un message à ce membre No comment provided by engineer. Cancel Annuler - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1204,7 +1316,7 @@ Cannot receive file Impossible de recevoir le fichier - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1221,6 +1333,10 @@ Changer No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Changer la phrase secrète de la base de données ? @@ -1267,9 +1383,16 @@ authentication reason set passcode view - - Chat archive - Archives du chat + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1294,6 +1417,7 @@ Chat database exported + Exportation de la base de données des discussions No comment provided by engineer. @@ -1318,6 +1442,7 @@ Chat list + Liste de discussion No comment provided by engineer. @@ -1330,20 +1455,46 @@ Préférences de chat No comment provided by engineer. + + Chat preferences were changed. + Les préférences de discussion ont été modifiées. + alert message + + + Chat profile + Profil d'utilisateur + No comment provided by engineer. + Chat theme Thème de chat No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Discussions No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Vérifiez l'adresse du serveur et réessayez. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1407,6 +1558,7 @@ Color chats with the new themes. + Colorez vos discussions avec les nouveaux thèmes. No comment provided by engineer. @@ -1426,7 +1578,43 @@ Completed - Complété + Complétées + No comment provided by engineer. + + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. No comment provided by engineer. @@ -1434,11 +1622,6 @@ Configurer les serveurs ICE No comment provided by engineer. - - Configured %@ servers - %@ serveurs configurés - No comment provided by engineer. - Confirm Confirmer @@ -1451,6 +1634,7 @@ Confirm contact deletion? + Confirmer la suppression du contact ? No comment provided by engineer. @@ -1510,6 +1694,7 @@ Connect to your friends faster. + Connectez-vous à vos amis plus rapidement. No comment provided by engineer. @@ -1588,6 +1773,7 @@ Il s'agit de votre propre lien unique ! Connecting to contact, please wait or check later! + Connexion au contact, veuillez patienter ou vérifier plus tard ! No comment provided by engineer. @@ -1602,6 +1788,7 @@ Il s'agit de votre propre lien unique ! Connection and servers status. + État de la connexion et des serveurs. No comment provided by engineer. @@ -1624,6 +1811,10 @@ Il s'agit de votre propre lien unique ! Demande de connexion envoyée ! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated Connexion terminée @@ -1656,6 +1847,7 @@ Il s'agit de votre propre lien unique ! Contact deleted! + Contact supprimé ! No comment provided by engineer. @@ -1670,6 +1862,7 @@ Il s'agit de votre propre lien unique ! Contact is deleted. + Le contact est supprimé. No comment provided by engineer. @@ -1684,6 +1877,7 @@ Il s'agit de votre propre lien unique ! Contact will be deleted - this cannot be undone! + Le contact sera supprimé - il n'est pas possible de revenir en arrière ! No comment provided by engineer. @@ -1703,6 +1897,7 @@ Il s'agit de votre propre lien unique ! Conversation deleted! + Conversation supprimée ! No comment provided by engineer. @@ -1720,6 +1915,11 @@ Il s'agit de votre propre lien unique ! Version du cœur : v%@ No comment provided by engineer. + + Corner + Coin + No comment provided by engineer. + Correct name to %@? Corriger le nom pour %@ ? @@ -1730,6 +1930,10 @@ Il s'agit de votre propre lien unique ! Créer No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address Créer une adresse SimpleX @@ -1740,11 +1944,6 @@ Il s'agit de votre propre lien unique ! Création de groupes via un profil aléatoire. No comment provided by engineer. - - Create an address to let people connect with you. - Vous pouvez créer une adresse pour permettre aux autres utilisateurs de vous contacter. - No comment provided by engineer. - Create file Créer un fichier @@ -1792,7 +1991,7 @@ Il s'agit de votre propre lien unique ! Created - Créé + Créées No comment provided by engineer. @@ -1805,11 +2004,6 @@ Il s'agit de votre propre lien unique ! Créé à : %@ copied message info - - Created on %@ - Créé le %@ - No comment provided by engineer. - Creating archive link Création d'un lien d'archive @@ -1825,6 +2019,10 @@ Il s'agit de votre propre lien unique ! Code d'accès actuel No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Phrase secrète actuelle… @@ -1845,6 +2043,11 @@ Il s'agit de votre propre lien unique ! Délai personnalisé No comment provided by engineer. + + Customizable message shape. + Forme des messages personnalisable. + No comment provided by engineer. + Customize theme Personnaliser le thème @@ -1976,7 +2179,8 @@ Il s'agit de votre propre lien unique ! Delete Supprimer - chat item action + alert action + chat item action swipe action @@ -2014,14 +2218,8 @@ Il s'agit de votre propre lien unique ! Supprimer et en informer le contact No comment provided by engineer. - - Delete archive - Supprimer l'archive - No comment provided by engineer. - - - Delete chat archive? - Supprimer l'archive du chat ? + + Delete chat No comment provided by engineer. @@ -2034,6 +2232,10 @@ Il s'agit de votre propre lien unique ! Supprimer le profil du chat ? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Supprimer la connexion @@ -2046,6 +2248,7 @@ Il s'agit de votre propre lien unique ! Delete contact? + Supprimer le contact ? No comment provided by engineer. @@ -2138,6 +2341,11 @@ Il s'agit de votre propre lien unique ! Supprimer l'ancienne base de données ? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Supprimer ou modérer jusqu'à 200 messages. + No comment provided by engineer. + Delete pending connection? Supprimer la connexion en attente ? @@ -2155,6 +2363,7 @@ Il s'agit de votre propre lien unique ! Delete up to 20 messages at once. + Supprimez jusqu'à 20 messages à la fois. No comment provided by engineer. @@ -2164,11 +2373,12 @@ Il s'agit de votre propre lien unique ! Delete without notification + Supprimer sans notification No comment provided by engineer. Deleted - Supprimé + Supprimées No comment provided by engineer. @@ -2186,6 +2396,10 @@ Il s'agit de votre propre lien unique ! Erreurs de suppression No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Distribution @@ -2253,6 +2467,7 @@ Il s'agit de votre propre lien unique ! Developer options + Options pour les développeurs No comment provided by engineer. @@ -2285,8 +2500,12 @@ Il s'agit de votre propre lien unique ! Messages directs chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Les messages directs entre membres sont interdits dans ce groupe. No comment provided by engineer. @@ -2325,8 +2544,8 @@ Il s'agit de votre propre lien unique ! Les messages éphémères sont interdits dans cette discussion. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Les messages éphémères sont interdits dans ce groupe. No comment provided by engineer. @@ -2385,6 +2604,11 @@ Il s'agit de votre propre lien unique ! Ne pas envoyer d'historique aux nouveaux membres. No comment provided by engineer. + + Do not use credentials with proxy. + Ne pas utiliser d'identifiants avec le proxy. + No comment provided by engineer. + Don't create address Ne pas créer d'adresse @@ -2408,7 +2632,8 @@ Il s'agit de votre propre lien unique ! Download Télécharger - chat item action + alert button + chat item action Download errors @@ -2425,6 +2650,11 @@ Il s'agit de votre propre lien unique ! Télécharger le fichier server test step + + Download files + Télécharger les fichiers + alert action + Downloaded Téléchargé @@ -2455,6 +2685,10 @@ Il s'agit de votre propre lien unique ! Durée No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Modifier @@ -2475,6 +2709,10 @@ Il s'agit de votre propre lien unique ! Activer (conserver les remplacements) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Activer SimpleX Lock @@ -2680,26 +2918,34 @@ Il s'agit de votre propre lien unique ! Erreur lors de l'annulation du changement d'adresse No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request Erreur de validation de la demande de contact No comment provided by engineer. - - Error accessing database file - Erreur d'accès au fichier de la base de données - No comment provided by engineer. - Error adding member(s) Erreur lors de l'ajout de membre·s No comment provided by engineer. + + Error adding server + alert title + Error changing address Erreur de changement d'adresse No comment provided by engineer. + + Error changing connection profile + Erreur lors du changement de profil de connexion + No comment provided by engineer. + Error changing role Erreur lors du changement de rôle @@ -2710,6 +2956,11 @@ Il s'agit de votre propre lien unique ! Erreur de changement de paramètre No comment provided by engineer. + + Error changing to incognito! + Erreur lors du passage en mode incognito ! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Erreur de connexion au serveur de redirection %@. Veuillez réessayer plus tard. @@ -2825,9 +3076,13 @@ Il s'agit de votre propre lien unique ! Erreur lors de la liaison avec le groupe No comment provided by engineer. - - Error loading %@ servers - Erreur lors du chargement des serveurs %@ + + Error loading servers + alert title + + + Error migrating settings + Erreur lors de la migration des paramètres No comment provided by engineer. @@ -2838,7 +3093,7 @@ Il s'agit de votre propre lien unique ! Error receiving file Erreur lors de la réception du fichier - No comment provided by engineer. + alert title Error reconnecting server @@ -2860,11 +3115,6 @@ Il s'agit de votre propre lien unique ! Erreur de réinitialisation des statistiques No comment provided by engineer. - - Error saving %@ servers - Erreur lors de la sauvegarde des serveurs %@ - No comment provided by engineer. - Error saving ICE servers Erreur lors de la sauvegarde des serveurs ICE @@ -2885,6 +3135,10 @@ Il s'agit de votre propre lien unique ! Erreur lors de l'enregistrement de la phrase de passe dans la keychain No comment provided by engineer. + + Error saving servers + alert title + Error saving settings Erreur lors de l'enregistrement des paramètres @@ -2930,10 +3184,15 @@ Il s'agit de votre propre lien unique ! Erreur lors de l'arrêt du chat No comment provided by engineer. + + Error switching profile + Erreur lors du changement de profil + No comment provided by engineer. + Error switching profile! Erreur lors du changement de profil ! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2950,6 +3209,10 @@ Il s'agit de votre propre lien unique ! Erreur lors de la mise à jour du message No comment provided by engineer. + + Error updating server + alert title + Error updating settings Erreur lors de la mise à jour des paramètres @@ -2978,8 +3241,7 @@ Il s'agit de votre propre lien unique ! Error: %@ Erreur : %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2996,6 +3258,10 @@ Il s'agit de votre propre lien unique ! Erreurs No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. Même s'il est désactivé dans la conversation. @@ -3066,6 +3332,13 @@ Il s'agit de votre propre lien unique ! Erreur de fichier No comment provided by engineer. + + File errors: +%@ + Erreurs de fichier : +%@ + alert message + File not found - most likely file was deleted or cancelled. Fichier introuvable - le fichier a probablement été supprimé ou annulé. @@ -3121,8 +3394,8 @@ Il s'agit de votre propre lien unique ! Fichiers et médias chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Les fichiers et les médias sont interdits dans ce groupe. No comment provided by engineer. @@ -3191,21 +3464,57 @@ Il s'agit de votre propre lien unique ! Correction non prise en charge par un membre du groupe No comment provided by engineer. + + For chat profile %@: + servers error + For console Pour la console No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward Transférer chat item action + + Forward %d message(s)? + Transférer %d message(s) ? + alert title + Forward and save messages Transférer et sauvegarder des messages No comment provided by engineer. + + Forward messages + Transférer les messages + alert action + + + Forward messages without files? + Transférer les messages sans les fichiers ? + alert message + + + Forward up to 20 messages at once. + Transférez jusqu'à 20 messages à la fois. + No comment provided by engineer. + Forwarded Transféré @@ -3216,6 +3525,11 @@ Il s'agit de votre propre lien unique ! Transféré depuis No comment provided by engineer. + + Forwarding %lld messages + Transfert des %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. Le serveur de redirection %@ n'a pas réussi à se connecter au serveur de destination %@. Veuillez réessayer plus tard. @@ -3265,11 +3579,6 @@ Erreur : %2$@ Nom complet (optionnel) No comment provided by engineer. - - Full name: - Nom complet : - No comment provided by engineer. - Fully decentralized – visible only to members. Entièrement décentralisé – visible que par ses membres. @@ -3355,41 +3664,6 @@ Erreur : %2$@ Liens de groupe No comment provided by engineer. - - 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. (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 SimpleX links. - Les membres du groupe peuvent envoyer des liens SimpleX. - No comment provided by engineer. - - - Group members can send direct messages. - Les membres du groupe peuvent envoyer des messages directs. - No comment provided by engineer. - - - Group members can send disappearing messages. - Les membres du groupes peuvent envoyer des messages éphémères. - No comment provided by engineer. - - - Group members can send files and media. - Les membres du groupe peuvent envoyer des fichiers et des médias. - No comment provided by engineer. - - - Group members can send voice messages. - Les membres du groupe peuvent envoyer des messages vocaux. - No comment provided by engineer. - Group message: Message du groupe : @@ -3485,9 +3759,12 @@ Erreur : %2$@ Comment SimpleX fonctionne No comment provided by engineer. - - How it works - Comment ça fonctionne + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3515,6 +3792,11 @@ Erreur : %2$@ Serveurs ICE (un par ligne) No comment provided by engineer. + + IP address + Adresse IP + 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. @@ -3555,8 +3837,8 @@ Erreur : %2$@ Immédiatement No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Protégé du spam et des abus No comment provided by engineer. @@ -3590,6 +3872,13 @@ Erreur : %2$@ Importation de l'archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Amélioration de la distribution, réduction de l'utilisation du trafic. +D'autres améliorations sont à venir ! + No comment provided by engineer. + Improved message delivery Amélioration de la transmission des messages @@ -3690,6 +3979,11 @@ Erreur : %2$@ Installer [SimpleX Chat pour terminal](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Instantané + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3697,11 +3991,6 @@ Erreur : %2$@ No comment provided by engineer. - - Instantly - Instantané - No comment provided by engineer. - Interface Interface @@ -3750,7 +4039,7 @@ Erreur : %2$@ Invalid server address! Adresse de serveur invalide ! - No comment provided by engineer. + alert title Invalid status @@ -3772,6 +4061,10 @@ Erreur : %2$@ Inviter des membres No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Inviter au groupe @@ -3787,8 +4080,8 @@ Erreur : %2$@ La suppression irréversible de message est interdite dans ce chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. La suppression irréversible de messages est interdite dans ce groupe. No comment provided by engineer. @@ -3815,6 +4108,7 @@ Erreur : %2$@ It protects your IP address and connections. + Il protège votre adresse IP et vos connexions. No comment provided by engineer. @@ -3877,10 +4171,11 @@ Voici votre lien pour le groupe %@ ! Keep Conserver - No comment provided by engineer. + alert action Keep conversation + Garder la conversation No comment provided by engineer. @@ -3891,7 +4186,7 @@ Voici votre lien pour le groupe %@ ! Keep unused invitation? Conserver l'invitation inutilisée ? - No comment provided by engineer. + alert title Keep your connections @@ -3928,6 +4223,14 @@ Voici votre lien pour le groupe %@ ! Quitter swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Quitter le groupe @@ -3978,11 +4281,6 @@ Voici votre lien pour le groupe %@ ! Messages dynamiques No comment provided by engineer. - - Local - Local - No comment provided by engineer. - Local name Nom local @@ -4003,11 +4301,6 @@ Voici votre lien pour le groupe %@ ! Mode de verrouillage No comment provided by engineer. - - Make a private connection - Établir une connexion privée - No comment provided by engineer. - Make one message disappear Rendre un message éphémère @@ -4018,21 +4311,11 @@ Voici votre lien pour le groupe %@ ! Rendre un profil privé ! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Assurez-vous que les adresses des serveurs %@ sont au bon format et ne sont pas dupliquées, un par ligne (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Assurez-vous que les adresses des serveurs WebRTC ICE sont au bon format et ne sont pas dupliquées, un par ligne. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Beaucoup se demandent : *si SimpleX n'a pas d'identifiant d'utilisateur, comment peut-il délivrer des messages ?* - No comment provided by engineer. - Mark deleted for everyone Marquer comme supprimé pour tout le monde @@ -4060,6 +4343,7 @@ Voici votre lien pour le groupe %@ ! Media & file servers + Serveurs de fichiers et de médias No comment provided by engineer. @@ -4077,6 +4361,10 @@ Voici votre lien pour le groupe %@ ! Membre inactif item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Le rôle du membre sera changé pour "%@". Tous les membres du groupe en seront informés. @@ -4087,11 +4375,50 @@ Voici votre lien pour le groupe %@ ! Le rôle du membre sera changé pour "%@". Ce membre recevra une nouvelle invitation. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Ce membre sera retiré du groupe - impossible de revenir en arrière ! No comment provided by engineer. + + Members can add message reactions. + Les membres du groupe peuvent ajouter des réactions aux messages. + No comment provided by engineer. + + + 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. + + + Members can send SimpleX links. + Les membres du groupe peuvent envoyer des liens SimpleX. + No comment provided by engineer. + + + Members can send direct messages. + Les membres du groupe peuvent envoyer des messages directs. + No comment provided by engineer. + + + Members can send disappearing messages. + Les membres du groupes peuvent envoyer des messages éphémères. + No comment provided by engineer. + + + Members can send files and media. + Les membres du groupe peuvent envoyer des fichiers et des médias. + No comment provided by engineer. + + + Members can send voice messages. + Les membres du groupe peuvent envoyer des messages vocaux. + No comment provided by engineer. + Menus Menus @@ -4142,8 +4469,8 @@ Voici votre lien pour le groupe %@ ! Les réactions aux messages sont interdites dans ce chat. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Les réactions aux messages sont interdites dans ce groupe. No comment provided by engineer. @@ -4154,6 +4481,12 @@ Voici votre lien pour le groupe %@ ! Message servers + Serveurs de messages + No comment provided by engineer. + + + Message shape + Forme du message No comment provided by engineer. @@ -4206,6 +4539,11 @@ Voici votre lien pour le groupe %@ ! Messages envoyés No comment provided by engineer. + + Messages were deleted after you selected them. + Les messages ont été supprimés après avoir été sélectionnés. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Les messages, fichiers et appels sont protégés par un chiffrement **de bout en bout** avec une confidentialité persistante, une répudiation et une récupération en cas d'effraction. @@ -4271,9 +4609,9 @@ Voici votre lien pour le groupe %@ ! La migration est terminée No comment provided by engineer. - - Migrations: %@ - Migrations : %@ + + Migrations: + Migrations : No comment provided by engineer. @@ -4301,6 +4639,10 @@ Voici votre lien pour le groupe %@ ! Connexion réseau plus fiable. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Connexion probablement supprimée. @@ -4336,6 +4678,10 @@ Voici votre lien pour le groupe %@ ! Connexion au réseau No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Problèmes de réseau - le message a expiré après plusieurs tentatives d'envoi. @@ -4346,6 +4692,10 @@ Voici votre lien pour le groupe %@ ! Gestion du réseau No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Paramètres réseau @@ -4361,6 +4711,16 @@ Voici votre lien pour le groupe %@ ! Nouveau code d'accès No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + De nouveaux identifiants SOCKS seront utilisés chaque fois que vous démarrerez l'application. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + De nouveaux identifiants SOCKS seront utilisées pour chaque serveur. + No comment provided by engineer. + New chat Nouveau chat @@ -4368,6 +4728,7 @@ Voici votre lien pour le groupe %@ ! New chat experience 🎉 + Nouvelle expérience de discussion 🎉 No comment provided by engineer. @@ -4380,11 +4741,6 @@ Voici votre lien pour le groupe %@ ! Nouveau contact : notification - - New database archive - Nouvelle archive de base de données - No comment provided by engineer. - New desktop app! Nouvelle application de bureau ! @@ -4395,6 +4751,10 @@ Voici votre lien pour le groupe %@ ! Nouveau nom d'affichage No comment provided by engineer. + + New events + notification + New in %@ Nouveautés de la %@ @@ -4402,6 +4762,7 @@ Voici votre lien pour le groupe %@ ! New media options + Nouvelles options de médias No comment provided by engineer. @@ -4419,6 +4780,10 @@ Voici votre lien pour le groupe %@ ! Nouvelle phrase secrète… No comment provided by engineer. + + New server + No comment provided by engineer. + No Non @@ -4474,21 +4839,65 @@ Voici votre lien pour le groupe %@ ! Pas d'info, essayez de recharger No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection Pas de connexion au réseau No comment provided by engineer. + + No permission to record speech + Enregistrement des conversations non autorisé + No comment provided by engineer. + + + No permission to record video + Enregistrement de la vidéo non autorisé + No comment provided by engineer. + No permission to record voice message Pas l'autorisation d'enregistrer un message vocal No comment provided by engineer. + + No push server + No push server + No comment provided by engineer. + No received or sent files Aucun fichier reçu ou envoyé No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Aucun identifiant d'utilisateur. + No comment provided by engineer. + Not compatible! Non compatible ! @@ -4499,6 +4908,11 @@ Voici votre lien pour le groupe %@ ! Aucune sélection No comment provided by engineer. + + Nothing to forward! + Rien à transférer ! + alert title + Notifications Notifications @@ -4509,6 +4923,10 @@ Voici votre lien pour le groupe %@ ! Les notifications sont désactivées ! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4531,18 +4949,13 @@ Voici votre lien pour le groupe %@ ! Ok Ok - No comment provided by engineer. + alert button Old database Ancienne base de données No comment provided by engineer. - - Old database archive - Archives de l'ancienne base de données - No comment provided by engineer. - One-time invitation link Lien d'invitation unique @@ -4567,13 +4980,18 @@ Nécessite l'activation d'un VPN. Les hôtes .onion ne seront pas utilisés. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Seuls les appareils clients stockent les profils des utilisateurs, les contacts, les groupes et les messages envoyés avec un **chiffrement de bout en bout à deux couches**. No comment provided by engineer. Only delete conversation + Ne supprimer que la conversation No comment provided by engineer. @@ -4651,6 +5069,10 @@ Nécessite l'activation d'un VPN. Ouvrir les Paramètres No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Ouvrir le chat @@ -4661,6 +5083,10 @@ Nécessite l'activation d'un VPN. Ouvrir la console du chat authentication reason + + Open conditions + No comment provided by engineer. + Open group Ouvrir le groupe @@ -4671,26 +5097,23 @@ Nécessite l'activation d'un VPN. Ouvrir le transfert vers un autre appareil authentication reason - - Open server settings - Ouvrir les paramètres du serveur - No comment provided by engineer. - - - Open user profiles - Ouvrir les profils d'utilisateurs - authentication reason - - - 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 app… Ouverture de l'app… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link Ou coller le lien de l'archive @@ -4708,7 +5131,11 @@ Nécessite l'activation d'un VPN. Or show this code - Ou présenter ce code + Ou montrez ce code + No comment provided by engineer. + + + Or to share privately No comment provided by engineer. @@ -4716,10 +5143,12 @@ Nécessite l'activation d'un VPN. Autres No comment provided by engineer. - - Other %@ servers - Autres serveurs %@ - No comment provided by engineer. + + Other file errors: +%@ + Autres erreurs de fichiers : +%@ + alert message PING count @@ -4756,6 +5185,11 @@ Nécessite l'activation d'un VPN. Code d'accès défini ! No comment provided by engineer. + + Password + Mot de passe + No comment provided by engineer. + Password to show Mot de passe à entrer @@ -4791,13 +5225,8 @@ Nécessite l'activation d'un VPN. En attente No comment provided by engineer. - - People can connect to you only via the links you share. - On ne peut se connecter à vous qu’avec les liens que vous partagez. - No comment provided by engineer. - - - Periodically + + Periodic Périodique No comment provided by engineer. @@ -4813,10 +5242,12 @@ Nécessite l'activation d'un VPN. Play from the chat list. + Aperçu depuis la liste de conversation. No comment provided by engineer. Please ask your contact to enable calls. + Veuillez demander à votre contact d'autoriser les appels. No comment provided by engineer. @@ -4903,6 +5334,11 @@ Erreur : %@ Interface en polonais No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Il est possible que l'empreinte du certificat dans l'adresse du serveur soit incorrecte @@ -4913,16 +5349,15 @@ Erreur : %@ Conserver le brouillon du dernier message, avec les pièces jointes. No comment provided by engineer. - - Preset server - Serveur prédéfini - No comment provided by engineer. - Preset server address Adresse du serveur prédéfinie No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview Aperçu @@ -4938,6 +5373,10 @@ Erreur : %@ Vie privée et sécurité No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined La vie privée redéfinie @@ -4988,16 +5427,6 @@ Erreur : %@ Images de profil No comment provided by engineer. - - Profile name - Nom du profil - No comment provided by engineer. - - - Profile name: - Nom du profil : - No comment provided by engineer. - Profile password Mot de passe de profil @@ -5011,7 +5440,7 @@ Erreur : %@ Profile update will be sent to your contacts. La mise à jour du profil sera envoyée à vos contacts. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5100,6 +5529,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Serveurs routés via des proxy No comment provided by engineer. + + Proxy requires password + Le proxy est protégé par un mot de passe + No comment provided by engineer. + Push notifications Notifications push @@ -5122,6 +5556,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Reachable chat toolbar + Barre d'outils accessible No comment provided by engineer. @@ -5139,26 +5574,21 @@ Activez-le dans les paramètres *Réseau et serveurs*. En savoir plus 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Plus d'informations sur notre GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Pour en savoir plus, consultez notre [dépôt GitHub](https://github.com/simplex-chat/simplex-chat#readme). @@ -5320,6 +5750,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Supprimer No comment provided by engineer. + + Remove archive? + Supprimer l'archive ? + No comment provided by engineer. + Remove image Enlever l'image @@ -5397,6 +5832,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Reset all hints + Rétablir tous les conseils No comment provided by engineer. @@ -5469,6 +5905,14 @@ Activez-le dans les paramètres *Réseau et serveurs*. Révéler chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke Révoquer @@ -5499,6 +5943,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Serveur SMP No comment provided by engineer. + + SOCKS proxy + proxy SOCKS + No comment provided by engineer. + Safely receive files Réception de fichiers en toute sécurité @@ -5512,17 +5961,18 @@ Activez-le dans les paramètres *Réseau et serveurs*. Save Enregistrer - chat item action + alert button + chat item action Save (and notify contacts) Enregistrer (et en informer les contacts) - No comment provided by engineer. + alert button Save and notify contact Enregistrer et en informer le contact - No comment provided by engineer. + alert button Save and notify group members @@ -5531,6 +5981,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Save and reconnect + Sauvegarder et se reconnecter No comment provided by engineer. @@ -5538,16 +5989,6 @@ Activez-le dans les paramètres *Réseau et serveurs*. Enregistrer et mettre à jour le profil du groupe No comment provided by engineer. - - Save archive - Enregistrer l'archive - No comment provided by engineer. - - - Save auto-accept settings - Enregistrer les paramètres de validation automatique - No comment provided by engineer. - Save group profile Enregistrer le profil du groupe @@ -5566,7 +6007,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Save preferences? Enregistrer les préférences ? - No comment provided by engineer. + alert title Save profile password @@ -5581,18 +6022,18 @@ Activez-le dans les paramètres *Réseau et serveurs*. Save servers? Enregistrer les serveurs ? - No comment provided by engineer. - - - Save settings? - Enregistrer les paramètres ? - No comment provided by engineer. + alert title Save welcome message? Enregistrer le message d'accueil ? No comment provided by engineer. + + Save your profile? + Sauvegarder votre profil ? + alert title + Saved Enregistré @@ -5613,6 +6054,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Message enregistré message info title + + Saving %lld messages + Sauvegarde de %lld messages + No comment provided by engineer. + Scale Échelle @@ -5620,7 +6066,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Scan / Paste link - Scanner / Coller le lien + Scanner / Coller un lien No comment provided by engineer. @@ -5675,7 +6121,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Secured - Sécurisé + Sécurisées No comment provided by engineer. @@ -5693,6 +6139,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Choisir chat item action + + Select chat profile + Sélectionner un profil de discussion + No comment provided by engineer. + Selected %lld %lld sélectionné(s) @@ -5755,7 +6206,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Send link previews - Envoi d'aperçus de liens + Aperçu des liens No comment provided by engineer. @@ -5765,6 +6216,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Send message to enable calls. + Envoyer un message pour activer les appels. No comment provided by engineer. @@ -5782,11 +6234,6 @@ Activez-le dans les paramètres *Réseau et serveurs*. Envoi de notifications No comment provided by engineer. - - Send notifications: - Envoi de notifications : - No comment provided by engineer. - Send questions and ideas Envoyez vos questions et idées @@ -5810,7 +6257,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Sender cancelled file transfer. L'expéditeur a annulé le transfert de fichiers. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5907,6 +6354,15 @@ Activez-le dans les paramètres *Réseau et serveurs*. Envoyé via le proxy No comment provided by engineer. + + Server + Serveur + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address Adresse du serveur @@ -5922,6 +6378,18 @@ Activez-le dans les paramètres *Réseau et serveurs*. L'adresse du serveur est incompatible avec les paramètres réseau : %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Le serveur requiert une autorisation pour créer des files d'attente, vérifiez le mot de passe @@ -5929,7 +6397,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Server requires authorization to upload, check password - Le serveur requiert une autorisation pour uploader, vérifiez le mot de passe + Le serveur requiert une autorisation pour téléverser, vérifiez le mot de passe server test error @@ -6027,6 +6495,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Paramètres No comment provided by engineer. + + Settings were changed. + Les paramètres ont été modifiés. + alert message + Shape profile images Images de profil modelable @@ -6035,25 +6508,39 @@ Activez-le dans les paramètres *Réseau et serveurs*. Share Partager - chat item action + alert action + chat item action Share 1-time link Partager un lien unique No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Partager l'adresse No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Partager l'adresse avec vos contacts ? - No comment provided by engineer. + alert title Share from other apps. + Partager depuis d'autres applications. No comment provided by engineer. @@ -6061,9 +6548,14 @@ Activez-le dans les paramètres *Réseau et serveurs*. Partager le lien No comment provided by engineer. + + Share profile + Partager le profil + No comment provided by engineer. + Share this 1-time invite link - Partager ce lien d'invitation unique + Partagez ce lien d'invitation unique No comment provided by engineer. @@ -6093,7 +6585,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Show last messages - Voir les derniers messages + Aperçu des derniers messages No comment provided by engineer. @@ -6108,7 +6600,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Show preview - Afficher l'aperçu + Aperçu affiché No comment provided by engineer. @@ -6131,6 +6623,10 @@ Activez-le dans les paramètres *Réseau et serveurs*. Adresse SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. La sécurité de SimpleX Chat a été auditée par Trail of Bits. @@ -6161,6 +6657,14 @@ Activez-le dans les paramètres *Réseau et serveurs*. Adresse SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address Adresse de contact SimpleX @@ -6181,8 +6685,8 @@ Activez-le dans les paramètres *Réseau et serveurs*. Liens SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. Les liens SimpleX sont interdits dans ce groupe. No comment provided by engineer. @@ -6196,6 +6700,11 @@ Activez-le dans les paramètres *Réseau et serveurs*. Invitation unique SimpleX simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Protocoles SimpleX audité par Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Mode incognito simplifié @@ -6226,8 +6735,14 @@ Activez-le dans les paramètres *Réseau et serveurs*. Léger blur media + + Some app settings were not migrated. + Certains paramètres de l'application n'ont pas été migrés. + No comment provided by engineer. + Some file(s) were not exported: + Certains fichiers n'ont pas été exportés : No comment provided by engineer. @@ -6237,8 +6752,14 @@ Activez-le dans les paramètres *Réseau et serveurs*. Some non-fatal errors occurred during import: + L'importation a entraîné des erreurs non fatales : No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Quelqu'un @@ -6289,11 +6810,6 @@ Activez-le dans les paramètres *Réseau et serveurs*. Arrêter le chat No comment provided by engineer. - - Stop chat to enable database actions - Arrêter le chat pour permettre des actions sur la base de données - 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. Arrêtez le chat pour exporter, importer ou supprimer la base de données du chat. Vous ne pourrez pas recevoir et envoyer de messages pendant que le chat est arrêté. @@ -6322,12 +6838,12 @@ Activez-le dans les paramètres *Réseau et serveurs*. Stop sharing Cesser le partage - No comment provided by engineer. + alert action Stop sharing address? Cesser le partage d'adresse ? - No comment provided by engineer. + alert title Stopping chat @@ -6346,7 +6862,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Subscribed - Inscrit + Inscriptions No comment provided by engineer. @@ -6364,6 +6880,16 @@ Activez-le dans les paramètres *Réseau et serveurs*. Supporter SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Passer de l'audio à la vidéo pendant l'appel. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Changer de profil de chat pour les invitations à usage unique. + No comment provided by engineer. + System Système @@ -6376,6 +6902,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. TCP connection + Connexion TCP No comment provided by engineer. @@ -6398,11 +6925,20 @@ Activez-le dans les paramètres *Réseau et serveurs*. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Queue + No comment provided by engineer. + Take picture Prendre une photo No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Appuyez sur le bouton @@ -6461,7 +6997,7 @@ Activez-le dans les paramètres *Réseau et serveurs*. Tests failed! Échec des tests ! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6478,11 +7014,6 @@ Activez-le dans les paramètres *Réseau et serveurs*. Merci aux utilisateurs - contribuez via Weblate ! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - La 1ère plateforme sans aucun identifiant d'utilisateur – privée par design. - No comment provided by engineer. - 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. @@ -6495,6 +7026,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. L'application peut vous avertir lorsque vous recevez des messages ou des demandes de contact - veuillez ouvrir les paramètres pour les activer. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). L'application demandera de confirmer les téléchargements à partir de serveurs de fichiers inconnus (sauf .onion). @@ -6510,6 +7045,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Le code scanné n'est pas un code QR de lien SimpleX. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! La connexion que vous avez acceptée sera annulée ! @@ -6530,6 +7069,11 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Le chiffrement fonctionne et le nouvel accord de chiffrement n'est pas nécessaire. Cela peut provoquer des erreurs de connexion ! No comment provided by engineer. + + The future of messaging + La nouvelle génération de messagerie privée + No comment provided by engineer. + The hash of the previous message is different. Le hash du message précédent est différent. @@ -6555,11 +7099,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Les messages seront marqués comme modérés pour tous les membres. No comment provided by engineer. - - The next generation of private messaging - La nouvelle génération de messagerie privée - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée. @@ -6570,6 +7109,18 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Le profil n'est partagé qu'avec vos contacts. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Le deuxième coche que nous avons manqué ! ✅ @@ -6585,16 +7136,29 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Les serveurs pour les nouvelles connexions de votre profil de chat actuel **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + 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. + + The uploaded database archive will be permanently removed from the servers. + L'archive de la base de données envoyée sera définitivement supprimée des serveurs. + No comment provided by engineer. + Themes Thèmes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Ces paramètres s'appliquent à votre profil actuel **%@**. @@ -6682,7 +7246,7 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. To connect, your contact can scan QR code or use the link in the app. - Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application. + Pour se connecter, votre contact peut scanner un code QR ou utiliser un lien dans l'app. No comment provided by engineer. @@ -6695,9 +7259,8 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise. Pour établir une nouvelle connexion 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. - Pour protéger votre vie privée, au lieu d’IDs utilisés par toutes les autres plateformes, SimpleX a des IDs pour les queues de messages, distinctes pour chacun de vos contacts. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6717,6 +7280,25 @@ You will be prompted to complete authentication before this feature is enabled.< Vous serez invité à confirmer l'authentification avant que cette fonction ne soit activée. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Pour protéger votre vie privée, au lieu d’IDs utilisés par toutes les autres plateformes, SimpleX a des IDs pour les queues de messages, distinctes pour chacun de vos contacts. + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Si vous souhaitez enregistrer une conversation, veuillez autoriser l'utilisation du microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Si vous souhaitez enregistrer une vidéo, veuillez autoriser l'utilisation de la caméra. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Pour enregistrer un message vocal, veuillez accorder la permission d'utiliser le microphone. @@ -6727,11 +7309,19 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Pour révéler votre profil caché, entrez le mot de passe dans le champ de recherche de la page **Vos profils de chat**. No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Pour prendre en charge les notifications push instantanées, la base de données du chat doit être migrée. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Pour vérifier le chiffrement de bout en bout avec votre contact, comparez (ou scannez) le code sur vos appareils. @@ -6739,6 +7329,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Toggle chat list: + Afficher la liste des conversations : No comment provided by engineer. @@ -6748,6 +7339,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Toolbar opacity + Opacité de la barre d'outils No comment provided by engineer. @@ -6820,6 +7412,10 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Débloquer ce membre ? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state État de la migration inattendu @@ -6868,7 +7464,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s Unknown servers! Serveurs inconnus ! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6934,6 +7530,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Update settings? + Mettre à jour les paramètres ? No comment provided by engineer. @@ -6958,7 +7555,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Upload file - Transférer le fichier + Téléverser le fichier server test step @@ -6976,11 +7573,20 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Envoi de l'archive No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts Utiliser les hôtes .onions No comment provided by engineer. + + Use SOCKS proxy + Utiliser un proxy SOCKS + No comment provided by engineer. + Use SimpleX Chat servers? Utiliser les serveurs SimpleX Chat ? @@ -6996,6 +7602,14 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Utiliser le profil actuel No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Utiliser pour les nouvelles connexions @@ -7036,6 +7650,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Utiliser ce serveur No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. Utiliser l'application pendant l'appel. @@ -7043,11 +7661,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Use the app with one hand. - No comment provided by engineer. - - - User profile - Profil d'utilisateur + Utiliser l'application d'une main. No comment provided by engineer. @@ -7055,6 +7669,11 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Sélection de l'utilisateur No comment provided by engineer. + + Username + Nom d'utilisateur + No comment provided by engineer. + Using SimpleX Chat servers. Vous utilisez les serveurs SimpleX. @@ -7112,7 +7731,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Video will be received when your contact completes uploading it. - La vidéo ne sera reçue que lorsque votre contact aura fini de la transférer. + La vidéo ne sera reçue que lorsque votre contact aura fini la mettre en ligne. No comment provided by engineer. @@ -7125,11 +7744,19 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Vidéos et fichiers jusqu'à 1Go No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Afficher le code de sécurité No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history Historique visible @@ -7145,8 +7772,8 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Les messages vocaux sont interdits dans ce chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Les messages vocaux sont interdits dans ce groupe. No comment provided by engineer. @@ -7240,9 +7867,8 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Lors des appels audio et vidéo. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Vous pouvez accepter ou refuser les demandes de contacts. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7288,7 +7914,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Sans Tor ni VPN, votre adresse IP sera visible par ces relais XFTP : %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7315,11 +7941,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Serveur XFTP No comment provided by engineer. - - You - Vous - No comment provided by engineer. - You **must not** use the same database on two devices. Vous **ne devez pas** utiliser la même base de données sur deux appareils. @@ -7345,6 +7966,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien Vous êtes déjà connecté·e à %@ via ce lien. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. Vous êtes déjà en train de vous connecter à %@. @@ -7404,6 +8029,15 @@ Répéter la demande d'adhésion ? You can change it in Appearance settings. + Vous pouvez choisir de le modifier dans les paramètres d'apparence. + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. No comment provided by engineer. @@ -7443,6 +8077,11 @@ Répéter la demande d'adhésion ? You can send messages to %@ from Archived contacts. + Vous pouvez envoyer des messages à %@ à partir des contacts archivés. + No comment provided by engineer. + + + You can set connection name, to remember who the link was shared with. No comment provided by engineer. @@ -7460,11 +8099,6 @@ Répéter la demande d'adhésion ? Vous pouvez partager cette adresse avec vos contacts pour leur permettre de se connecter avec **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Vous pouvez partager votre adresse sous la forme d'un lien ou d'un code QR - tout le monde peut l'utiliser pour vous contacter. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Vous pouvez lancer le chat via Paramètres / Base de données ou en redémarrant l'app @@ -7472,6 +8106,7 @@ Répéter la demande d'adhésion ? You can still view conversation with %@ in the list of chats. + Vous pouvez toujours voir la conversation avec %@ dans la liste des discussions. No comment provided by engineer. @@ -7487,23 +8122,23 @@ Répéter la demande d'adhésion ? 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. + alert message You can't send messages! Vous ne pouvez pas envoyer de messages ! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Vous contrôlez par quel·s serveur·s vous pouvez **transmettre** ainsi que par quel·s serveur·s vous pouvez **recevoir** les messages de vos contacts. - No comment provided by engineer. - You could not be verified; please try again. Vous n'avez pas pu être vérifié·e ; veuillez réessayer. No comment provided by engineer. + + You decide who can connect. + Vous choisissez qui peut se connecter. + No comment provided by engineer. + You have already requested connection via this address! Vous avez déjà demandé une connexion via cette adresse ! @@ -7538,10 +8173,12 @@ Répéter la demande de connexion ? You may migrate the exported database. + Vous pouvez migrer la base de données exportée. No comment provided by engineer. You may save the exported archive. + Vous pouvez enregistrer l'archive exportée. No comment provided by engineer. @@ -7551,6 +8188,7 @@ Répéter la demande de connexion ? You need to allow your contact to call to be able to call them. + Vous devez autoriser votre contact à appeler pour pouvoir l'appeler. No comment provided by engineer. @@ -7603,6 +8241,10 @@ Répéter la demande de connexion ? Vous continuerez à recevoir des appels et des notifications des profils mis en sourdine lorsqu'ils sont actifs. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Vous ne recevrez plus de messages de ce groupe. L'historique du chat sera conservé. @@ -7623,11 +8265,6 @@ Répéter la demande de connexion ? Vous utilisez un profil incognito pour ce groupe - pour éviter de partager votre profil principal ; inviter des contacts n'est pas possible No comment provided by engineer. - - Your %@ servers - Vos serveurs %@ - No comment provided by engineer. - Your ICE servers Vos serveurs ICE @@ -7643,11 +8280,6 @@ Répéter la demande de connexion ? Votre adresse SimpleX No comment provided by engineer. - - Your XFTP servers - Vos serveurs XFTP - No comment provided by engineer. - Your calls Vos appels @@ -7663,11 +8295,21 @@ Répéter la demande de connexion ? Votre base de données de chat n'est pas chiffrée - définisez une phrase secrète. No comment provided by engineer. + + Your chat preferences + Vos préférences de discussion + alert title + Your chat profiles Vos profils de chat No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Votre connexion a été déplacée vers %@ mais une erreur inattendue s'est produite lors de la redirection vers le profil. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Votre contact a envoyé un fichier plus grand que la taille maximale supportée actuellement(%@). @@ -7683,6 +8325,11 @@ Répéter la demande de connexion ? Vos contacts resteront connectés. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Vos informations d'identification peuvent être envoyées non chiffrées. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Votre base de données de chat actuelle va être SUPPRIMEE et REMPLACEE par celle importée. @@ -7713,13 +8360,16 @@ Répéter la demande de connexion ? Votre profil **%@** sera partagé. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. -Les serveurs SimpleX ne peuvent pas voir votre profil. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Votre profil a été modifié. Si vous l'enregistrez, le profil mis à jour sera envoyé à tous vos contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil. @@ -7730,16 +8380,15 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. Votre profil aléatoire No comment provided by engineer. - - Your server - Votre serveur - No comment provided by engineer. - Your server address Votre adresse de serveur No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings Vos paramètres @@ -7780,6 +8429,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. appel accepté call status + + accepted invitation + chat list item title + admin admin @@ -7862,6 +8515,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. call + appeler No comment provided by engineer. @@ -7967,7 +8621,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. connecting… connexion… - chat list item title + No comment provided by engineer. connection established @@ -8159,6 +8813,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. expiré No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded transféré @@ -8236,6 +8894,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. invite + inviter No comment provided by engineer. @@ -8295,6 +8954,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. message + message No comment provided by engineer. @@ -8329,6 +8989,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. mute + muet No comment provided by engineer. @@ -8453,6 +9114,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. vous a retiré rcv group event chat item + + requested to connect + chat list item title + saved enregistré @@ -8465,6 +9130,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil. search + rechercher No comment provided by engineer. @@ -8553,6 +9219,7 @@ dernier message reçu : %2$@ unmute + démuter No comment provided by engineer. @@ -8602,6 +9269,7 @@ dernier message reçu : %2$@ video + vidéo No comment provided by engineer. @@ -8775,6 +9443,33 @@ dernier message reçu : %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
@@ -8944,10 +9639,12 @@ dernier message reçu : %2$@ Sending a message takes longer than expected. + L'envoi d'un message prend plus de temps que prévu. No comment provided by engineer. Sending message… + Envoi du message… No comment provided by engineer. @@ -8957,6 +9654,7 @@ dernier message reçu : %2$@ Slow network? + Réseau lent ? No comment provided by engineer. @@ -8971,6 +9669,7 @@ dernier message reçu : %2$@ Wait + Attendez No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/fr.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - diff --git a/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff b/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff index 928a01dead..08f46bb056 100644 --- a/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff +++ b/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff @@ -217,23 +217,18 @@ Available in v5.1 ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **הוסיפו איש קשר חדש**: ליצירת קוד QR או קישור חד־פעמיים עבור איש הקשר שלכם. - No comment provided by engineer. - **Create link / QR code** for your contact to use. **צור קישור / קוד QR** לשימוש איש הקשר שלך. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **יותר פרטי**: בדוק הודעות חדשות כל 20 דקות. אסימון המכשיר משותף עם שרת SimpleX Chat, אך לא כמה אנשי קשר או הודעות יש לך. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **הכי פרטי**: אל תשתמש בשרת ההתראות של SimpleX Chat, בדוק הודעות מעת לעת ברקע (תלוי בתדירות השימוש באפליקציה). No comment provided by engineer. @@ -247,8 +242,8 @@ Available in v5.1 **שימו לב**: לא ניתן יהיה לשחזר או לשנות את הסיסמה אם תאבדו אותה. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **מומלץ**: אסימון מכשיר והתראות נשלחים לשרת ההתראות של SimpleX Chat, אך לא תוכן ההודעה, גודלה או ממי היא. No comment provided by engineer. @@ -1391,8 +1386,8 @@ Available in v5.1 הודעות ישירות chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. הודעות ישירות בין חברי קבוצה אסורות בקבוצה זו. No comment provided by engineer. @@ -1411,8 +1406,8 @@ Available in v5.1 הודעות נעלמות אסורות בצ׳אט זה. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. הודעות נעלמות אסורות בקבוצה זו. No comment provided by engineer. @@ -1956,18 +1951,18 @@ Available in v5.1 חברי הקבוצה יכולים למחוק באופן בלתי הפיך הודעות שנשלחו. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. חברי הקבוצה יכולים לשלוח הודעות ישירות. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. חברי הקבוצה יכולים לשלוח הודעות נעלמות. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. חברי הקבוצה יכולים לשלוח הודעות קוליות. No comment provided by engineer. @@ -2115,8 +2110,8 @@ Available in v5.1 מיד No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam חסין מפני ספאם ושימוש לרעה No comment provided by engineer. @@ -2257,8 +2252,8 @@ Available in v5.1 מחיקה בלתי הפיכה של הודעות אסורה בצ׳אט זה. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. מחיקה בלתי הפיכה של הודעות אסורה בקבוצה זו. No comment provided by engineer. @@ -2502,9 +2497,9 @@ Available in v5.1 ההעברה הושלמה No comment provided by engineer. - - Migrations: %@ - העברות: %@ + + Migrations: + העברות: No comment provided by engineer. @@ -2701,8 +2696,8 @@ Available in v5.1 לא ייעשה שימוש במארחי Onion. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2761,8 +2756,8 @@ Available in v5.1 Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2817,8 +2812,8 @@ Available in v5.1 Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -3521,8 +3516,8 @@ Available in v5.1 Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -3566,8 +3561,8 @@ It can happen because of some bug or when the connection is compromised.The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -3638,8 +3633,8 @@ It can happen because of some bug or when the connection is compromised.To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -3864,8 +3859,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -4005,10 +4000,6 @@ SimpleX Lock must be enabled. You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. @@ -4967,8 +4958,8 @@ SimpleX servers cannot see your profile. נמחק No comment provided by engineer. - - Files and media are prohibited in this group. + + Files and media are prohibited. קבצים ומדיה אסורים בקבוצה זו. No comment provided by engineer. @@ -5027,13 +5018,13 @@ SimpleX servers cannot see your profile. הזמן חברים No comment provided by engineer. - - Group members can add message reactions. + + Members can add message reactions. חברי הקבוצה יכולים להוסיף תגובות אמוג׳י להודעות. No comment provided by engineer. - - Group members can send files and media. + + Members can send files and media. חברי הקבוצה יכולים לשלוח קבצים ומדיה. No comment provided by engineer. @@ -5231,8 +5222,8 @@ SimpleX servers cannot see your profile. תגובות אמוג׳י להודעות אסורות בצ׳אט זה. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. תגובות אמוג׳י להודעות אסורות בקבוצה זו. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff index 50f5536e5e..2fd96e3492 100644 --- a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff +++ b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff @@ -181,23 +181,18 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **Dodajte novi kontakt**: da biste stvorili svoj jednokratni QR kôd ili vezu za svoj kontakt. - No comment provided by engineer. - **Create link / QR code** for your contact to use. **Stvorite vezu / QR kôd** za vaš kontakt. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Privatnije**: provjeravajte nove poruke svakih 20 minuta. Token uređaja dijeli se s SimpleX Chat poslužiteljem, ali ne i s brojem kontakata ili poruka koje imate. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Najprivatniji**: nemojte koristiti SimpleX Chat poslužitelj obavijesti, povremeno provjeravajte poruke u pozadini (ovisi o tome koliko često koristite aplikaciju). No comment provided by engineer. @@ -211,8 +206,8 @@ **Imajte na umu**: NEĆETE moći oporaviti ili promijeniti pristupni izraz ako ga izgubite. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Preporučeno**: token uređaja i obavijesti šalju se na poslužitelj obavijesti SimpleX Chata, ali ne i sadržaj poruke, veličinu ili od koga je. No comment provided by engineer. @@ -1039,8 +1034,8 @@ Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1055,8 +1050,8 @@ Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1419,16 +1414,16 @@ Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1519,8 +1514,8 @@ Image will be received when your contact is online, please wait or check later! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1616,8 +1611,8 @@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -1917,8 +1912,8 @@ We will be adding server redundancy to prevent lost messages. Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -1965,8 +1960,8 @@ We will be adding server redundancy to prevent lost messages. Open chat console authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -1997,8 +1992,8 @@ We will be adding server redundancy to prevent lost messages. Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -2577,8 +2572,8 @@ We will be adding server redundancy to prevent lost messages. Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -2609,8 +2604,8 @@ We will be adding server redundancy to prevent lost messages. The microphone does not work when the app is in the background. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -2673,8 +2668,8 @@ We will be adding server redundancy to prevent lost messages. To prevent the call interruption, enable Do Not Disturb mode. 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -2847,8 +2842,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -2959,10 +2954,6 @@ To connect, please ask your contact to create another connection link and check You can use markdown to format messages: No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff index dbe3c50ceb..231c33523d 100644 --- a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff +++ b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -59,7 +44,7 @@ #secret# - #titkos# + #titok# No comment provided by engineer. @@ -99,7 +84,7 @@ %1$@ at %2$@: - %1$@ ekkor: %2$@ + %1$@ ekkor: %2$@: copied message info, <sender> at <time> @@ -119,12 +104,22 @@ %@ is not verified - %@ nem ellenőrzött + %@ nem hitelesített No comment provided by engineer. %@ is verified - %@ ellenőrizve + %@ hitelesítve + No comment provided by engineer. + + + %@ server + %@ kiszolgáló + No comment provided by engineer. + + + %@ servers + %@ kiszolgáló No comment provided by engineer. @@ -137,6 +132,11 @@ %@ kapcsolódni szeretne! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ és további %lld tag @@ -157,11 +157,36 @@ %d nap time interval + + %d file(s) are still being downloaded. + %d fájl letöltése még folyamatban van. + forward confirmation reason + + + %d file(s) failed to download. + %d fájlt nem sikerült letölteni. + forward confirmation reason + + + %d file(s) were deleted. + %d fájl törölve lett. + forward confirmation reason + + + %d file(s) were not downloaded. + %d fájl nem lett letöltve. + forward confirmation reason + %d hours %d óra time interval + + %d messages not forwarded + %d üzenet nem lett továbbítva + alert title + %d min %d perc @@ -219,12 +244,12 @@ %lld messages blocked - %lld üzenet blokkolva + %lld üzenet letiltva No comment provided by engineer. %lld messages blocked by admin - %lld üzenet blokkolva az admin által + %lld üzenetet letiltott az adminisztrátor No comment provided by engineer. @@ -234,7 +259,7 @@ %lld messages moderated by %@ - %lld üzenet moderálva lett %@ által + %@ %lld üzenetet moderált No comment provided by engineer. @@ -244,7 +269,7 @@ %lld new interface languages - %lld új nyelvi csomag + %lld új kezelőfelületi nyelv No comment provided by engineer. @@ -322,54 +347,54 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. - **Ismerős hozzáadása**: új meghívó hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz. - No comment provided by engineer. - - - **Add new contact**: to create your one-time QR Code or link for your contact. - **Új ismerős hozzáadása**: egyszer használatos QR-kód vagy hivatkozás létrehozása az ismerőse számára. + + **Create 1-time link**: to create and share a new invitation link. + **Ismerős hozzáadása:** új meghívó-hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz. No comment provided by engineer. **Create group**: to create a new group. - **Csoport létrehozása**: új csoport létrehozásához. + **Csoport létrehozása:** új csoport létrehozásához. 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. - **Privátabb**: 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken megosztásra kerül a SimpleX Chat kiszolgálóval, de az nem, hogy hány ismerőse vagy üzenete van. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. + **Privátabb:** 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken megosztásra kerül a SimpleX Chat-kiszolgálóval, de az nem, hogy hány ismerőse vagy üzenete van. 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). - **Legprivátabb**: ne használja a SimpleX Chat értesítési kiszolgálót, rendszeresen ellenőrizze az üzeneteket a háttérben (attól függően, hogy milyen gyakran használja az alkalmazást). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. + **Legprivátabb:** ne használja a SimpleX Chat értesítési kiszolgálót, rendszeresen ellenőrizze az üzeneteket a háttérben (attól függően, hogy milyen gyakran használja az alkalmazást). No comment provided by engineer. **Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection. - **Megjegyzés**: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja az ismerőseitől érkező üzenetek visszafejtését. + **Megjegyzés:** ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja az ismerőseitől érkező üzenetek visszafejtését. No comment provided by engineer. **Please note**: you will NOT be able to recover or change passphrase if you lose it. - **Figyelem**: NEM tudja visszaállítani vagy megváltoztatni jelmondatát, ha elveszíti azt. + **Megjegyzés:** NEM tudja visszaállítani vagy megváltoztatni jelmondatát, ha elveszíti azt. 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. - **Javasolt**: az eszköztoken és az értesítések elküldésre kerülnek a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. + **Megjegyzés:** az eszköztoken és az értesítések elküldésre kerülnek a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik. + No comment provided by engineer. + + + **Scan / Paste link**: to connect via a link you received. + **Hivatkozás beolvasása / beillesztése**: egy kapott hivatkozáson keresztüli kapcsolódáshoz. No comment provided by engineer. **Warning**: Instant push notifications require passphrase saved in Keychain. - **Figyelmeztetés**: Az azonnali push-értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges. + **Figyelmeztetés:** Az azonnali push-értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges. No comment provided by engineer. **Warning**: the archive will be removed. - **Figyelem**: az archívum törlésre kerül. + **Figyelmeztetés:** az archívum eltávolításra kerül. No comment provided by engineer. @@ -414,8 +439,8 @@ - optionally notify deleted contacts. - profile names with spaces. - and more! - - opcionális értesítés a törölt kapcsolatokról. -- profilnevek szóközökkel. + - értesíti az ismerősöket a törlésről (nem kötelező) +- profil nevek szóközökkel - és még sok más! No comment provided by engineer. @@ -423,8 +448,8 @@ - voice messages up to 5 minutes. - custom time to disappear. - editing history. - - hangüzenetek legfeljebb 5 perces időtartamig. -- egyedi eltűnési időhatár megadása. + - 5 perc hosszúságú hangüzenetek. +- egyedi üzenet-eltűnési időkorlát. - előzmények szerkesztése. No comment provided by engineer. @@ -468,6 +493,16 @@ 1 hét time interval + + 1-time link + Egyszer használható meghívó-hivatkozás + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Az egyszer használható meghívó-hivatkozás csak *egyetlen ismerőssel használható* - személyesen vagy bármilyen üzenetküldőn keresztül megosztható. + No comment provided by engineer. + 5 minutes 5 perc @@ -492,7 +527,7 @@ <p>Hi!</p> <p><a href="%@">Connect to me via SimpleX Chat</a></p> <p>Üdvözlöm!</p> -<p><a href=„%@”>Csatlakozzon hozzám a SimpleX Chaten</a></p> +<p><a href="%@">Csatlakozzon hozzám a SimpleX Chaten keresztül</a></p> email text @@ -512,14 +547,14 @@ A separate TCP connection will be used **for each chat profile you have in the app**. - A rendszer külön TCP-kapcsolatot fog használni **az alkalmazásban található minden csevegési profilhoz**. + **Az összes csevegési profiljához az alkalmazásban** külön TCP-kapcsolat (és SOCKS-hitelesítőadat) lesz használva. No comment provided by engineer. 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. - A rendszer külön TCP-kapcsolatot fog használni **minden ismerőshöz és csoporttaghoz**. -**Figyelem**: sok kapcsolódás esetén, az akkumulátor- és adatforgalom fogyasztás jelentősen megnőhet, és egyes kapcsolatok meghiúsulhatnak. + **Az összes ismerőséhez és csoporttaghoz** külön TCP-kapcsolat (és SOCKS-hitelesítőadat) lesz használva. +**Megjegyzés:** ha sok kapcsolata van, az akkumulátor-használat és az adatforgalom jelentősen megnövekedhet, és néhány kapcsolódási kísérlet sikertelen lehet. No comment provided by engineer. @@ -537,19 +572,14 @@ Címváltoztatás megszakítása?? No comment provided by engineer. - - About SimpleX - A SimpleX-ről - No comment provided by engineer. - About SimpleX Chat - A SimpleX Chat-ről + SimpleX Chat névjegye No comment provided by engineer. - - About SimpleX address - A SimpleX címről + + About operators + Az üzemeltetőkről No comment provided by engineer. @@ -564,22 +594,32 @@ accept incoming call via notification swipe action + + Accept conditions + Feltételek elfogadása + No comment provided by engineer. + Accept connection request? - Kapcsolódási kérelem elfogadása? + Kapcsolatkérés elfogadása? No comment provided by engineer. Accept contact request from %@? - Elfogadja %@ kapcsolat kérését? + Elfogadja %@ kapcsolatkérését? notification body Accept incognito - Fogadás inkognítóban + Fogadás inkognitóban accept contact request via notification swipe action + + Accepted conditions + Elfogadott feltételek + No comment provided by engineer. + Acknowledged Nyugtázva @@ -600,14 +640,9 @@ Cím hozzáadása a profilhoz, hogy az ismerősei megoszthassák másokkal. A profilfrissítés elküldésre kerül az ismerősei számára. No comment provided by engineer. - - Add contact - Ismerős hozzáadása - No comment provided by engineer. - - - Add preset servers - Előre beállított kiszolgálók hozzáadása + + Add friends + Barátok hozzáadása No comment provided by engineer. @@ -625,6 +660,11 @@ Kiszolgáló hozzáadása QR-kód beolvasásával. No comment provided by engineer. + + Add team members + Csapattagok hozzáadása + No comment provided by engineer. + Add to another device Hozzáadás egy másik eszközhöz @@ -632,7 +672,22 @@ Add welcome message - Üdvözlő üzenet hozzáadása + Üdvözlőüzenet hozzáadása + No comment provided by engineer. + + + Add your team members to the conversations. + Adja hozzá csapattagjait a beszélgetésekhez. + No comment provided by engineer. + + + Added media & file servers + Hozzáadott média- és fájlkiszolgálók + No comment provided by engineer. + + + Added message servers + Hozzáadott üzenetkiszolgálók No comment provided by engineer. @@ -660,14 +715,24 @@ A cím módosítása megszakad. A régi fogadási cím kerül felhasználásra. No comment provided by engineer. + + Address or 1-time link? + Cím vagy egyszer használható meghívó-hivatkozás? + No comment provided by engineer. + + + Address settings + Címbeállítások + No comment provided by engineer. + Admins can block a member for all. - Az adminok egy tagot mindenki számára letilthatnak. + Az adminisztrátorok egy tagot a csoport összes tagja számára letilthatnak. No comment provided by engineer. Admins can create the links to join groups. - Az adminok hivatkozásokat hozhatnak létre a csoportokhoz való kapcsolódáshoz. + Az adminisztrátorok hivatkozásokat hozhatnak létre a csoportokhoz való kapcsolódáshoz. No comment provided by engineer. @@ -677,67 +742,72 @@ Advanced settings - Haladó beállítások + Speciális beállítások No comment provided by engineer. All app data is deleted. - Minden alkalmazásadat törölve. + Az összes alkalmazásadat törölve. No comment provided by engineer. All chats and messages will be deleted - this cannot be undone! - Minden csevegés és üzenet törlésre kerül - ez a művelet nem vonható vissza! + Az összes csevegés és üzenet törlésre kerül - ez a művelet nem vonható vissza! No comment provided by engineer. All data is erased when it is entered. - A jelkód megadása után minden adat törlésre kerül. + A jelkód megadása után az összes adat törlésre kerül. No comment provided by engineer. - - All data is private to your device. - Minden adat biztonságban van a készülékén. + + All data is kept private on your device. + Az összes adat biztonságban van az eszközén. No comment provided by engineer. All group members will remain connected. - Minden csoporttag kapcsolódva marad. + Az összes csoporttag kapcsolatban marad. + No comment provided by engineer. + + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Az összes üzenetet és fájlt **végpontok közötti titkosítással** küldi, a közvetlen üzenetekben pedig kvantumrezisztens biztonsággal. No comment provided by engineer. All messages will be deleted - this cannot be undone! - Minden üzenet törlésre kerül – ez a művelet nem vonható vissza! + Az összes üzenet törlésre kerül – ez a művelet nem vonható vissza! No comment provided by engineer. All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you. - Minden üzenet törlésre kerül - ez a művelet nem vonható vissza! Az üzenetek CSAK az ön számára törlődnek. + Az összes üzenet törlésre kerül - ez a művelet nem vonható vissza! Az üzenetek CSAK az Ön számára törlődnek. No comment provided by engineer. All new messages from %@ will be hidden! - Minden új üzenet elrejtésre kerül tőle: %@! + Az összes új üzenet elrejtésre kerül tőle: %@! No comment provided by engineer. All profiles - Minden profil - No comment provided by engineer. + Összes profil + profile dropdown All your contacts will remain connected. - Minden ismerős kapcsolódva marad. + Az összes ismerősével kapcsolatban marad. No comment provided by engineer. All your contacts will remain connected. Profile update will be sent to your contacts. - Ismerőseivel kapcsolatban marad. A profil változtatások frissítésre kerülnek az ismerősöknél. + Az ismerőseivel kapcsolatban marad. A profil-változtatások frissítésre kerülnek az ismerősöknél. No comment provided by engineer. All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays. - Minden ismerőse, a beszélgetései és a fájljai biztonságosan titkosításra kerülnek, melyek részletekben feltöltődnek a beállított XFTP átjátszókra. + Az összes ismerőse, -beszélgetése és -fájlja biztonságosan titkosításra kerülnek, melyek részletekben feltöltődnek a beállított XFTP-közvetítő-kiszolgálóra. No comment provided by engineer. @@ -747,7 +817,7 @@ Allow calls only if your contact allows them. - A hívások kezdeményezése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. + A hívások kezdeményezése csak abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. @@ -757,7 +827,7 @@ Allow disappearing messages only if your contact allows it to you. - Az eltűnő üzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi az ön számára. + Az eltűnő üzenetek küldése csak abban az esetben van engedélyezve, ha az ismerőse is engedélyezi az Ön számára. No comment provided by engineer. @@ -767,12 +837,12 @@ Allow irreversible message deletion only if your contact allows it to you. (24 hours) - Az üzenetek végleges törlése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. (24 óra) + Az üzenetek végleges törlése csak abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. (24 óra) No comment provided by engineer. Allow message reactions only if your contact allows them. - Az üzenetreakciók küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. + Az üzenetreakciók küldése csak abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. @@ -802,12 +872,12 @@ Allow to send SimpleX links. - A SimpleX hivatkozások küldése engedélyezve van. + A SimpleX-hivatkozások küldése engedélyezve van. No comment provided by engineer. Allow to send files and media. - Fájlok és médiatartalom küldésének engedélyezése. + Fájlok és médiatartalmak küldésének engedélyezése. No comment provided by engineer. @@ -817,7 +887,7 @@ Allow voice messages only if your contact allows them. - A hangüzenetek küldése kizárólag abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. + A hangüzenetek küldése csak abban az esetben van engedélyezve, ha az ismerőse is engedélyezi. No comment provided by engineer. @@ -872,7 +942,7 @@ Always use relay - Mindig használjon átjátszó kiszolgálót + Mindig használjon közvetítő-kiszolgálót No comment provided by engineer. @@ -885,6 +955,11 @@ Hívás fogadása No comment provided by engineer. + + Anybody can host servers. + Bárki üzemeltethet kiszolgálókat. + No comment provided by engineer. + App build: %@ Az alkalmazás build száma: %@ @@ -902,7 +977,7 @@ App icon - Alkalmazás ikon + Alkalmazásikon No comment provided by engineer. @@ -915,6 +990,11 @@ Az alkalmazás jelkód helyettesítésre kerül egy önmegsemmisítő jelkóddal. No comment provided by engineer. + + App session + Alkalmazás munkamenete + No comment provided by engineer. + App version Alkalmazás verzió @@ -947,7 +1027,7 @@ Archive contacts to chat later. - Ismerősök archiválása a későbbi csevegéshez. + Az ismerősök archiválása a későbbi csevegéshez. No comment provided by engineer. @@ -1012,7 +1092,7 @@ Auto-accept contact requests - Kapcsolódási kérelmek automatikus elfogadása + Kapcsolatkérések automatikus elfogadása No comment provided by engineer. @@ -1020,6 +1100,11 @@ Képek automatikus elfogadása No comment provided by engineer. + + Auto-accept settings + Beállítások automatikus elfogadása + alert title + Back Vissza @@ -1042,7 +1127,12 @@ Bad message hash - Téves üzenet hash + Hibás az üzenet hasító értéke + No comment provided by engineer. + + + Better calls + Továbbfejlesztett hívásélmény No comment provided by engineer. @@ -1050,6 +1140,11 @@ Javított csoportok No comment provided by engineer. + + Better message dates. + Továbbfejlesztett üzenetdátumok. + No comment provided by engineer. + Better messages Jobb üzenetek @@ -1060,6 +1155,21 @@ Jobb hálózatkezelés No comment provided by engineer. + + Better notifications + Továbbfejlesztett értesítések + No comment provided by engineer. + + + Better security ✅ + Továbbfejlesztett biztonság ✅ + No comment provided by engineer. + + + Better user experience + Továbbfejlesztett felhasználói élmény + No comment provided by engineer. + Black Fekete @@ -1067,37 +1177,37 @@ Block - Blokkolás + Letiltás No comment provided by engineer. Block for all - Letiltás mindenki számára + Letiltás az összes tag számára No comment provided by engineer. Block group members - Csoporttagok blokkolása + Csoporttagok letiltása No comment provided by engineer. Block member - Tag blokkolása + Tag letiltása No comment provided by engineer. Block member for all? - Mindenki számára letiltja ezt a tagot? + Az összes tag számára letiltja ezt a tagot? No comment provided by engineer. Block member? - Tag blokkolása? + Tag letiltása? No comment provided by engineer. Blocked by admin - Letiltva az admin által + Az adminisztrátor letiltotta No comment provided by engineer. @@ -1107,7 +1217,7 @@ Blur media - Média elhomályosítása + Médiatartalom elhomályosítása No comment provided by engineer. @@ -1140,9 +1250,19 @@ Bolgár, finn, thai és ukrán – köszönet a felhasználóknak és a [Weblate-nek](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Üzleti cím + No comment provided by engineer. + + + Business chats + Üzleti csevegések + 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). - Csevegési profil (alapértelmezett) vagy [kapcsolat alapján] (https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BÉTA). + A csevegési profillal (alapértelmezett), vagy a [kapcsolattal] (https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BÉTA). No comment provided by engineer. @@ -1177,12 +1297,12 @@ Can't invite contact! - Ismerősök meghívása le van tiltva! + Nem lehet meghívni az ismerőst! No comment provided by engineer. Can't invite contacts! - Ismerősök meghívása nem lehetséges! + Nem lehet meghívni az ismerősöket! No comment provided by engineer. @@ -1193,7 +1313,8 @@ Cancel Mégse - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1202,7 +1323,7 @@ Cannot access keychain to save database password - Nem lehet hozzáférni a kulcstartóhoz az adatbázis jelszavának mentéséhez + Nem lehet hozzáférni a kulcstartóhoz az adatbázisjelszó mentéséhez No comment provided by engineer. @@ -1213,7 +1334,7 @@ Cannot receive file Nem lehet fogadni a fájlt - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,9 +1351,14 @@ Változtatás No comment provided by engineer. + + Change chat profiles + Csevegési profilok megváltoztatása + authentication reason + Change database passphrase? - Adatbázis jelmondat megváltoztatása? + Adatbázis-jelmondat megváltoztatása? No comment provided by engineer. @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Csevegési archívum + + Chat + Csevegés + No comment provided by engineer. + + + Chat already exists + A csevegés már létezik + No comment provided by engineer. + + + Chat already exists! + A csevegés már létezik! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Csevegési beállítások No comment provided by engineer. + + Chat preferences were changed. + A csevegési beállítások megváltoztak. + alert message + + + Chat profile + Csevegési profil + No comment provided by engineer. + Chat theme Csevegés témája No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + A csevegés minden tag számára törlésre kerül - ezt a műveletet nem lehet visszavonni! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + A csevegés törlésre kerül az Ön számára - ezt a műveletet nem lehet visszavonni! + No comment provided by engineer. + Chats Csevegések No comment provided by engineer. + + Check messages every 20 min. + Üzenetek ellenőrzése 20 percenként. + No comment provided by engineer. + + + Check messages when allowed. + Üzenetek ellenőrzése, amikor engedélyezett. + No comment provided by engineer. + Check server address and try again. Kiszolgáló címének ellenőrzése és újrapróbálkozás. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1363,7 +1529,7 @@ Choose _Migrate from another device_ on the new device and scan QR code. - Válassza az _Átköltöztetés egy másik eszközről_ opciót az új eszközön és olvassa be a QR-kódot. + Válassza az _Átköltöztetés egy másik eszközről_ opciót az új eszközén és olvassa be a QR-kódot. No comment provided by engineer. @@ -1433,7 +1599,7 @@ Compare security codes with your contacts. - Biztonsági kódok összehasonlítása az ismerősökkel. + Biztonsági kódok összehasonlítása az ismerősökével. No comment provided by engineer. @@ -1441,14 +1607,54 @@ Elkészült No comment provided by engineer. - - Configure ICE servers - ICE kiszolgálók beállítása + + Conditions accepted on: %@. + Feltételek elfogadva ekkor: %@. No comment provided by engineer. - - Configured %@ servers - Beállított %@ kiszolgálók + + Conditions are accepted for the operator(s): **%@**. + A következő üzemeltető(k) számára elfogadott feltételek: **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + A feltételek már el lettek fogadva a következő üzemeltető(k) számára: **%@**. + No comment provided by engineer. + + + Conditions of use + Használati feltételek + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + A feltételek 30 nap elteltével lesznek elfogadva az engedélyezett üzemeltető számára. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + A feltételek el lesznek fogadva a következő üzemeltető(k) számára: **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + A feltételek el lesznek fogadva a következő üzemeltető(k) számára: **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + A feltételek ekkor lesznek elfogadva: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + A feltételek automatikusan elfogadásra kerülnek az engedélyezett üzemeltető számára: %@. + No comment provided by engineer. + + + Configure ICE servers + ICE-kiszolgálók beállítása No comment provided by engineer. @@ -1473,7 +1679,7 @@ Confirm files from unknown servers. - Ismeretlen kiszolgálókról származó fájlok jóváhagyása. + Ismeretlen kiszolgálókról származó fájlok megerősítése. No comment provided by engineer. @@ -1493,7 +1699,7 @@ Confirm that you remember database passphrase to migrate it. - Erősítse meg, hogy emlékszik az adatbázis jelmondatára az átköltöztetéshez. + Az átköltöztetéshez erősítse meg, hogy emlékszik az adatbázis jelmondatára. No comment provided by engineer. @@ -1518,7 +1724,7 @@ Connect to desktop - Kapcsolódás számítógéphez + Társítás számítógéppel No comment provided by engineer. @@ -1535,14 +1741,14 @@ Connect to yourself? This is your own SimpleX address! Kapcsolódás saját magához? -Ez az ön SimpleX címe! +Ez az Ön SimpleX-címe! No comment provided by engineer. Connect to yourself? This is your own one-time link! Kapcsolódás saját magához? -Ez az egyszer használatos hivatkozása! +Ez az Ön egyszer használható meghívó-hivatkozása! No comment provided by engineer. @@ -1557,22 +1763,22 @@ Ez az egyszer használatos hivatkozása! Connect via one-time link - Kapcsolódás egyszer használatos hivatkozáson keresztül + Kapcsolódás egyszer használható meghívó-hivatkozáson keresztül No comment provided by engineer. Connect with %@ - Kapcsolódás ezzel: %@ + Kapcsolódás a következővel: %@ No comment provided by engineer. Connected - Kapcsolódva + Kapcsolódott No comment provided by engineer. Connected desktop - Csatlakoztatott számítógép + Társított számítógép No comment provided by engineer. @@ -1597,7 +1803,7 @@ Ez az egyszer használatos hivatkozása! Connecting to server… (error: %@) - Kapcsolódás a kiszolgálóhoz... (hiba: %@) + Kapcsolódás a kiszolgálóhoz… (hiba: %@) No comment provided by engineer. @@ -1637,7 +1843,12 @@ Ez az egyszer használatos hivatkozása! Connection request sent! - Kapcsolódási kérés elküldve! + Kapcsolatkérés elküldve! + No comment provided by engineer. + + + Connection security + Kapcsolatbiztonság No comment provided by engineer. @@ -1647,7 +1858,7 @@ Ez az egyszer használatos hivatkozása! Connection timeout - Kapcsolat időtúllépés + Időtúllépés kapcsolódáskor No comment provided by engineer. @@ -1667,7 +1878,7 @@ Ez az egyszer használatos hivatkozása! Contact already exists - Létező ismerős + Az ismerős már létezik No comment provided by engineer. @@ -1692,7 +1903,7 @@ Ez az egyszer használatos hivatkozása! Contact name - Ismerős neve + Csak név No comment provided by engineer. @@ -1712,7 +1923,7 @@ Ez az egyszer használatos hivatkozása! Contacts can mark messages for deletion; you will be able to view them. - Az ismerősei törlésre jelölhetnek üzeneteket; ön majd meg tudja nézni azokat. + Az ismerősei törlésre jelölhetnek üzeneteket; Ön majd meg tudja nézni azokat. No comment provided by engineer. @@ -1740,6 +1951,11 @@ Ez az egyszer használatos hivatkozása! Alapverziószám: v%@ No comment provided by engineer. + + Corner + Sarok + No comment provided by engineer. + Correct name to %@? Név javítása erre: %@? @@ -1750,9 +1966,14 @@ Ez az egyszer használatos hivatkozása! Létrehozás No comment provided by engineer. + + Create 1-time link + Egyszer használható meghívó-hivatkozás létrehozása + No comment provided by engineer. + Create SimpleX address - SimpleX cím létrehozása + SimpleX-cím létrehozása No comment provided by engineer. @@ -1760,11 +1981,6 @@ Ez az egyszer használatos hivatkozása! Csoport létrehozása véletlenszerűen létrehozott profillal. No comment provided by engineer. - - Create an address to let people connect with you. - Cím létrehozása, hogy az emberek kapcsolatba léphessenek önnel. - No comment provided by engineer. - Create file Fájl létrehozása @@ -1777,7 +1993,7 @@ Ez az egyszer használatos hivatkozása! Create group link - Csoportos hivatkozás létrehozása + Csoporthivatkozás létrehozása No comment provided by engineer. @@ -1787,7 +2003,7 @@ Ez az egyszer használatos hivatkozása! Create new profile in [desktop app](https://simplex.chat/downloads/). 💻 - Új profil létrehozása az [asztali kliensben](https://simplex.chat/downloads/). 💻 + Új profil létrehozása a [számítógép-alkalmazásban](https://simplex.chat/downloads/). 💻 No comment provided by engineer. @@ -1797,7 +2013,7 @@ Ez az egyszer használatos hivatkozása! Create queue - Várólista létrehozása + Sorbaállítás létrehozása server test step @@ -1825,14 +2041,9 @@ Ez az egyszer használatos hivatkozása! Létrehozva ekkor: %@ copied message info - - Created on %@ - Létrehozva %@ - No comment provided by engineer. - Creating archive link - Archív hivatkozás létrehozása + Archívum hivatkozás létrehozása No comment provided by engineer. @@ -1845,6 +2056,11 @@ Ez az egyszer használatos hivatkozása! Jelenlegi jelkód No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + A jelenlegi feltételek szövegét nem lehetett betölteni, a feltételeket ezen a hivatkozáson keresztül vizsgálhatja felül: + No comment provided by engineer. + Current passphrase… Jelenlegi jelmondat… @@ -1865,6 +2081,11 @@ Ez az egyszer használatos hivatkozása! Személyreszabott idő No comment provided by engineer. + + Customizable message shape. + Testreszabható üzenetbuborékok. + No comment provided by engineer. + Customize theme Téma személyre szabása @@ -1882,17 +2103,17 @@ Ez az egyszer használatos hivatkozása! Database ID - Adatbázis ID + Adatbázis-azonosító No comment provided by engineer. Database ID: %d - Adatbázis azonosító: %d + Adatbázis-azonosító: %d copied message info Database IDs and Transport isolation option. - Adatbázis azonosítók és átviteli izolációs beállítások. + Adatbázis-azonosítók és átvitel-izolációs beállítások. No comment provided by engineer. @@ -1908,40 +2129,40 @@ Ez az egyszer használatos hivatkozása! Database encryption passphrase will be updated and stored in the keychain. - Az adatbázis titkosítási jelmondata frissül és tárolódik a kulcstartóban. + Az adatbázis titkosítási jelmondata frissítve lesz és a kulcstartóban kerül tárolásra. No comment provided by engineer. Database encryption passphrase will be updated. - Adatbázis titkosítási jelmondat frissítve lesz. + Az datbázis titkosítási jelmondata frissítve lesz. No comment provided by engineer. Database error - Adatbázis hiba + Adatbázishiba No comment provided by engineer. Database is encrypted using a random passphrase, you can change it. - Az adatbázis egy véletlenszerű jelmondattal van titkosítva, megváltoztatható. + Az adatbázis egy véletlenszerű jelmondattal van titkosítva, ami megváltoztatható. No comment provided by engineer. Database is encrypted using a random passphrase. Please change it before exporting. - Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Exportálás előtti módosítás szükséges. + Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Exportálás előtt változtassa meg. No comment provided by engineer. Database passphrase - Adatbázis jelmondat + Adatbázis-jelmondat No comment provided by engineer. Database passphrase & export - Adatbázis jelmondat és exportálás + Adatbázis-jelmondat és -exportálás No comment provided by engineer. @@ -1962,7 +2183,7 @@ Ez az egyszer használatos hivatkozása! Database will be encrypted and the passphrase stored in the keychain. - Az adatbázis titkosítva lesz, a jelmondat pedig a kulcstartóban lesz tárolva. + Az adatbázis titkosítva lesz, a jelmondat pedig a kulcstartóban kerül tárolásra. No comment provided by engineer. @@ -1975,7 +2196,7 @@ Ez az egyszer használatos hivatkozása! Database will be migrated when the app restarts - Az adatbázis az alkalmazás újraindításakor migrálásra kerül + Az adatbázis az alkalmazás újraindításakor átköltöztetésre kerül No comment provided by engineer. @@ -1996,7 +2217,8 @@ Ez az egyszer használatos hivatkozása! Delete Törlés - chat item action + alert action + chat item action swipe action @@ -2026,7 +2248,7 @@ Ez az egyszer használatos hivatkozása! Delete all files - Minden fájl törlése + Az összes fájl törlése No comment provided by engineer. @@ -2034,14 +2256,9 @@ Ez az egyszer használatos hivatkozása! Törlés, és az ismerős értesítése No comment provided by engineer. - - Delete archive - Archívum törlése - No comment provided by engineer. - - - Delete chat archive? - Csevegési archívum törlése? + + Delete chat + Csevegés törlése No comment provided by engineer. @@ -2054,6 +2271,11 @@ Ez az egyszer használatos hivatkozása! Csevegési profil törlése? No comment provided by engineer. + + Delete chat? + Csevegés törlése? + No comment provided by engineer. + Delete connection Kapcsolat törlése @@ -2091,12 +2313,12 @@ Ez az egyszer használatos hivatkozása! Delete files for all chat profiles - Fájlok törlése minden csevegési profilból + Fájlok törlése az összes csevegési profilból No comment provided by engineer. Delete for everyone - Törlés mindenkinél + Törlés az összes tagnál chat feature @@ -2131,7 +2353,7 @@ Ez az egyszer használatos hivatkozása! Delete member message? - Csoporttag üzenet törlése? + Csoporttag üzenetének törlése? No comment provided by engineer. @@ -2159,9 +2381,14 @@ Ez az egyszer használatos hivatkozása! Régi adatbázis törlése? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Legfeljebb 200 üzenet egyszerre való törlése, vagy moderálása. + No comment provided by engineer. + Delete pending connection? - Függő kapcsolatfelvételi kérések törlése? + Függőben lévő ismerőskérelem törlése? No comment provided by engineer. @@ -2171,12 +2398,12 @@ Ez az egyszer használatos hivatkozása! Delete queue - Várólista törlése + Sorbaállítás törlése server test step Delete up to 20 messages at once. - Legfeljebb 20 üzenet törlése egyszerre. + Legfeljebb 20 üzenet egyszerre való törlése. No comment provided by engineer. @@ -2209,6 +2436,11 @@ Ez az egyszer használatos hivatkozása! Törlési hibák No comment provided by engineer. + + Delivered even when Apple drops them. + Kézbesítés akkor is, amikor az Apple eldobja őket. + No comment provided by engineer. + Delivery Kézbesítés @@ -2221,7 +2453,7 @@ Ez az egyszer használatos hivatkozása! Delivery receipts! - Kézbesítési igazolások! + Kézbesítési jelentések! No comment provided by engineer. @@ -2236,7 +2468,7 @@ Ez az egyszer használatos hivatkozása! Desktop app version %@ is not compatible with this app. - Az asztali kliens verziója %@ nem kompatibilis ezzel az alkalmazással. + A számítógép-alkalmazás verziója %@ nem kompatibilis ezzel az alkalmazással. No comment provided by engineer. @@ -2266,7 +2498,7 @@ Ez az egyszer használatos hivatkozása! Details - Részletek + További részletek No comment provided by engineer. @@ -2291,17 +2523,17 @@ Ez az egyszer használatos hivatkozása! Device authentication is disabled. Turning off SimpleX Lock. - A készüléken nincs beállítva a képernyőzár. A SimpleX zár ki van kapcsolva. + Az eszközön nincs beállítva a képernyőzár. A SimpleX-zár ki van kapcsolva. No comment provided by engineer. Device authentication is not enabled. You can turn on SimpleX Lock via Settings, once you enable device authentication. - A készüléken nincs beállítva a képernyőzár. A SimpleX zár az „Adatvédelem és biztonság” menüben kapcsolható be, miután beállította a képernyőzárat az eszközén. + Az eszközön nincs beállítva a képernyőzár. A SimpleX-zár az „Adatvédelem és biztonság” menüben kapcsolható be, miután beállította a képernyőzárat az eszközén. No comment provided by engineer. Different names, avatars and transport isolation. - Különböző nevek, avatarok és átviteli izoláció. + Különböző nevek, profilképek és átvitel-izoláció. No comment provided by engineer. @@ -2309,8 +2541,13 @@ Ez az egyszer használatos hivatkozása! Közvetlen üzenetek chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + A tagok közötti közvetlen üzenetek le vannak tiltva ebben a csevegésben. + No comment provided by engineer. + + + Direct messages between members are prohibited. A közvetlen üzenetek küldése a tagok között le van tiltva ebben a csoportban. No comment provided by engineer. @@ -2321,12 +2558,12 @@ Ez az egyszer használatos hivatkozása! Disable SimpleX Lock - SimpleX zár kikapcsolása + SimpleX-zár kikapcsolása authentication reason Disable for all - Letiltás mindenki számára + Letiltás az összes tag számára No comment provided by engineer. @@ -2349,8 +2586,8 @@ Ez az egyszer használatos hivatkozása! Az eltűnő üzenetek küldése le van tiltva ebben a csevegésben. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Az eltűnő üzenetek küldése le van tiltva ebben a csoportban. No comment provided by engineer. @@ -2386,7 +2623,7 @@ Ez az egyszer használatos hivatkozása! Do NOT send messages directly, even if your or destination server does not support private routing. - Ne küldjön üzeneteket közvetlenül, még akkor sem, ha az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Ne küldjön üzeneteket közvetlenül, még akkor sem, ha az Ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. No comment provided by engineer. @@ -2401,7 +2638,7 @@ Ez az egyszer használatos hivatkozása! Do it later - Későbbre halaszt + Befejezés később No comment provided by engineer. @@ -2409,6 +2646,11 @@ Ez az egyszer használatos hivatkozása! Az előzmények ne kerüljenek elküldésre az új tagok számára. No comment provided by engineer. + + Do not use credentials with proxy. + Ne használja a hitelesítőadatokat proxyval. + No comment provided by engineer. + Don't create address Ne hozzon létre címet @@ -2432,7 +2674,8 @@ Ez az egyszer használatos hivatkozása! Download Letöltés - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ Ez az egyszer használatos hivatkozása! Fájl letöltése server test step + + Download files + Fájlok letöltése + alert action + Downloaded Letöltve @@ -2471,7 +2719,7 @@ Ez az egyszer használatos hivatkozása! Duplicate display name! - Duplikált megjelenítési név! + Duplikált megjelenített név! No comment provided by engineer. @@ -2479,6 +2727,11 @@ Ez az egyszer használatos hivatkozása! Időtartam No comment provided by engineer. + + E2E encrypted notifications. + Végpontok közötti titkosított értesítések. + No comment provided by engineer. + Edit Szerkesztés @@ -2499,9 +2752,14 @@ Ez az egyszer használatos hivatkozása! Engedélyezés (felülírások megtartásával) No comment provided by engineer. + + Enable Flux + Flux engedélyezése + No comment provided by engineer. + Enable SimpleX Lock - SimpleX zár bekapcsolása + SimpleX-zár bekapcsolása authentication reason @@ -2521,7 +2779,7 @@ Ez az egyszer használatos hivatkozása! Enable for all - Engedélyezés mindenki számára + Engedélyezés az összes tag számára No comment provided by engineer. @@ -2566,7 +2824,7 @@ Ez az egyszer használatos hivatkozása! Enabled for - Engedélyezve + Számukra engedélyezve: No comment provided by engineer. @@ -2586,7 +2844,7 @@ Ez az egyszer használatos hivatkozása! Encrypt stored files & media - Tárolt fájlok és médiatartalmak titkosítása + A tárolt fájlok- és a médiatartalmak titkosítása No comment provided by engineer. @@ -2606,12 +2864,12 @@ Ez az egyszer használatos hivatkozása! Encrypted message: database error - Titkosított üzenet: adatbázis hiba + Titkosított üzenet: adatbázishiba notification Encrypted message: database migration error - Titkosított üzenet: adatbázis-átköltöztetés hiba + Titkosított üzenet: adatbázis-átköltöztetési hiba notification @@ -2646,7 +2904,7 @@ Ez az egyszer használatos hivatkozása! Enter correct passphrase. - Helyes jelmondat bevitele. + Adja meg a helyes jelmondatot. No comment provided by engineer. @@ -2676,17 +2934,17 @@ Ez az egyszer használatos hivatkozása! Enter this device name… - Eszköznév megadása… + Adja meg ennek az eszköznek a nevét… No comment provided by engineer. Enter welcome message… - Üdvözlő üzenetet megadása… + Üdvözlőüzenet megadása… placeholder Enter welcome message… (optional) - Üdvözlő üzenetet megadása… (opcionális) + Üdvözlőüzenet megadása… (nem kötelező) placeholder @@ -2704,26 +2962,36 @@ Ez az egyszer használatos hivatkozása! Hiba a cím megváltoztatásának megszakításakor No comment provided by engineer. + + Error accepting conditions + Hiba a feltételek elfogadásakor + alert title + Error accepting contact request - Hiba történt a kapcsolatfelvételi kérelem elfogadásakor - No comment provided by engineer. - - - Error accessing database file - Hiba az adatbázisfájl elérésekor + Hiba történt a kapcsolatkérés elfogadásakor No comment provided by engineer. Error adding member(s) - Hiba a tag(-ok) hozzáadásakor + Hiba a tag(ok) hozzáadásakor No comment provided by engineer. + + Error adding server + Hiba a kiszolgáló hozzáadásakor + alert title + Error changing address Hiba a cím megváltoztatásakor No comment provided by engineer. + + Error changing connection profile + Hiba a kapcsolati profilra való váltáskor + No comment provided by engineer. + Error changing role Hiba a szerepkör megváltoztatásakor @@ -2734,6 +3002,11 @@ Ez az egyszer használatos hivatkozása! Hiba a beállítás megváltoztatásakor No comment provided by engineer. + + Error changing to incognito! + Hiba az inkognitóprofilra való váltáskor! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Hiba a(z) %@ továbbító kiszolgálóhoz való kapcsolódáskor. Próbálja meg később. @@ -2751,7 +3024,7 @@ Ez az egyszer használatos hivatkozása! Error creating group link - Hiba a csoport hivatkozásának létrehozásakor + Hiba a csoporthivatkozás létrehozásakor No comment provided by engineer. @@ -2806,7 +3079,7 @@ Ez az egyszer használatos hivatkozása! Error deleting user profile - Hiba a felhasználói profil törlésekor + Hiba a felhasználó-profil törlésekor No comment provided by engineer. @@ -2849,9 +3122,14 @@ Ez az egyszer használatos hivatkozása! Hiba a csoporthoz való csatlakozáskor No comment provided by engineer. - - Error loading %@ servers - Hiba a %@ kiszolgálók betöltésekor + + Error loading servers + Hiba a kiszolgálók betöltésekor + alert title + + + Error migrating settings + Hiba a beallítások átköltöztetésekor No comment provided by engineer. @@ -2862,7 +3140,7 @@ Ez az egyszer használatos hivatkozása! Error receiving file Hiba a fájl fogadásakor - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,14 +3162,9 @@ Ez az egyszer használatos hivatkozása! Hiba a statisztikák visszaállításakor No comment provided by engineer. - - Error saving %@ servers - Hiba történt a %@ kiszolgálók mentése közben - No comment provided by engineer. - Error saving ICE servers - Hiba az ICE kiszolgálók mentésekor + Hiba az ICE-kiszolgálók mentésekor No comment provided by engineer. @@ -2901,7 +3174,7 @@ Ez az egyszer használatos hivatkozása! Error saving passcode - Hiba a jelkód mentése közben + Hiba a jelkód mentésekor No comment provided by engineer. @@ -2909,6 +3182,11 @@ Ez az egyszer használatos hivatkozása! Hiba a jelmondat kulcstartóba történő mentésekor No comment provided by engineer. + + Error saving servers + Hiba a kiszolgálók mentésekor + alert title + Error saving settings Hiba a beállítások mentésekor @@ -2916,12 +3194,12 @@ Ez az egyszer használatos hivatkozása! Error saving user password - Hiba a felhasználó jelszavának mentésekor + Hiba a felhasználói jelszó mentésekor No comment provided by engineer. Error scanning code: %@ - Hiba a kód beolvasása közben: %@ + Hiba a kód beolvasásakor: %@ No comment provided by engineer. @@ -2941,7 +3219,7 @@ Ez az egyszer használatos hivatkozása! Error setting delivery receipts! - Hiba történt a kézbesítési igazolások beállításakor! + Hiba történt a kézbesítési jelentések beállításakor! No comment provided by engineer. @@ -2954,19 +3232,24 @@ Ez az egyszer használatos hivatkozása! Hiba a csevegés megállításakor No comment provided by engineer. + + Error switching profile + Hiba a profilváltáskor + No comment provided by engineer. + Error switching profile! - Hiba a profil váltásakor! - No comment provided by engineer. + Hiba a profilváltásakor! + alertTitle Error synchronizing connection - Hiba a kapcsolat szinkronizálása során + Hiba a kapcsolat szinkronizálásakor No comment provided by engineer. Error updating group link - Hiba a csoport hivatkozás frissítésekor + Hiba a csoporthivatkozás frissítésekor No comment provided by engineer. @@ -2974,6 +3257,11 @@ Ez az egyszer használatos hivatkozása! Hiba az üzenet frissítésekor No comment provided by engineer. + + Error updating server + Hiba a kiszolgáló frissítésekor + alert title + Error updating settings Hiba történt a beállítások frissítésekor @@ -2981,7 +3269,7 @@ Ez az egyszer használatos hivatkozása! Error updating user privacy - Hiba a felhasználói beállítások frissítésekor + Hiba a felhasználói adatvédelem frissítésekor No comment provided by engineer. @@ -2991,7 +3279,7 @@ Ez az egyszer használatos hivatkozása! Error verifying passphrase: - Hiba a jelmondat ellenőrzésekor: + Hiba a jelmondat hitelesítésekor: No comment provided by engineer. @@ -3002,17 +3290,16 @@ Ez az egyszer használatos hivatkozása! Error: %@ Hiba: %@ - file error text - snd error text + alert message Error: URL is invalid - Hiba: az URL érvénytelen + Hiba: a webcím érvénytelen No comment provided by engineer. Error: no database file - Hiba: nincs adatbázis fájl + Hiba: nincs adatbázisfájl No comment provided by engineer. @@ -3020,6 +3307,11 @@ Ez az egyszer használatos hivatkozása! Hibák No comment provided by engineer. + + Errors in servers configuration. + Hibák a kiszolgálók konfigurációjában. + servers error + Even when disabled in the conversation. Akkor is, ha le van tiltva a beszélgetésben. @@ -3062,7 +3354,7 @@ Ez az egyszer használatos hivatkozása! Exporting database archive… - Adatbázis archívum exportálása… + Adatbázis-archívum exportálása… No comment provided by engineer. @@ -3077,7 +3369,7 @@ Ez az egyszer használatos hivatkozása! Faster joining and more reliable messages. - Gyorsabb csatlakozás és megbízhatóbb üzenet kézbesítés. + Gyorsabb csatlakozás és megbízhatóbb üzenetkézbesítés. No comment provided by engineer. @@ -3090,6 +3382,13 @@ Ez az egyszer használatos hivatkozása! Fájlhiba No comment provided by engineer. + + File errors: +%@ + Fájlhiba: +%@ + alert message + File not found - most likely file was deleted or cancelled. A fájl nem található - valószínűleg a fájlt törölték vagy visszavonták. @@ -3112,7 +3411,7 @@ Ez az egyszer használatos hivatkozása! File will be deleted from servers. - A fájl törölve lesz a kiszolgálóról. + A fájl törölve lesz a kiszolgálókról. No comment provided by engineer. @@ -3137,27 +3436,27 @@ Ez az egyszer használatos hivatkozása! Files & media - Fájlok és média + Fájlok és médiatartalmak No comment provided by engineer. Files and media - Fájlok és médiatartalom + Fájlok és médiatartalmak chat feature - - Files and media are prohibited in this group. - A fájlok- és a médiatartalom küldése le van tiltva ebben a csoportban. + + Files and media are prohibited. + A fájlok- és a médiatartalmak le vannak tiltva ebben a csoportban. No comment provided by engineer. Files and media not allowed - Fájlok és média tartalom küldése le van tiltva + A fájlok- és médiatartalmak nincsenek engedélyezve No comment provided by engineer. Files and media prohibited! - A fájlok- és a médiatartalom küldése le van tiltva! + A fájlok- és a médiatartalmak küldése le van tiltva! No comment provided by engineer. @@ -3215,21 +3514,61 @@ Ez az egyszer használatos hivatkozása! Csoporttag általi javítás nem támogatott No comment provided by engineer. + + For chat profile %@: + A(z) %@ nevű csevegési profilhoz: + servers error + For console Konzolhoz No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Például, ha az Ön ismerőse egy SimpleX Chat-kiszolgálón keresztül fogadja az üzeneteket, az Ön alkalmazása egy Flux-kiszolgálón keresztül fogja azokat kézbesíteni. + No comment provided by engineer. + + + For private routing + A privát útválasztáshoz + No comment provided by engineer. + + + For social media + A közösségi médiához + No comment provided by engineer. + Forward Továbbítás chat item action + + Forward %d message(s)? + %d üzenet továbbítása? + alert title + Forward and save messages Üzenetek továbbítása és mentése No comment provided by engineer. + + Forward messages + Üzenetek továbbítása + alert action + + + Forward messages without files? + Üzenetek továbbítása fájlok nélkül? + alert message + + + Forward up to 20 messages at once. + Legfeljebb 20 üzenet egyszerre való továbbítása. + No comment provided by engineer. + Forwarded Továbbított @@ -3240,32 +3579,37 @@ Ez az egyszer használatos hivatkozása! Továbbítva innen: No comment provided by engineer. + + Forwarding %lld messages + %lld üzenet továbbítása + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. - A(z) %@ továbbító kiszolgáló nem tudott csatlakozni a(z) %@ célkiszolgálóhoz. Próbálja meg később. + A(z) %@ továbbító-kiszolgáló nem tudott csatlakozni a(z) %@ célkiszolgálóhoz. Próbálja meg később. No comment provided by engineer. Forwarding server address is incompatible with network settings: %@. - A továbbító kiszolgáló címe nem kompatibilis a hálózati beállításokkal: %@. + A továbbító-kiszolgáló címe nem kompatibilis a hálózati beállításokkal: %@. No comment provided by engineer. Forwarding server version is incompatible with network settings: %@. - A továbbító kiszolgáló verziója nem kompatibilis a hálózati beállításokkal: %@. + A továbbító-kiszolgáló verziója nem kompatibilis a hálózati beállításokkal: %@. No comment provided by engineer. Forwarding server: %1$@ Destination server error: %2$@ - Továbbító kiszolgáló: %1$@ + Továbbító-kiszolgáló: %1$@ Célkiszolgáló hiba:%2$@ snd error text Forwarding server: %1$@ Error: %2$@ - Továbbító kiszolgáló: %1$@ + Továbbító-kiszolgáló: %1$@ Hiba: %2$@ snd error text @@ -3286,17 +3630,12 @@ Hiba: %2$@ Full name (optional) - Teljes név (opcionális) - No comment provided by engineer. - - - Full name: - Teljes név: + Teljes név (nem kötelező) No comment provided by engineer. Fully decentralized – visible only to members. - Teljesen decentralizált - kizárólag tagok számára látható. + Teljesen decentralizált - csak a tagok számára látható. No comment provided by engineer. @@ -3306,7 +3645,7 @@ Hiba: %2$@ Further reduced battery usage - Tovább csökkentett akkumulátor használat + Tovább csökkentett akkumulátor-használat No comment provided by engineer. @@ -3346,72 +3685,37 @@ Hiba: %2$@ Group full name (optional) - Csoport teljes neve (opcionális) + Csoport teljes neve (nem kötelező) No comment provided by engineer. Group image - Csoportkép + Csoport profilképe No comment provided by engineer. Group invitation - Csoportos meghívó + Csoportmeghívó No comment provided by engineer. Group invitation expired - A csoport meghívó lejárt + A csoportmeghívó lejárt No comment provided by engineer. Group invitation is no longer valid, it was removed by sender. - A csoport meghívó már nem érvényes, a küldője törölte. + A csoportmeghívó már nem érvényes, a küldője eltávolította. No comment provided by engineer. Group link - Csoport hivatkozás + Csoporthivatkozás No comment provided by engineer. Group links - Csoport hivatkozások - No comment provided by engineer. - - - Group members can add message reactions. - Csoporttagok üzenetreakciókat adhatnak hozzá. - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - A csoport tagjai véglegesen törölhetik az elküldött üzeneteiket. (24 óra) - No comment provided by engineer. - - - Group members can send SimpleX links. - A csoport tagjai küldhetnek SimpleX hivatkozásokat. - No comment provided by engineer. - - - Group members can send direct messages. - A csoport tagjai küldhetnek egymásnak közvetlen üzeneteket. - No comment provided by engineer. - - - Group members can send disappearing messages. - A csoport tagjai küldhetnek eltűnő üzeneteket. - No comment provided by engineer. - - - Group members can send files and media. - A csoport tagjai küldhetnek fájlokat és médiatartalmakat. - No comment provided by engineer. - - - Group members can send voice messages. - A csoport tagjai küldhetnek hangüzeneteket. + Csoporthivatkozások No comment provided by engineer. @@ -3426,7 +3730,7 @@ Hiba: %2$@ Group preferences - Csoport beállítások + Csoportbeállítások No comment provided by engineer. @@ -3441,27 +3745,27 @@ Hiba: %2$@ Group welcome message - Csoport üdvözlő üzenete + A csoport üdvözlőüzenete No comment provided by engineer. Group will be deleted for all members - this cannot be undone! - Csoport törlésre kerül minden tag számára - ez a művelet nem vonható vissza! + A csoport törlésre kerül az összes tag számára - ez a művelet nem vonható vissza! No comment provided by engineer. Group will be deleted for you - this cannot be undone! - A csoport törlésre kerül az ön számára - ez a művelet nem vonható vissza! + A csoport törlésre kerül az Ön számára - ez a művelet nem vonható vissza! No comment provided by engineer. Help - Segítség + Súgó No comment provided by engineer. Hidden - Rejtett + Se név, se üzenet No comment provided by engineer. @@ -3471,12 +3775,12 @@ Hiba: %2$@ Hidden profile password - Rejtett profil jelszó + Rejtett profiljelszó No comment provided by engineer. Hide - Elrejt + Összecsukás chat item action @@ -3491,7 +3795,7 @@ Hiba: %2$@ Hide: - Elrejt: + Elrejtés: No comment provided by engineer. @@ -3509,9 +3813,14 @@ Hiba: %2$@ Hogyan működik a SimpleX No comment provided by engineer. - - How it works - Hogyan működik + + How it affects privacy + Hogyan érinti az adatvédelmet + No comment provided by engineer. + + + How it helps privacy + Hogyan segíti az adatvédelmet No comment provided by engineer. @@ -3526,7 +3835,7 @@ Hiba: %2$@ How to use your servers - Kiszolgálók használata + Saját kiszolgálók használata No comment provided by engineer. @@ -3539,14 +3848,19 @@ Hiba: %2$@ ICE-kiszolgálók (soronként egy) No comment provided by engineer. + + IP address + IP-cím + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. - Ha nem tud személyesen találkozni, mutassa meg a QR-kódot egy videohívás során, vagy ossza meg a hivatkozást. + Ha nem tud személyesen találkozni, mutassa meg a QR-kódot egy videohívás közben, vagy ossza meg a hivatkozást. No comment provided by engineer. If you enter this passcode when opening the app, all app data will be irreversibly removed! - Ha az alkalmazás megnyitásakor megadja ezt a jelkódot, az összes alkalmazásadat véglegesen törlődik! + Ha az alkalmazás megnyitásakor megadja ezt a jelkódot, az összes alkalmazásadat véglegesen eltávolításra kerül! No comment provided by engineer. @@ -3556,12 +3870,12 @@ Hiba: %2$@ 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). - Ha most kell használnia a csevegést, koppintson a ** Csináld később** elemre (az alkalmazás újraindításakor felajánlásra kerül az adatbázis áttelepítése). + Ha most kell használnia a csevegést, koppintson alább a **Befejezés később** lehetőségre (az alkalmazás újraindításakor felajánlásra kerül az adatbázis átköltöztetése). No comment provided by engineer. Ignore - Figyelmen kívül hagyás + Mellőzés No comment provided by engineer. @@ -3579,8 +3893,8 @@ Hiba: %2$@ Azonnal No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Spam és visszaélések elleni védelem No comment provided by engineer. @@ -3614,9 +3928,16 @@ Hiba: %2$@ Archívum importálása No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Továbbfejlesztett kézbesítés, csökkentett adatforgalom-használat. +További fejlesztések hamarosan! + No comment provided by engineer. + Improved message delivery - Továbbfejlesztett üzenetküldés + Továbbfejlesztett üzenetkézbesítés No comment provided by engineer. @@ -3651,17 +3972,17 @@ Hiba: %2$@ Incognito groups - Inkognitó csoportok + Inkognitócsoportok No comment provided by engineer. Incognito mode - Inkognitó mód + Inkognitómód No comment provided by engineer. Incognito mode protects your privacy by using a new random profile for each contact. - Az inkognitómód védi személyes adatait azáltal, hogy minden ismerőshöz új véletlenszerű profilt használ. + Az inkognitómód védi személyes adatait azáltal, hogy az összes ismerőséhez új, véletlenszerű profilt használ. No comment provided by engineer. @@ -3681,7 +4002,7 @@ Hiba: %2$@ Incompatible database version - Nem kompatibilis adatbázis verzió + Nem kompatibilis adatbázis-verzió No comment provided by engineer. @@ -3714,21 +4035,21 @@ Hiba: %2$@ A [SimpleX Chat terminálhoz] telepítése (https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Azonnal + No comment provided by engineer. + Instant push notifications will be hidden! - Az azonnali push értesítések elrejtésre kerülnek! + Az azonnali push-értesítések elrejtésre kerülnek! No comment provided by engineer. - - Instantly - Azonnal - No comment provided by engineer. - Interface - Felület + Kezelőfelület No comment provided by engineer. @@ -3743,12 +4064,12 @@ Hiba: %2$@ Invalid connection link - Érvénytelen kapcsolati hivatkozás + Érvénytelen kapcsolattartási hivatkozás No comment provided by engineer. Invalid display name! - Érvénytelen megjelenítendő felhaszálónév! + Érvénytelen megjelenítendő név! No comment provided by engineer. @@ -3774,7 +4095,7 @@ Hiba: %2$@ Invalid server address! Érvénytelen kiszolgálócím! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4117,11 @@ Hiba: %2$@ Tagok meghívása No comment provided by engineer. + + Invite to chat + Meghívás a csevegésbe + No comment provided by engineer. + Invite to group Meghívás a csoportba @@ -3811,19 +4137,19 @@ Hiba: %2$@ Az üzenetek végleges törlése le van tiltva ebben a csevegésben. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Az üzenetek végleges törlése le van tiltva ebben a csoportban. No comment provided by engineer. It allows having many anonymous connections without any shared data between them in a single chat profile. - 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. + Lehetővé teszi, hogy egyetlen csevegőprofilon belül több névtelen kapcsolat legyen, anélkül, hogy megosztott adatok lennének közöttük. No comment provided by engineer. It can happen when you or your connection used the old database backup. - Ez akkor fordulhat elő, ha ön vagy az ismerőse régi adatbázis biztonsági mentést használt. + Ez akkor fordulhat elő, ha Ön vagy az ismerőse régi adatbázis biztonsági mentést használt. No comment provided by engineer. @@ -3839,7 +4165,7 @@ Hiba: %2$@ It protects your IP address and connections. - Védi az IP-címét és a kapcsolatokat. + Védi az IP-címét és a kapcsolatait. No comment provided by engineer. @@ -3891,7 +4217,7 @@ Hiba: %2$@ Join your group? This is your link for group %@! Csatlakozik a csoportjához? -Ez az ön hivatkozása a(z) %@ csoporthoz! +Ez az Ön hivatkozása a(z) %@ nevű csoporthoz! No comment provided by engineer. @@ -3902,7 +4228,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Keep Megtart - No comment provided by engineer. + alert action Keep conversation @@ -3917,7 +4243,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Keep unused invitation? Fel nem használt meghívó megtartása? - No comment provided by engineer. + alert title Keep your connections @@ -3926,12 +4252,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! KeyChain error - Kulcstartó hiba + Kulcstartóhiba No comment provided by engineer. Keychain error - Kulcstartó hiba + Kulcstartóhiba No comment provided by engineer. @@ -3954,6 +4280,16 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Elhagyás swipe action + + Leave chat + Csevegés elhagyása + No comment provided by engineer. + + + Leave chat? + Csevegés elhagyása? + No comment provided by engineer. + Leave group Csoport elhagyása @@ -3966,7 +4302,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Let's talk in SimpleX Chat - Beszélgessünk a SimpleX Chat-ben + Beszélgessünk a SimpleX Chatben email subject @@ -3981,17 +4317,17 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Link mobile and desktop apps! 🔗 - Társítsa össze a mobil és az asztali alkalmazásokat! 🔗 + Társítsa össze a hordozható eszköz- és számítógépes alkalmazásokat! 🔗 No comment provided by engineer. Linked desktop options - Összekapcsolt számítógép beállítások + Társított számítógép beállítások No comment provided by engineer. Linked desktops - Összekapcsolt számítógépek + Társított számítógépek No comment provided by engineer. @@ -4004,11 +4340,6 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Élő üzenetek No comment provided by engineer. - - Local - Helyi - No comment provided by engineer. - Local name Helyi név @@ -4029,11 +4360,6 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Zárolási mód No comment provided by engineer. - - Make a private connection - Privát kapcsolat létrehozása - No comment provided by engineer. - Make one message disappear Egy üzenet eltüntetése @@ -4044,29 +4370,19 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Tegye priváttá a profilját! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Győződjön meg arról, hogy a %@ kiszolgálócímek megfelelő formátumúak, sorszeparáltak és nincsenek duplikálva (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Győződjön meg arról, hogy a WebRTC ICE-kiszolgáló címei megfelelő formátumúak, sorszeparáltak és nincsenek duplikálva. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Sokan kérdezték: *ha a SimpleX-nek nincsenek felhasználói azonosítói, akkor hogyan tud üzeneteket kézbesíteni?* - No comment provided by engineer. - Mark deleted for everyone - Jelölje meg mindenki számára töröltként + Jelölje meg az összes tag számára töröltként No comment provided by engineer. Mark read - Olvasottnak jelölés + Megjelölés olvasottként No comment provided by engineer. @@ -4104,9 +4420,14 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Inaktív tag item status text + + Member role will be changed to "%@". All chat members will be notified. + A tag szerepeköre meg fog változni a következőre: "%@". A csevegés tagjai értesítést fognak kapni. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. - A tag szerepköre meg fog változni erre: „%@”. A csoport minden tagja értesítést kap róla. + A tag szerepköre meg fog változni erre: „%@”. A csoportban az összes tag értesítve lesz. No comment provided by engineer. @@ -4114,11 +4435,51 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! A tag szerepköre meg fog változni erre: „%@”. A tag új meghívást fog kapni. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + A tag el lesz távolítva a csevegésből - ezt a műveletet nem lehet visszavonni! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! A tag eltávolítása a csoportból - ez a művelet nem vonható vissza! No comment provided by engineer. + + Members can add message reactions. + Csoporttagok üzenetreakciókat adhatnak hozzá. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + A csoport tagjai véglegesen törölhetik az elküldött üzeneteiket. (24 óra) + No comment provided by engineer. + + + Members can send SimpleX links. + A csoport tagjai küldhetnek SimpleX-hivatkozásokat. + No comment provided by engineer. + + + Members can send direct messages. + A csoport tagjai küldhetnek egymásnak közvetlen üzeneteket. + No comment provided by engineer. + + + Members can send disappearing messages. + A csoport tagjai küldhetnek eltűnő üzeneteket. + No comment provided by engineer. + + + Members can send files and media. + A csoport tagjai küldhetnek fájlokat és médiatartalmakat. + No comment provided by engineer. + + + Members can send voice messages. + A csoport tagjai küldhetnek hangüzeneteket. + No comment provided by engineer. + Menus Menük @@ -4131,12 +4492,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Message delivery receipts! - Üzenetkézbesítési bizonylatok! + Üzenetkézbesítési jelentések! No comment provided by engineer. Message delivery warning - Üzenet kézbesítési figyelmeztetés + Üzenetkézbesítési figyelmeztetés item status text @@ -4156,7 +4517,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Message queue info - Üzenet-várakoztatási információ + Üzenet-sorbaállítási információ No comment provided by engineer. @@ -4169,8 +4530,8 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Az üzenetreakciók küldése le van tiltva ebben a csevegésben. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Az üzenetreakciók küldése le van tiltva ebben a csoportban. No comment provided by engineer. @@ -4184,6 +4545,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Üzenetkiszolgálók No comment provided by engineer. + + Message shape + Üzenetbuborék formája + No comment provided by engineer. + Message source remains private. Az üzenet forrása titokban marad. @@ -4201,7 +4567,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Message text - Üzenet szövege + Név és üzenet No comment provided by engineer. @@ -4234,6 +4600,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Elküldött üzenetek No comment provided by engineer. + + Messages were deleted after you selected them. + Az üzeneteket törölték miután kiválasztotta őket. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Az üzeneteket, fájlokat és hívásokat **végpontok közötti titkosítással**, sérülés utáni titkosság-védelemmel és -helyreállítással, továbbá visszautasítással védi. @@ -4276,7 +4647,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Migrating database archive… - Adatbázis archívum migrálása… + Adatbázis-archívum átköltöztetése… No comment provided by engineer. @@ -4291,7 +4662,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! 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). - Sikertelen átköltöztetés. Koppintson a **Kihagyás** lehetőségre az aktuális adatbázis használatának folytatásához. Jelentse a problémát az alkalmazás fejlesztőinek csevegésben vagy e-mailben [chat@simplex.chat](mailto:chat@simplex.chat). + Sikertelen átköltöztetés. Koppintson a **Kihagyás** lehetőségre a jelenlegi adatbázis használatának folytatásához. Jelentse a problémát az alkalmazás fejlesztőinek csevegésben vagy e-mailben [chat@simplex.chat](mailto:chat@simplex.chat). No comment provided by engineer. @@ -4299,9 +4670,9 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Az átköltöztetés befejeződött No comment provided by engineer. - - Migrations: %@ - Átköltöztetések: %@ + + Migrations: + Átköltöztetések: No comment provided by engineer. @@ -4311,12 +4682,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Moderated at - Moderálva lett ekkor: + Moderálva ekkor: No comment provided by engineer. Moderated at: %@ - Moderálva lett ekkor: %@ + Moderálva ekkor: %@ copied message info @@ -4329,6 +4700,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Megbízhatóbb hálózati kapcsolat. No comment provided by engineer. + + More reliable notifications + Megbízhatóbb értesítések + No comment provided by engineer. + Most likely this connection is deleted. Valószínűleg ez a kapcsolat törlésre került. @@ -4364,6 +4740,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Internetkapcsolat No comment provided by engineer. + + Network decentralization + Hálózati decentralizáció + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Hálózati problémák - az üzenet többszöri elküldési kísérlet után lejárt. @@ -4374,6 +4755,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Hálózatkezelés No comment provided by engineer. + + Network operator + Hálózati üzemeltető + No comment provided by engineer. + Network settings Hálózati beállítások @@ -4389,6 +4775,16 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Új jelkód No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Minden alkalommal, amikor elindítja az alkalmazást, új SOCKS-hitelesítő-adatokat fog használni. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Az összes kiszolgálóhoz új, SOCKS-hitelesítő-adatok legyenek használva. + No comment provided by engineer. + New chat Új beszélgetés @@ -4401,7 +4797,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! New contact request - Új kapcsolattartási kérelem + Új kapcsolatkérés notification @@ -4409,14 +4805,9 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Új kapcsolat: notification - - New database archive - Új adatbázis-archívum - No comment provided by engineer. - New desktop app! - Új asztali alkalmazás! + Új számítógép-alkalmazás! No comment provided by engineer. @@ -4424,6 +4815,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Új megjelenítési név No comment provided by engineer. + + New events + Új események + notification + New in %@ Újdonságok a(z) %@ verzióban @@ -4449,6 +4845,11 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Új jelmondat… No comment provided by engineer. + + New server + Új kiszolgáló + No comment provided by engineer. + No Nem @@ -4461,7 +4862,7 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! No contacts selected - Nem kerültek ismerősök kiválasztásra + Nincs kiválasztva ismerős No comment provided by engineer. @@ -4476,12 +4877,12 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! No device token! - Nincs eszköztoken! + Nincs kiszüléktoken! No comment provided by engineer. No direct connection yet, message is forwarded by admin. - Még nincs közvetlen kapcsolat, az üzenetet az admin továbbítja. + Még nincs közvetlen kapcsolat, az üzenetet az adminisztrátor továbbítja. item status description @@ -4504,21 +4905,71 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Nincs információ, próbálja meg újratölteni No comment provided by engineer. + + No media & file servers. + Nincsenek média- és fájlkiszolgálók. + servers error + + + No message servers. + Nincsenek üzenet-kiszolgálók. + servers error + No network connection Nincs hálózati kapcsolat No comment provided by engineer. + + No permission to record speech + Nincs jogosultság megadva a beszéd rögzítéséhez + No comment provided by engineer. + + + No permission to record video + Nincs jogosultság megadva a videó rögzítéséhez + No comment provided by engineer. + No permission to record voice message Nincs engedély a hangüzenet rögzítésére No comment provided by engineer. + + No push server + Helyi + No comment provided by engineer. + No received or sent files Nincsenek fogadott vagy küldött fájlok No comment provided by engineer. + + No servers for private message routing. + Nincsenek kiszolgálók a privát üzenet-útválasztáshoz. + servers error + + + No servers to receive files. + Nincsenek fájlfogadó-kiszolgálók. + servers error + + + No servers to receive messages. + Nincsenek üzenetfogadó-kiszolgálók. + servers error + + + No servers to send files. + Nincsenek fájlküldő-kiszolgálók. + servers error + + + No user identifiers. + Nincsenek felhasználó-azonosítók. + No comment provided by engineer. + Not compatible! Nem kompatibilis! @@ -4526,9 +4977,14 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Nothing selected - Semmi sincs kiválasztva + Nincs kiválasztva semmi No comment provided by engineer. + + Nothing to forward! + Nincs mit továbbítani! + alert title + Notifications Értesítések @@ -4539,11 +4995,16 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Az értesítések le vannak tiltva! No comment provided by engineer. + + Notifications privacy + Értesítési adatvédelem + No comment provided by engineer. + Now admins can: - delete members' messages. - disable members ("observer" role) - Most már az adminok is: + Most már az adminisztrátorok is: - törölhetik a tagok üzeneteit. - letilthatnak tagokat („megfigyelő” szerepkör) No comment provided by engineer. @@ -4561,45 +5022,45 @@ Ez az ön hivatkozása a(z) %@ csoporthoz! Ok Rendben - No comment provided by engineer. + alert button Old database Régi adatbázis No comment provided by engineer. - - Old database archive - Régi adatbázis archívum - No comment provided by engineer. - One-time invitation link - Egyszer használatos meghívó hivatkozás + Egyszer használható meghívó-hivatkozás No comment provided by engineer. Onion hosts will be **required** for connection. Requires compatible VPN. - A kapcsolódáshoz Onion kiszolgálókra lesz szükség. -VPN engedélyezése szükséges. + Onion-kiszolgálók **szükségesek** a kapcsolódáshoz. +Kompatibilis VPN szükséges. No comment provided by engineer. Onion hosts will be used when available. Requires compatible VPN. - Onion kiszolgálók használata, ha azok rendelkezésre állnak. + Onion-kiszolgálók használata, ha azok rendelkezésre állnak. VPN engedélyezése szükséges. No comment provided by engineer. Onion hosts will not be used. - Onion kiszolgálók nem lesznek használva. + Onion-kiszolgálók nem lesznek használva. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. - Csak a klienseszközök tárolják a felhasználói profilokat, névjegyeket, csoportokat és a **2 rétegű végponttól-végpontig titkosítással** küldött üzeneteket. + + Only chat owners can change preferences. + Csak a csevegés tulajdonosai módosíthatják a beállításokat. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. + Csak az eszközök alkalmazásai tárolják a felhasználó-profilokat, névjegyeket, csoportokat és a **2 rétegű végpontok közötti titkosítással** küldött üzeneteket. No comment provided by engineer. @@ -4624,42 +5085,42 @@ VPN engedélyezése szükséges. Only you can add message reactions. - Csak ön adhat hozzá üzenetreakciókat. + Csak Ön adhat hozzá üzenetreakciókat. No comment provided by engineer. Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours) - Véglegesen csak ön törölhet üzeneteket (ismerőse csak törlésre jelölheti meg őket ). (24 óra) + Véglegesen csak Ön törölhet üzeneteket (ismerőse csak törlésre jelölheti meg őket ). (24 óra) No comment provided by engineer. Only you can make calls. - Csak ön tud hívásokat indítani. + Csak Ön tud hívásokat indítani. No comment provided by engineer. Only you can send disappearing messages. - Csak ön tud eltűnő üzeneteket küldeni. + Csak Ön tud eltűnő üzeneteket küldeni. No comment provided by engineer. Only you can send voice messages. - Csak ön tud hangüzeneteket küldeni. + Csak Ön tud hangüzeneteket küldeni. No comment provided by engineer. Only your contact can add message reactions. - Csak az ismerős tud üzeneteakciókat adni. + Csak az ismerőse tud üzenetreakciókat küldeni. No comment provided by engineer. Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours) - Csak az ismerőse tudja az üzeneteket véglegesen törölni (ön csak törlésre jelölheti meg azokat). (24 óra) + Csak az ismerőse tudja az üzeneteket véglegesen törölni (Ön csak törlésre jelölheti meg azokat). (24 óra) No comment provided by engineer. Only your contact can make calls. - Csak az ismerős tud hívást indítani. + Csak az ismerőse tud hívást indítani. No comment provided by engineer. @@ -4669,7 +5130,7 @@ VPN engedélyezése szükséges. Only your contact can send voice messages. - Csak az ismerős tud hangüzeneteket küldeni. + Csak az ismerőse tud hangüzeneteket küldeni. No comment provided by engineer. @@ -4682,6 +5143,11 @@ VPN engedélyezése szükséges. Beállítások megnyitása No comment provided by engineer. + + Open changes + Változások megnyitása + No comment provided by engineer. + Open chat Csevegés megnyitása @@ -4692,6 +5158,11 @@ VPN engedélyezése szükséges. Csevegés konzol megnyitása authentication reason + + Open conditions + Feltételek megnyitása + No comment provided by engineer. + Open group Csoport megnyitása @@ -4702,26 +5173,26 @@ VPN engedélyezése szükséges. Átköltöztetés megkezdése egy másik eszközre authentication reason - - Open server settings - Kiszolgáló beállításainak megnyitása - No comment provided by engineer. - - - Open user profiles - Felhasználói profilok megnyitása - authentication reason - - - Open-source protocol and code – anybody can run the servers. - Nyílt forráskódú protokoll és forráskód – bárki üzemeltethet kiszolgálókat. - No comment provided by engineer. - Opening app… Az alkalmazás megnyitása… No comment provided by engineer. + + Operator + Üzemeltető + No comment provided by engineer. + + + Operator server + Kiszolgáló üzemeltető + alert title + + + Or import archive file + Vagy archívumfájl importálása + No comment provided by engineer. + Or paste archive link Vagy az archívum hivatkozásának beillesztése @@ -4734,7 +5205,7 @@ VPN engedélyezése szükséges. Or securely share this file link - Vagy a fájl hivítkozásának biztonságos megosztása + Vagy ossza meg biztonságosan ezt a fájlhivatkozást No comment provided by engineer. @@ -4742,24 +5213,31 @@ VPN engedélyezése szükséges. Vagy mutassa meg ezt a kódot No comment provided by engineer. + + Or to share privately + Vagy a privát megosztáshoz + No comment provided by engineer. + Other További No comment provided by engineer. - - Other %@ servers - További %@ kiszolgálók - No comment provided by engineer. + + Other file errors: +%@ + Egyéb fájlhiba: +%@ + alert message PING count - PING számláló + PING-ek száma No comment provided by engineer. PING interval - PING időköze + Időtartam a PING-ek között No comment provided by engineer. @@ -4787,6 +5265,11 @@ VPN engedélyezése szükséges. A jelkód beállítva! No comment provided by engineer. + + Password + Jelszó + No comment provided by engineer. + Password to show Jelszó megjelenítése @@ -4794,7 +5277,7 @@ VPN engedélyezése szükséges. Past member %@ - Már nem tag - %@ + (Már nem tag) %@ past/unknown group member @@ -4814,21 +5297,16 @@ VPN engedélyezése szükséges. Paste the link you received - Fogadott hivatkozás beillesztése + Kapott hivatkozás beillesztése No comment provided by engineer. Pending - Függő + Függőben No comment provided by engineer. - - People can connect to you only via the links you share. - Az emberek csak az ön által megosztott hivatkozáson keresztül kapcsolódhatnak. - No comment provided by engineer. - - - Periodically + + Periodic Rendszeresen No comment provided by engineer. @@ -4854,34 +5332,34 @@ VPN engedélyezése szükséges. Please ask your contact to enable sending voice messages. - Ismerős felkérése, hogy engedélyezze a hangüzenetek küldését. + Kérje meg az ismerősét, hogy engedélyezze a hangüzenetek küldését. No comment provided by engineer. Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection. Please share any other issues with the developers. - Ellenőrizze, hogy a mobil és az asztali számítógép ugyanahhoz a helyi hálózathoz csatlakozik-e, valamint az asztali számítógép tűzfalában engedélyezve van-e a kapcsolat. + Ellenőrizze, hogy a hordozható eszköz és a számítógép ugyanahhoz a helyi hálózathoz csatlakozik-e, valamint a számítógép tűzfalában engedélyezve van-e a kapcsolat. Minden további problémát osszon meg a fejlesztőkkel. No comment provided by engineer. Please check that you used the correct link or ask your contact to send you another one. - Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg ismerősét, hogy küldjön egy másikat. + Ellenőrizze, hogy a megfelelő hivatkozást használta-e, vagy kérje meg az ismerősét, hogy küldjön egy másikat. No comment provided by engineer. Please check your network connection with %@ and try again. - Ellenőrizze hálózati kapcsolatát a(z) %@ segítségével, és próbálja újra. + Ellenőrizze a hálózati kapcsolatát a következővel: %@, és próbálja újra. No comment provided by engineer. Please check yours and your contact preferences. - Ellenőrizze az ön és ismerőse beállításait. + Ellenőrizze a saját- és az ismerőse beállításait. No comment provided by engineer. Please confirm that network settings are correct for this device. - Ellenőrizze, hogy a hálózati beállítások megfelelőek-e ehhez az eszközhöz. + Ellenőrizze, hogy a hálózati beállítások megfelelők-e ehhez az eszközhöz. No comment provided by engineer. @@ -4893,12 +5371,12 @@ Hiba: %@ Please contact group admin. - Lépjen kapcsolatba a csoport adminnal. + Lépjen kapcsolatba a csoport adminisztrátorával. No comment provided by engineer. Please enter correct current passphrase. - Adja meg a helyes aktuális jelmondatát. + Adja meg a helyes, jelenlegi jelmondatát. No comment provided by engineer. @@ -4918,7 +5396,7 @@ Hiba: %@ Please restart the app and migrate the database to enable push notifications. - Indítsa újra az alkalmazást az adatbázis-átköltöztetéséhez szükséges push értesítések engedélyezéséhez. + Indítsa újra az alkalmazást az adatbázis-átköltöztetéséhez szükséges push-értesítések engedélyezéséhez. No comment provided by engineer. @@ -4936,6 +5414,11 @@ Hiba: %@ Lengyel kezelőfelület No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Lehetséges, hogy a kiszolgáló címében szereplő tanúsítvány-ujjlenyomat helytelen @@ -4946,16 +5429,16 @@ Hiba: %@ Az utolsó üzenet tervezetének megőrzése a mellékletekkel együtt. No comment provided by engineer. - - Preset server - Előre beállított kiszolgáló - No comment provided by engineer. - Preset server address Előre beállított kiszolgáló címe No comment provided by engineer. + + Preset servers + Előre beállított kiszolgálók + No comment provided by engineer. + Preview Előnézet @@ -4971,6 +5454,11 @@ Hiba: %@ Adatvédelem és biztonság No comment provided by engineer. + + Privacy for your customers. + Az Ön ügyfeleinek adatvédelme. + No comment provided by engineer. + Privacy redefined Adatvédelem újraértelmezve @@ -4978,17 +5466,17 @@ Hiba: %@ Private filenames - Privát fájl nevek + Privát fájlnevek No comment provided by engineer. Private message routing - Privát üzenet útválasztás + Privát üzenet-útválasztás No comment provided by engineer. Private message routing 🚀 - Privát üzenet útválasztás 🚀 + Privát üzenet-útválasztás 🚀 No comment provided by engineer. @@ -5003,7 +5491,7 @@ Hiba: %@ Private routing error - Privát útválasztási hiba + Privát útválasztáshiba No comment provided by engineer. @@ -5021,16 +5509,6 @@ Hiba: %@ Profilképek No comment provided by engineer. - - Profile name - Profilnév - No comment provided by engineer. - - - Profile name: - Profil neve: - No comment provided by engineer. - Profile password Profiljelszó @@ -5044,7 +5522,7 @@ Hiba: %@ Profile update will be sent to your contacts. A profilfrissítés elküldésre került az ismerősök számára. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5068,7 +5546,7 @@ Hiba: %@ Prohibit sending SimpleX links. - A SimpleX hivatkozások küldése le van tiltva. + A SimpleX-hivatkozások küldése le van tiltva. No comment provided by engineer. @@ -5083,7 +5561,7 @@ Hiba: %@ Prohibit sending files and media. - Fájlok- és a médiatartalom küldés letiltása. + Fájlok- és a médiatartalmak küldésének letiltása. No comment provided by engineer. @@ -5093,7 +5571,7 @@ Hiba: %@ Protect IP address - IP-cím védelem + IP-cím védelme No comment provided by engineer. @@ -5104,23 +5582,23 @@ Hiba: %@ Protect your IP address from the messaging relays chosen by your contacts. Enable in *Network & servers* settings. - Védje IP-címét az ismerősei által kiválasztott üzenetküldő átjátszókkal szemben. -Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. + Védje IP-címét az ismerősei által kiválasztott üzenet-közvetítő-kiszolgálókkal szemben. +Engedélyezze a „Beállítások -> Hálózat és kiszolgálók” menüben. No comment provided by engineer. Protect your chat profiles with a password! - Csevegési profiljok védelme jelszóval! + Védje meg a csevegési profiljait egy jelszóval! No comment provided by engineer. Protocol timeout - Protokoll időtúllépés + Protokoll időtúllépése No comment provided by engineer. Protocol timeout per KB - Protokoll időkorlát KB-onként + Protokoll időtúllépése KB-onként No comment provided by engineer. @@ -5133,14 +5611,19 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Proxyzott kiszolgálók No comment provided by engineer. + + Proxy requires password + A proxy jelszót igényel + No comment provided by engineer. + Push notifications - Push értesítések + Push-értesítések No comment provided by engineer. Push server - Push kiszolgáló + Push-kiszolgáló No comment provided by engineer. @@ -5165,7 +5648,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Read - Olvasd el + Olvasott swipe action @@ -5173,26 +5656,21 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Tudjon meg többet No comment provided by engineer. - - Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address). - További információ a [Használati útmutatóban](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). További információ a [Használati útmutatóban](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + További információ a [Használati útmutatóban](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + No comment provided by engineer. + Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends). További információ a [Használati útmutatóban](https://simplex.chat/docs/guide/readme.html#connect-to-friends). No comment provided by engineer. - - Read more in our GitHub repository. - További információ a GitHub tárolónkban. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). További információ a [GitHub tárolóban](https://github.com/simplex-chat/simplex-chat#readme). @@ -5200,7 +5678,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Receipts are disabled - Üzenet kézbesítési jelentés letiltva + A kézbesítési jelentések le vannak tiltva No comment provided by engineer. @@ -5220,12 +5698,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Received file event - Fogadott fájl esemény + Fogadott fájlesemény notification Received message - Fogadott üzenet + Fogadott üzenetbuborék színe message info title @@ -5235,12 +5713,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Received reply - Fogadott válasz + Fogadott válaszüzenet-buborék színe No comment provided by engineer. Received total - Összes fogadott + Összes fogadott üzenet No comment provided by engineer. @@ -5250,7 +5728,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Receiving file will be stopped. - A fájl fogadása leállt. + A fájl fogadása le fog állni. No comment provided by engineer. @@ -5270,32 +5748,32 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Recipients see updates as you type them. - A címzettek a beírás közben látják a frissítéseket. + A címzettek a beírás közben látják a szövegváltozásokat. No comment provided by engineer. Reconnect - Újrakapcsolás + Újrakapcsolódás No comment provided by engineer. Reconnect all connected servers to force message delivery. It uses additional traffic. - Újrakapcsolódás az összes kiszolgálóhoz az üzenetek kézbesítésének kikényszerítéséhez. Ez további forgalmat használ. + Az összes kiszolgálóhoz való újrakapcsolódás az üzenetkézbesítési jelentések kikényszerítéséhez. Ez további adatforgalmat használ. No comment provided by engineer. Reconnect all servers - Újrakapcsolódás minden kiszolgálóhoz + Újrakapcsolódás az összes kiszolgálóhoz No comment provided by engineer. Reconnect all servers? - Újrakapcsolódás minden kiszolgálóhoz? + Újrakapcsolódás az összes kiszolgálóhoz? No comment provided by engineer. Reconnect server to force message delivery. It uses additional traffic. - A kiszolgálóhoz való újrakapcsolódás az üzenet kézbesítésének kikényszerítéséhez. Ez további adatforgalmat használ. + A kiszolgálóhoz való újrakapcsolódás az üzenetkézbesítési jelentések kikényszerítéséhez. Ez további adatforgalmat használ. No comment provided by engineer. @@ -5320,7 +5798,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Reduced battery usage - Csökkentett akkumulátorhasználat + Csökkentett akkumulátor-használat No comment provided by engineer. @@ -5336,17 +5814,17 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Reject contact request - Kapcsolatfelvételi kérelem elutasítása + Kapcsolatkérés elutasítása No comment provided by engineer. Relay server is only used if necessary. Another party can observe your IP address. - Az átjátszó kiszolgáló csak szükség esetén kerül használatra. Egy másik fél megfigyelheti az IP-címet. + A közvetítő-kiszolgáló csak szükség esetén kerül használatra. Egy másik fél megfigyelheti az IP-címet. No comment provided by engineer. Relay server protects your IP address, but it can observe the duration of the call. - Az átjátszó kiszolgáló megvédi az IP-címet, de megfigyelheti a hívás időtartamát. + A közvetítő-kiszolgáló megvédi az IP-címet, de megfigyelheti a hívás időtartamát. No comment provided by engineer. @@ -5354,6 +5832,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Eltávolítás No comment provided by engineer. + + Remove archive? + Archívum eltávolítása? + No comment provided by engineer. + Remove image Kép eltávolítása @@ -5391,7 +5874,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Repeat connection request? - Kapcsolódási kérés megismétlése? + Kapcsolatkérés megismétlése? No comment provided by engineer. @@ -5406,7 +5889,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Repeat join request? - Csatlakozási kérés megismétlése? + Csatlakozáskérés megismétlése? No comment provided by engineer. @@ -5426,7 +5909,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Reset - Alaphelyzetbe állítás + Visszaállítás No comment provided by engineer. @@ -5436,17 +5919,17 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Reset all statistics - Minden statisztika visszaállítása + Az összes statisztika visszaállítása No comment provided by engineer. Reset all statistics? - Minden statisztika visszaállítása? + Az összes statisztika visszaállítása? No comment provided by engineer. Reset colors - Színek alaphelyzetbe állítása + Színek visszaállítása No comment provided by engineer. @@ -5456,7 +5939,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Reset to defaults - Alaphelyzetbe állítás + Visszaállítás alapértelmezettre No comment provided by engineer. @@ -5504,6 +5987,16 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Felfedés chat item action + + Review conditions + Feltételek felülvizsgálata + No comment provided by engineer. + + + Review later + Felülvizsgálat később + No comment provided by engineer. + Revoke Visszavonás @@ -5534,6 +6027,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. SMP-kiszolgáló No comment provided by engineer. + + SOCKS proxy + SOCKS proxy + No comment provided by engineer. + Safely receive files Fájlok biztonságos fogadása @@ -5547,17 +6045,18 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Save Mentés - chat item action + alert button + chat item action Save (and notify contacts) - Mentés (és az ismerősök értesítése) - No comment provided by engineer. + Mentés és az ismerősök értesítése + alert button Save and notify contact - Mentés és ismerős értesítése - No comment provided by engineer. + Mentés és az ismerős értesítése + alert button Save and notify group members @@ -5571,27 +6070,17 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Save and update group profile - Mentés és csoportprofil frissítése - No comment provided by engineer. - - - Save archive - Archívum mentése - No comment provided by engineer. - - - Save auto-accept settings - Automatikus elfogadási beállítások mentése + Mentés és a csoportprofil frissítése No comment provided by engineer. Save group profile - Csoportprofil elmentése + Csoportprofil mentése No comment provided by engineer. Save passphrase and open chat - Jelmondat elmentése és csevegés megnyitása + Jelmondat mentése és a csevegés megnyitása No comment provided by engineer. @@ -5602,11 +6091,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Save preferences? Beállítások mentése? - No comment provided by engineer. + alert title Save profile password - Felhasználói fiók jelszavának mentése + Profiljelszó mentése No comment provided by engineer. @@ -5617,18 +6106,18 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Save servers? Kiszolgálók mentése? - No comment provided by engineer. - - - Save settings? - Beállítások mentése? - No comment provided by engineer. + alert title Save welcome message? - Üdvözlőszöveg mentése? + Üdvözlőüzenet mentése? No comment provided by engineer. + + Save your profile? + Profil mentése? + alert title + Saved Mentett @@ -5636,12 +6125,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Saved WebRTC ICE servers will be removed - A mentett WebRTC ICE kiszolgálók eltávolításra kerülnek + A mentett WebRTC ICE-kiszolgálók eltávolításra kerülnek No comment provided by engineer. Saved from - Mentve innen: + Elmentve innen: No comment provided by engineer. @@ -5649,6 +6138,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Mentett üzenet message info title + + Saving %lld messages + %lld üzenet mentése + No comment provided by engineer. + Scale Méretezés @@ -5676,7 +6170,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Scan security code from your contact's app. - Biztonsági kód beolvasása ismerős általi alkalmazásból. + Biztonsági kód beolvasása az ismerősének alkalmazásából. No comment provided by engineer. @@ -5691,12 +6185,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Search bar accepts invitation links. - A keresősáv elfogadja a meghívó hivatkozásokat. + A keresősáv elfogadja a meghívó-hivatkozásokat. No comment provided by engineer. Search or paste SimpleX link - Keresés, vagy SimpleX hivatkozás beillesztése + Keresés vagy SimpleX-hivatkozás beillesztése No comment provided by engineer. @@ -5706,7 +6200,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Secure queue - Biztonságos várólista + Biztonságos sorbaállítás server test step @@ -5726,9 +6220,14 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Select - Választás + Kiválasztás chat item action + + Select chat profile + Csevegési profil kiválasztása + No comment provided by engineer. + Selected %lld %lld kiválasztva @@ -5806,12 +6305,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Send messages directly when IP address is protected and your or destination server does not support private routing. - Közvetlen üzenetküldés, ha az IP-cím védett és az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Közvetlen üzenetküldés, ha az IP-cím védett és az Ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. No comment provided by engineer. Send messages directly when your or destination server does not support private routing. - Közvetlen üzenetküldés, ha az ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. + Közvetlen üzenetküldés, ha az Ön kiszolgálója vagy a célkiszolgáló nem támogatja a privát útválasztást. No comment provided by engineer. @@ -5819,11 +6318,6 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Értesítések küldése No comment provided by engineer. - - Send notifications: - Értesítések küldése: - No comment provided by engineer. - Send questions and ideas Ötletek és kérdések beküldése @@ -5831,7 +6325,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Send receipts - Üzenet kézbesítési jelentések + Kézbesítési jelentések küldése No comment provided by engineer. @@ -5847,46 +6341,46 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Sender cancelled file transfer. A fájl küldője visszavonta az átvitelt. - No comment provided by engineer. + alert message Sender may have deleted the connection request. - A küldő törölhette a kapcsolódási kérelmet. + A küldő törölhette a kapcsolatkérést. No comment provided by engineer. Sending delivery receipts will be enabled for all contacts in all visible chat profiles. - A kézbesítési jelentések küldése engedélyezésre kerül az összes látható csevegési profilban lévő minden ismerős számára. + A kézbesítési jelentések küldése engedélyezésre kerül az összes látható csevegési profilban lévő összes ismerőse számára. No comment provided by engineer. Sending delivery receipts will be enabled for all contacts. - A kézbesítési jelentés küldése minden ismerős számára engedélyezésre kerül. + A kézbesítési jelentés küldése az összes ismerőse számára engedélyezésre kerül. No comment provided by engineer. Sending file will be stopped. - A fájl küldése leállt. + A fájl küldése le fog állni. No comment provided by engineer. Sending receipts is disabled for %lld contacts - A kézbesítési jelentések küldése le van tiltva %lld ismerősnél + A kézbesítési jelentések le vannak tiltva %lld ismerősnél No comment provided by engineer. Sending receipts is disabled for %lld groups - A kézbesítési jelentések küldése le van tiltva %lld csoportban + A kézbesítési jelentések le vannak tiltva %lld csoportban No comment provided by engineer. Sending receipts is enabled for %lld contacts - A kézbesítési jelentések küldése engedélyezve van %lld ismerős számára + A kézbesítési jelentések engedélyezve vannak %lld ismerősnél No comment provided by engineer. Sending receipts is enabled for %lld groups - A kézbesítési jelentések küldése engedélyezve van %lld csoportban + A kézbesítési jelentések engedélyezve vannak %lld csoportban No comment provided by engineer. @@ -5911,12 +6405,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Sent file event - Elküldött fájl esemény + Elküldött fájlesemény notification Sent message - Elküldött üzenet + Üzenetbuborék színe message info title @@ -5931,12 +6425,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Sent reply - Elküldött válasz + Válaszüzenet-buborék színe No comment provided by engineer. Sent total - Összes elküldött + Összes elküldött üzenet No comment provided by engineer. @@ -5944,6 +6438,16 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Proxyn keresztül küldve No comment provided by engineer. + + Server + Kiszolgáló + No comment provided by engineer. + + + Server added to operator %@. + Kiszolgáló hozzáadva a következő üzemeltetőhöz: %@. + alert message + Server address Kiszolgáló címe @@ -5959,9 +6463,24 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. A kiszolgáló címe nem kompatibilis a hálózati beállításokkal: %@. No comment provided by engineer. + + Server operator changed. + A kiszolgáló üzemeltetője megváltozott. + alert title + + + Server operators + Kiszolgáló-üzemeltetők + No comment provided by engineer. + + + Server protocol changed. + A kiszolgáló-protokoll megváltozott. + alert title + Server requires authorization to create queues, check password - A kiszolgálónak engedélyre van szüksége a várólisták létrehozásához, ellenőrizze jelszavát + A kiszolgálónak engedélyre van szüksége a sorbaállítás létrehozásához, ellenőrizze jelszavát server test error @@ -5971,7 +6490,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Server test failed! - Sikertelen kiszolgáló-teszt! + Sikertelen kiszolgáló teszt! No comment provided by engineer. @@ -5996,12 +6515,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Servers info - információk a kiszolgálókról + Információk a kiszolgálókról No comment provided by engineer. Servers statistics will be reset - this cannot be undone! - A kiszolgálók statisztikái visszaállnak - ez nem vonható vissza! + A kiszolgálók statisztikái visszaállnak - ez a művelet nem vonható vissza! No comment provided by engineer. @@ -6064,6 +6583,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Beállítások No comment provided by engineer. + + Settings were changed. + A beállítások megváltoztak. + alert message + Shape profile images Profilkép alakzat @@ -6072,11 +6596,22 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Share Megosztás - chat item action + alert action + chat item action Share 1-time link - Egyszer használatos hivatkozás megosztása + Egyszer használható hivatkozás megosztása + No comment provided by engineer. + + + Share 1-time link with a friend + Egyszer használható meghívó-hivatkozás megosztása egy baráttal + No comment provided by engineer. + + + Share SimpleX address on social media. + SimpleX-cím megosztása a közösségi médiában. No comment provided by engineer. @@ -6084,10 +6619,15 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Cím megosztása No comment provided by engineer. + + Share address publicly + Cím nyilvános megosztása + No comment provided by engineer. + Share address with contacts? Megosztja a címet az ismerőseivel? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,9 +6639,14 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Hivatkozás megosztása No comment provided by engineer. + + Share profile + Profil megosztása + No comment provided by engineer. + Share this 1-time invite link - Egyszer használatos meghívó hivatkozás megosztása + Egyszer használható meghívó-hivatkozás megosztása No comment provided by engineer. @@ -6131,12 +6676,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Show last messages - Utolsó üzenetek megjelenítése + Szobák utolsó üzeneteinek megjelenítése a listanézetben No comment provided by engineer. Show message status - Üzenet állapot megjelenítése + Üzenetállapot megjelenítése No comment provided by engineer. @@ -6146,7 +6691,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Show preview - Előnézet megjelenítése + Értesítés előnézete No comment provided by engineer. @@ -6166,7 +6711,12 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. SimpleX Address - SimpleX cím + SimpleX-cím + No comment provided by engineer. + + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + A SimpleX Chat és a Flux megállapodást kötött arról, hogy a Flux által üzemeltetett kiszolgálókat beépítik az alkalmazásba. No comment provided by engineer. @@ -6176,7 +6726,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. SimpleX Lock - SimpleX zár + SimpleX-zár No comment provided by engineer. @@ -6186,17 +6736,27 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. SimpleX Lock not enabled! - A SimpleX zár nincs bekapcsolva! + A SimpleX-zár nincs bekapcsolva! No comment provided by engineer. SimpleX Lock turned on - SimpleX zár bekapcsolva + SimpleX-zár bekapcsolva No comment provided by engineer. SimpleX address - SimpleX cím + SimpleX-cím + No comment provided by engineer. + + + SimpleX address and 1-time links are safe to share via any messenger. + A SimpleX-cím és az egyszer használható meghívó-hivatkozás biztonságosan megosztható bármilyen üzenetküldőn keresztül. + No comment provided by engineer. + + + SimpleX address or 1-time link? + SimpleX-cím vagy egyszer használható meghívó-hivatkozás? No comment provided by engineer. @@ -6211,32 +6771,37 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. SimpleX group link - SimpleX csoport hivatkozás + SimpleX-csoporthivatkozás simplex link type SimpleX links - SimpleX hivatkozások + SimpleX-hivatkozások chat feature - - SimpleX links are prohibited in this group. - A SimpleX hivatkozások küldése le van tiltva ebben a csoportban. + + SimpleX links are prohibited. + A SimpleX-hivatkozások küldése le van tiltva ebben a csoportban. No comment provided by engineer. SimpleX links not allowed - A SimpleX hivatkozások küldése le van tiltva + A SimpleX-hivatkozások küldése le van tiltva No comment provided by engineer. SimpleX one-time invitation - SimpleX egyszer használatos meghívó + Egyszer használható SimpleX-meghívó-hivatkozás simplex link type + + SimpleX protocols reviewed by Trail of Bits. + A SimpleX Chat biztonsága a Trail of Bits által lett felülvizsgálva. + No comment provided by engineer. + Simplified incognito mode - Egyszerűsített inkognító mód + Egyszerűsített inkognitómód No comment provided by engineer. @@ -6264,6 +6829,11 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Enyhe blur media + + Some app settings were not migrated. + Egyes alkalmazásbeállítások nem lettek átköltöztetve. + No comment provided by engineer. + Some file(s) were not exported: Néhány fájl nem került exportálásra: @@ -6271,14 +6841,21 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Some non-fatal errors occurred during import - you may see Chat console for more details. - Néhány nem végzetes hiba történt az importálás során – további részletekért a csevegési konzolban olvashat. + Néhány nem végzetes hiba történt az importáláskor – további részleteket a csevegési konzolban olvashat. No comment provided by engineer. Some non-fatal errors occurred during import: - Néhány nem végzetes hiba történt az importálás során: + Néhány nem végzetes hiba történt az importáláskor: No comment provided by engineer. + + Some servers failed the test: +%@ + Néhány kiszolgáló megbukott a teszten: +%@ + alert message + Somebody Valaki @@ -6329,14 +6906,9 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Csevegési szolgáltatás megállítása No comment provided by engineer. - - Stop chat to enable database actions - Csevegés megállítása az adatbázis-műveletek engedélyezéséhez - 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. - A csevegés megállítása a csevegő adatbázis exportálásához, importálásához vagy törléséhez. A csevegés megállítása alatt nem tud üzeneteket fogadni és küldeni. + A csevegés megállítása a csevegési adatbázis exportálásához, importálásához vagy törléséhez. A csevegés megállításakor nem tud üzeneteket fogadni és küldeni. No comment provided by engineer. @@ -6351,23 +6923,23 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Stop receiving file? - Fájl fogadás megállítása? + Fájlfogadás megállítása? No comment provided by engineer. Stop sending file? - Fájl küldés megállítása? + Fájlküldés megállítása? No comment provided by engineer. Stop sharing Megosztás megállítása - No comment provided by engineer. + alert action Stop sharing address? Címmegosztás megállítása? - No comment provided by engineer. + alert title Stopping chat @@ -6396,12 +6968,22 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Subscriptions ignored - Elutasított feliratkozások + Mellőzött feliratkozások No comment provided by engineer. Support SimpleX Chat - Támogassa a SimpleX Chatet + SimpleX Chat támogatása + No comment provided by engineer. + + + Switch audio and video during the call. + Hang/Videó váltása hívás közben. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Csevegési profilváltás az egyszer használható meghívó-hivatkozásokhoz. No comment provided by engineer. @@ -6421,7 +7003,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. TCP connection timeout - TCP kapcsolat időtúllépés + TCP kapcsolat időtúllépése No comment provided by engineer. @@ -6439,11 +7021,21 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Farok + No comment provided by engineer. + Take picture Kép készítése No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Koppintson a SimpleX-cím létrehozása menüpontra a későbbi létrehozáshoz. + No comment provided by engineer. + Tap button Koppintson a @@ -6451,7 +7043,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Tap to Connect - Koppintson a kapcsolódáshoz + Koppintson ide a kapcsolódáshoz No comment provided by engineer. @@ -6461,27 +7053,27 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Tap to join - Koppintson a csatlakozáshoz + Koppintson ide a csatlakozáshoz No comment provided by engineer. Tap to join incognito - Koppintson az inkognitóban való csatlakozáshoz + Koppintson ide az inkognitóban való csatlakozáshoz No comment provided by engineer. Tap to paste link - Koppintson a hivatkozás beillesztéséhez + Koppintson ide a hivatkozás beillesztéséhez No comment provided by engineer. Tap to scan - Koppintson a beolvasáshoz + Koppintson ide a QR-kód beolvasáshoz No comment provided by engineer. Temporary file error - Ideiglenes fájlhiba + Ideiglenesfájl-hiba No comment provided by engineer. @@ -6502,7 +7094,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Tests failed! Sikertelen tesztek! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6516,12 +7108,7 @@ Engedélyezze a Beállítások / Hálózat és kiszolgálók menüben. Thanks to the users – contribute via Weblate! - Köszönet a felhasználóknak - hozzájárulás a Weblaten! - No comment provided by engineer. - - - The 1st platform without any user identifiers – private by design. - Az első csevegési rendszer bármiféle felhasználó azonosító nélkül - privátra lett tervezre. + Köszönet a felhasználóknak - hozzájárulás a Weblate-en! No comment provided by engineer. @@ -6533,7 +7120,12 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. The app can notify you when you receive messages or contact requests - please open settings to enable. - Az alkalmazás értesíteni fogja, amikor üzeneteket vagy kapcsolatfelvételi kéréseket kap – beállítások megnyitása az engedélyezéshez. + Az alkalmazás értesíteni fogja, amikor üzeneteket vagy kapcsolatkéréseket kap – beállítások megnyitása az engedélyezéshez. + No comment provided by engineer. + + + The app protects your privacy by using different operators in each conversation. + Az alkalmazás úgy védi az adatait, hogy minden egyes beszélgetésben más-más üzemeltetőket használ. No comment provided by engineer. @@ -6548,12 +7140,17 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. The code you scanned is not a SimpleX link QR code. - A beolvasott kód nem egy SimpleX hivatkozás QR-kód. + A beolvasott QR-kód nem egy SimpleX-QR-kód-hivatkozás. + No comment provided by engineer. + + + The connection reached the limit of undelivered messages, your contact may be offline. + A kapcsolat elérte a kézbesítetlen üzenetek számának határát, az Ön ismerőse lehet, hogy offline állapotban van. No comment provided by engineer. The connection you accepted will be cancelled! - Az ön által elfogadott kapcsolat vissza lesz vonva! + Az Ön által elfogadott kérelem vissza lesz vonva! No comment provided by engineer. @@ -6563,7 +7160,7 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. The created archive is available via app Settings / Database / Old database archive. - A létrehozott archívum a Beállítások / Adatbázis / Régi adatbázis-archívum menüben érhető el. + A létrehozott archívum a „Beállítások / Adatbázis / Régi adatbázis-archívum” menüben érhető el. No comment provided by engineer. @@ -6571,44 +7168,59 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. A titkosítás működik, és új titkosítási egyezményre nincs szükség. Ez kapcsolati hibákat eredményezhet! No comment provided by engineer. + + The future of messaging + A privát üzenetküldés következő generációja + No comment provided by engineer. + The hash of the previous message is different. - Az előző üzenet hash-e más. + Az előző üzenet hasító értéke különbözik. No comment provided by engineer. The message will be deleted for all members. - Az üzenet minden tag számára törlésre kerül. + Az üzenet az összes tag számára törlésre kerül. No comment provided by engineer. The message will be marked as moderated for all members. - Az üzenet minden tag számára moderáltként lesz megjelölve. + Az üzenet az összes tag számára moderáltként lesz megjelölve. No comment provided by engineer. The messages will be deleted for all members. - Az üzenetek minden tag számára törlésre kerülnek. + Az üzenetek az összes tag számára törlésre kerülnek. No comment provided by engineer. The messages will be marked as moderated for all members. - Az üzenetek moderáltként lesznek megjelölve minden tag számára. - No comment provided by engineer. - - - The next generation of private messaging - A privát üzenetküldés következő generációja + Az üzenetek az összes tag számára moderáltként lesznek megjelölve. No comment provided by engineer. The old database was not removed during the migration, it can be deleted. - A régi adatbázis nem került eltávolításra az átköltöztetés során, így törölhető. + A régi adatbázis nem került eltávolításra az átköltöztetéskor, így törölhető. No comment provided by engineer. The profile is only shared with your contacts. - Profilja csak az ismerőseivel kerül megosztásra. + A profilja csak az ismerőseivel kerül megosztásra. + No comment provided by engineer. + + + The same conditions will apply to operator **%@**. + Ugyanezek a feltételek lesznek elfogadva a következő üzemeltetőre is: **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Ugyanezek a feltételek lesznek elfogadva a következő üzemeltető(k)re is: **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + A második előre beállított üzemeltető az alkalmazásban! No comment provided by engineer. @@ -6623,12 +7235,22 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. The servers for new connections of your current chat profile **%@**. - Jelenlegi profil új ismerőseinek kiszolgálói **%@**. + A jelenlegi csevegési profilhoz tartozó új kapcsolatok kiszolgálói **%@**. + No comment provided by engineer. + + + The servers for new files of your current chat profile **%@**. + Az Ön jelenlegi **%@** nevű csevegőprofiljához tartozó új fájlok kiszolgálói. No comment provided by engineer. The text you pasted is not a SimpleX link. - A beillesztett szöveg nem egy SimpleX hivatkozás. + A beillesztett szöveg nem egy SimpleX-hivatkozás. + No comment provided by engineer. + + + The uploaded database archive will be permanently removed from the servers. + A feltöltött adatbázis-archívum véglegesen eltávolításra kerül a kiszolgálókról. No comment provided by engineer. @@ -6636,19 +7258,24 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. Témák No comment provided by engineer. + + These conditions will also apply for: **%@**. + Ezek a feltételek lesznek elfogadva a következő számára is: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. - Ezek a beállítások a jelenlegi **%@** profiljára vonatkoznak. + Ezek a beállítások csak a jelenlegi (**%@**) profiljára vonatkoznak. No comment provided by engineer. They can be overridden in contact and group settings. - Ezek felülbírálhatóak az ismerős- és csoportbeállításokban. + Ezek felülbírálhatók az ismerős- és csoportbeállításokban. 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. - 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ú képek viszont megmaradnak. + Ez a művelet nem vonható vissza - az összes fogadott és küldött fájl a médiatartalmakkal együtt törlésre kerül. Az alacsony felbontású képek viszont megmaradnak. No comment provided by engineer. @@ -6678,7 +7305,7 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. This display name is invalid. Please choose another name. - Ez a megjelenített felhasználónév érvénytelen. Válasszon egy másik nevet. + Ez a megjelenített név érvénytelen. Válasszon egy másik nevet. No comment provided by engineer. @@ -6693,22 +7320,22 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. This is your own SimpleX address! - Ez az ön SimpleX címe! + Ez az Ön SimpleX-címe! No comment provided by engineer. This is your own one-time link! - Ez az egyszer használatos hivatkozása! + Ez az Ön egyszer használható meghívó-hivatkozása! No comment provided by engineer. This link was used with another mobile device, please create a new link on the desktop. - Ezt a hivatkozást egy másik mobilleszközön már használták, hozzon létre egy új hivatkozást az asztali számítógépén. + Ezt a hivatkozást egy másik hordozható eszközön már használták, hozzon létre egy új hivatkozást a számítógépén. No comment provided by engineer. This setting applies to messages in your current chat profile **%@**. - Ez a beállítás a jelenlegi **%@** profiljában lévő üzenetekre érvényes. + Ez a beállítás csak a jelenlegi (**%@**) profiljában lévő üzenetekre vonatkozik. No comment provided by engineer. @@ -6736,28 +7363,48 @@ Ez valamilyen hiba, vagy sérült kapcsolat esetén fordulhat elő. Új kapcsolat létrehozásához 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. - Az adatvédelem érdekében, a más csevegési platformokon megszokott felhasználói azonosítók helyett, a SimpleX üzenetsorokhoz rendel azonosítókat, minden egyes ismerőshöz egy különbözőt. + + To protect against your link being replaced, you can compare contact security codes. + A hivatkozás cseréje elleni védelem érdekében összehasonlíthatja a biztonsági kódokat az ismerősével. No comment provided by engineer. To protect timezone, image/voice files use UTC. - Az időzóna védelme érdekében a kép-/hangfájlok UTC-t használnak. + Az időzóna védelmének érdekében a kép-/hangfájlok UTC-t használnak. No comment provided by engineer. To protect your IP address, private routing uses your SMP servers to deliver messages. - Az IP-cím védelmének érdekében a privát útválasztás az SMP kiszolgálókat használja az üzenetek kézbesítéséhez. + Az IP-cím védelmének érdekében a privát útválasztás az SMP-kiszolgálókat használja az üzenetek kézbesítéséhez. No comment provided by engineer. To protect your information, turn on SimpleX Lock. You will be prompted to complete authentication before this feature is enabled. - A biztonsága érdekében kapcsolja be a SimpleX zár funkciót. + A biztonsága érdekében kapcsolja be a SimpleX-zár funkciót. A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beállítására az eszközén. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Az adatvédelem érdekében (a más csevegési platformokon megszokott felhasználó-azonosítók helyett) a SimpleX csak az üzenetek sorbaállításához használ azonosítókat, az összes ismerőséhez különbözőt. + No comment provided by engineer. + + + To receive + A fogadáshoz + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + A beszéd rögzítéséhez adjon engedélyt a Mikrofon használatára. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + A videó rögzítéséhez adjon engedélyt a Kamera használatára. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Hangüzenet rögzítéséhez adjon engedélyt a mikrofon használathoz. @@ -6768,14 +7415,24 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Rejtett profilja megjelenítéséhez írja be a teljes jelszavát a keresőmezőbe a **Csevegési profilok** menüben. No comment provided by engineer. + + To send + A küldéshez + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. - Az azonnali push értesítések támogatásához a csevegési adatbázis migrálása szükséges. + Az azonnali push-értesítések támogatásához a csevegési adatbázis átköltöztetése szükséges. + No comment provided by engineer. + + + To use the servers of **%@**, accept conditions of use. + A(z) **%@** kiszolgálóinak használatához fogadja el a használati feltételeket. No comment provided by engineer. To verify end-to-end encryption with your contact compare (or scan) the code on your devices. - A végpontok közötti titkosítás ellenőrzéséhez hasonlítsa össze (vagy olvassa be a QR-kódot) az ismerőse eszközén lévő kóddal. + A végpontok közötti titkosítás hitelesítéséhez hasonlítsa össze (vagy olvassa be a QR-kódot) az ismerőse eszközén lévő kóddal. No comment provided by engineer. @@ -6785,7 +7442,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Toggle incognito when connecting. - Inkognitó mód kapcsolódáskor. + Inkognitómód használata kapcsolódáskor. No comment provided by engineer. @@ -6795,12 +7452,12 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Total - Összesen + Összes kapcsolat No comment provided by engineer. Transport isolation - Kapcsolat izolációs mód + Átvitel-izoláció módja No comment provided by engineer. @@ -6810,12 +7467,12 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Trying to connect to the server used to receive messages from this contact (error: %@). - Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál (hiba: %@). + Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál (hiba: %@). No comment provided by engineer. Trying to connect to the server used to receive messages from this contact. - Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál. + Kapcsolódási kísérlet ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál. No comment provided by engineer. @@ -6845,7 +7502,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Unblock for all - Letiltás feloldása mindenki számára + Letiltás feloldása az összes tag számára No comment provided by engineer. @@ -6855,7 +7512,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Unblock member for all? - Mindenki számára feloldja a tag letiltását? + Az összes tag számára feloldja a tag letiltását? No comment provided by engineer. @@ -6863,6 +7520,11 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Tag feloldása? No comment provided by engineer. + + Undelivered messages + Kézbesítetlen üzenetek + No comment provided by engineer. + Unexpected migration state Váratlan átköltöztetési állapot @@ -6870,7 +7532,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Unfav. - Nem kedvelt. + Kedvenc megszüntetése swipe action @@ -6911,7 +7573,7 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll Unknown servers! Ismeretlen kiszolgálók! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6921,8 +7583,8 @@ A funkció bekapcsolása előtt a rendszer felszólítja a képernyőzár beáll 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. - Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt, lehet hogy ez egy hiba – jelentse a problémát. -A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsolati hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e. + Hacsak az ismerőse nem törölte a kapcsolatot, vagy ez a hivatkozás már használatban volt egyszer, lehet hogy ez egy hiba – jelentse a problémát. +A kapcsolódáshoz kérje meg az ismerősét, hogy hozzon létre egy másik kapcsolattartási hivatkozást, és ellenőrizze, hogy a hálózati kapcsolat stabil-e. No comment provided by engineer. @@ -6947,7 +7609,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Unmute - Némítás feloldása + Némítás megszüntetése swipe action @@ -6967,7 +7629,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Update database passphrase - Adatbázis jelmondat megváltoztatása + Adatbázis-jelmondat megváltoztatása No comment provided by engineer. @@ -7020,14 +7682,24 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Archívum feltöltése No comment provided by engineer. + + Use %@ + %@ használata + No comment provided by engineer. + Use .onion hosts - Tor .onion kiszolgálók használata + Onion-kiszolgálók használata + No comment provided by engineer. + + + Use SOCKS proxy + SOCKS proxy használata No comment provided by engineer. Use SimpleX Chat servers? - SimpleX Chat kiszolgálók használata? + SimpleX Chat-kiszolgálók használata? No comment provided by engineer. @@ -7040,6 +7712,16 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Jelenlegi profil használata No comment provided by engineer. + + Use for files + Használat a fájlokhoz + No comment provided by engineer. + + + Use for messages + Használat az üzenetekhez + No comment provided by engineer. + Use for new connections Alkalmazás új kapcsolatokhoz @@ -7047,17 +7729,17 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Use from desktop - Használat számítógépről + Társítás számítógéppel No comment provided by engineer. Use iOS call interface - Az iOS hívófelület használata + Az iOS hívási felületét használata No comment provided by engineer. Use new incognito profile - Az új inkognító profil használata + Új inkognitóprofil használata No comment provided by engineer. @@ -7067,7 +7749,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Use private routing with unknown servers when IP address is not protected. - Privát útválasztás használata ismeretlen kiszolgálókkal, ha az IP-cím nem védett. + Használjon privát útválasztást ismeretlen kiszolgálókkal, ha az IP-cím nem védett. No comment provided by engineer. @@ -7080,6 +7762,11 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Kiszolgáló használata No comment provided by engineer. + + Use servers + Kiszolgálók használata + No comment provided by engineer. + Use the app while in the call. Használja az alkalmazást hívás közben. @@ -7090,54 +7777,54 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Használja az alkalmazást egy kézzel. No comment provided by engineer. - - User profile - Felhasználói profil - No comment provided by engineer. - User selection Felhasználó kiválasztása No comment provided by engineer. + + Username + Felhasználónév + No comment provided by engineer. + Using SimpleX Chat servers. - SimpleX Chat kiszolgálók használatban. + SimpleX Chat-kiszolgálók használatban. No comment provided by engineer. Verify code with desktop - Kód ellenőrzése a számítógépen + Kód hitelesítése a számítógépen No comment provided by engineer. Verify connection - Kapcsolat ellenőrzése + Kapcsolat hitelesítése No comment provided by engineer. Verify connection security - Kapcsolat biztonságának ellenőrzése + Biztonságos kapcsolat hitelesítése No comment provided by engineer. Verify connections - Kapcsolatok ellenőrzése + Kapcsolatok hitelesítése No comment provided by engineer. Verify database passphrase - Adatbázis jelmondatának ellenőrzése + Az adatbázis jelmondatának hitelesítése No comment provided by engineer. Verify passphrase - Jelmondat ellenőrzése + Jelmondat hitelesítése No comment provided by engineer. Verify security code - Biztonsági kód ellenőrzése + Biztonsági kód hitelesítése No comment provided by engineer. @@ -7147,7 +7834,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Via secure quantum resistant protocol. - Biztonságos kvantum ellenálló protokoll által. + Biztonságos kvantumrezisztens-protokollon keresztül. No comment provided by engineer. @@ -7170,11 +7857,21 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Videók és fájlok 1Gb méretig No comment provided by engineer. + + View conditions + Feltételek megtekintése + No comment provided by engineer. + View security code Biztonsági kód megtekintése No comment provided by engineer. + + View updated conditions + Frissített feltételek megtekintése + No comment provided by engineer. + Visible history Látható előzmények @@ -7190,8 +7887,8 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol A hangüzenetek küldése le van tiltva ebben a csevegésben. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. A hangüzenetek küldése le van tiltva ebben a csoportban. No comment provided by engineer. @@ -7212,22 +7909,22 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Waiting for desktop... - Várakozás az asztali kliensre... + Várakozás a számítógép-alkalmazásra… No comment provided by engineer. Waiting for file - Fájlra várakozás + Várakozás a fájlra No comment provided by engineer. Waiting for image - Képre várakozás + Várakozás a képre No comment provided by engineer. Waiting for video - Videóra várakozás + Várakozás a videóra No comment provided by engineer. @@ -7252,7 +7949,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol WebRTC ICE servers - WebRTC ICE kiszolgálók + WebRTC ICE-kiszolgálók No comment provided by engineer. @@ -7262,17 +7959,17 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Welcome message - Üdvözlő üzenet + Üdvözlőüzenet No comment provided by engineer. Welcome message is too long - Az üdvözlő üzenet túl hosszú + Az üdvözlőüzenet túl hosszú No comment provided by engineer. What's new - Milyen újdonságok vannak + Újdonságok No comment provided by engineer. @@ -7285,9 +7982,9 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Amikor egy bejövő hang- vagy videóhívás érkezik. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Amikor az emberek kapcsolódást kérelmeznek, ön elfogadhatja vagy elutasíthatja azokat. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Amikor egynél több hálózati üzemeltető van engedélyezve, egyikük sem rendelkezik olyan metaadatokkal ahhoz, hogy felderítse, ki kommunikál kivel. No comment provided by engineer. @@ -7312,17 +8009,17 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol With encrypted files and media. - Titkosított fájlokkal és médiatartalommal. + Titkosított fájlokkal és médiatartalmakkal. No comment provided by engineer. With optional welcome message. - Opcionális üdvözlő üzenettel. + Nem kötelező üdvözlőüzenettel. No comment provided by engineer. With reduced battery usage. - Csökkentett akkumulátorhasználattal. + Csökkentett akkumulátor-használattal. No comment provided by engineer. @@ -7332,12 +8029,12 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - Tor vagy VPN nélkül az IP-címe látható lesz ezen XFTP átjátszók számára: %@. - No comment provided by engineer. + Tor vagy VPN nélkül az IP-címe látható lesz a következő XFTP-közvetítő-kiszolgálók számára: %@. + alert message Wrong database passphrase - Hibás adatbázis jelmondat + Hibás adatbázis-jelmondat No comment provided by engineer. @@ -7360,11 +8057,6 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol XFTP-kiszolgáló No comment provided by engineer. - - You - Ön - No comment provided by engineer. - You **must not** use the same database on two devices. **Nem szabad** ugyanazt az adatbázist használni egyszerre két eszközön. @@ -7377,7 +8069,7 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol You allow - Engedélyezte + Ön engedélyezi No comment provided by engineer. @@ -7387,7 +8079,12 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol You are already connected to %@. - Már kapcsolódva van hozzá: %@. + Ön már kapcsolódva van ehhez: %@. + No comment provided by engineer. + + + You are already connected with %@. + Ön már kapcsolódva van vele: %@. No comment provided by engineer. @@ -7397,17 +8094,17 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol You are already connecting via this one-time link! - A kapcsolódás már folyamatban van ezen az egyszer használatos hivatkozáson keresztül! + A kapcsolódás már folyamatban van ezen az egyszer használható meghívó-hivatkozáson keresztül! No comment provided by engineer. You are already in group %@. - Már a(z) %@ csoport tagja. + Ön már a(z) %@ nevű csoport tagja. No comment provided by engineer. You are already joining the group %@. - A csatlakozás már folyamatban van a(z) %@ csoporthoz. + A csatlakozás már folyamatban van a(z) %@ nevű csoporthoz. No comment provided by engineer. @@ -7424,12 +8121,12 @@ A kapcsolódáshoz kérje meg ismerősét, hogy hozzon létre egy másik kapcsol You are already joining the group! Repeat join request? Csatlakozás folyamatban! -Csatlakozási kérés megismétlése? +Csatlakozáskérés megismétlése? No comment provided by engineer. You are connected to the server used to receive messages from this contact. - Már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerőstől érkező üzenetek fogadására szolgál. + Ön már kapcsolódott ahhoz a kiszolgálóhoz, amely az adott ismerősétől érkező üzenetek fogadására szolgál. No comment provided by engineer. @@ -7444,7 +8141,7 @@ Csatlakozási kérés megismétlése? You can accept calls from lock screen, without device and app authentication. - Hívásokat fogadhat a lezárási képernyőről, eszköz- és alkalmazáshitelesítés nélkül. + Hívásokat fogadhat a lezárási képernyőről, eszköz- és alkalmazás-hitelesítés nélkül. No comment provided by engineer. @@ -7452,6 +8149,16 @@ Csatlakozási kérés megismétlése? Ezt a „Megjelenés” menüben módosíthatja. No comment provided by engineer. + + You can configure operators in Network & servers settings. + Az üzemeltetőket a „Hálózat és kiszolgálók” beállításaban konfigurálhatja. + No comment provided by engineer. + + + You can configure servers via settings. + A kiszolgálókat a „Hálózat és kiszolgálók” menüben konfigurálhatja. + No comment provided by engineer. + You can create it later Létrehozás később @@ -7459,12 +8166,12 @@ Csatlakozási kérés megismétlése? You can enable later via Settings - Később engedélyezheti a Beállításokban + Később engedélyezheti a „Beállításokban” No comment provided by engineer. You can enable them later via app Privacy & Security settings. - Később engedélyezheti őket az alkalmazás „Adatvédelem és biztonság” menüben. + Később engedélyezheti őket az alkalmazás „Adatvédelem és biztonság” menüjében. No comment provided by engineer. @@ -7474,12 +8181,12 @@ Csatlakozási kérés megismétlése? You can hide or mute a user profile - swipe it to the right. - Elrejtheti vagy lenémíthatja a felhasználó profiljait - csúsztassa jobbra a profilt. + Elrejtheti vagy lenémíthatja a felhasználó -profiljait - csúsztassa jobbra a profilt. No comment provided by engineer. You can make it visible to your SimpleX contacts via Settings. - Láthatóvá teheti SimpleX ismerősök számára a Beállításokban. + Láthatóvá teheti a SimpleXbeli ismerősei számára a „Beállításokban”. No comment provided by engineer. @@ -7492,9 +8199,14 @@ Csatlakozási kérés megismétlése? Az „Archivált ismerősökből” továbbra is küldhet üzeneteket neki: %@. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + Beállíthatja az ismerős nevét, hogy emlékezzen arra, hogy kivel osztotta meg a hivatkozást. + No comment provided by engineer. + You can set lock screen notification preview via settings. - A beállításokon keresztül beállíthatja a lezárási képernyő értesítési előnézetét. + A lezárási képernyő értesítési előnézetét az „Értesítések” menüben állíthatja be. No comment provided by engineer. @@ -7504,17 +8216,12 @@ Csatlakozási kérés megismétlése? You can share this address with your contacts to let them connect with **%@**. - Megoszthatja ezt a címet az ismerőseivel, hogy kapcsolatba léphessenek önnel a(z) **%@** nevű profilján keresztül. - No comment provided by engineer. - - - You can share your address as a link or QR code - anybody can connect to you. - Megoszthatja a címét egy hivatkozásként vagy QR-kódként – így bárki kapcsolódhat önhöz. + Megoszthatja ezt a címet az ismerőseivel, hogy kapcsolatba léphessenek Önnel a(z) **%@** nevű profilján keresztül. No comment provided by engineer. You can start chat via app Settings / Database or by restarting the app - A csevegést az alkalmazás Beállítások / Adatbázis menüben vagy az alkalmazás újraindításával indíthatja el + A csevegést az alkalmazás „Beállítások / Adatbázis” menüben vagy az alkalmazás újraindításával indíthatja el No comment provided by engineer. @@ -7524,7 +8231,7 @@ Csatlakozási kérés megismétlése? You can turn on SimpleX Lock via Settings. - A SimpleX zár az „Adatvédelem és biztonság” menüben kapcsolható be. + A SimpleX-zár az „Adatvédelem és biztonság” menüben kapcsolható be. No comment provided by engineer. @@ -7534,34 +8241,34 @@ Csatlakozási kérés megismétlése? You can view invitation link again in connection details. - A meghívó hivatkozást újra megtekintheti a kapcsolat részleteinél. - No comment provided by engineer. + A meghívó-hivatkozást újra megtekintheti a kapcsolat részleteinél. + alert message You can't send messages! Nem lehet üzeneteket küldeni! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Ön szabályozhatja, hogy mely kiszogál(ók)ón keresztül **kapja** az üzeneteket, az ismerősöket - az üzenetküldéshez használt kiszolgálókon. - No comment provided by engineer. - You could not be verified; please try again. - Nem lehetett ellenőrizni; próbálja meg újra. + Nem sikerült hitelesíteni; próbálja meg újra. + No comment provided by engineer. + + + You decide who can connect. + Ön dönti el, hogy kivel beszélget. No comment provided by engineer. You have already requested connection via this address! - Már kért egy kapcsolódási kérelmet ezen a címen keresztül! + Már küldött egy kapcsolatkérést ezen a címen keresztül! No comment provided by engineer. You have already requested connection! Repeat connection request? - Már kért egy kapcsolódási kérelmet! -Kapcsolódási kérés megismétlése? + Már küldött egy kapcsolódási kérelmet! +Kapcsolatkérés megismétlése? No comment provided by engineer. @@ -7596,7 +8303,7 @@ Kapcsolódási kérés megismétlése? 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. - A csevegési adatbázis legfrissebb verzióját CSAK egy eszközön kell használnia, ellenkező esetben előfordulhat, hogy az üzeneteket nem fogja megkapni valamennyi ismerőstől. + A csevegési adatbázis legfrissebb verzióját CSAK egy eszközön kell használnia, ellenkező esetben előfordulhat, hogy az üzeneteket nem fogja megkapni valamennyi ismerősétől. No comment provided by engineer. @@ -7606,17 +8313,17 @@ Kapcsolódási kérés megismétlése? You need to allow your contact to send voice messages to be able to send them. - Hangüzeneteket küldéséhez engedélyeznie kell azok küldését az ismerősök számára. + Engedélyeznie kell a hangüzenetek küldését az ismerőse számára, hogy hangüzeneteket küldhessenek egymásnak. No comment provided by engineer. You rejected group invitation - Csoport meghívó elutasítva + Csoportmeghívó elutasítva No comment provided by engineer. You sent group invitation - Csoport meghívó elküldve + Csoportmeghívó elküldve No comment provided by engineer. @@ -7626,17 +8333,17 @@ Kapcsolódási kérés megismétlése? You will be connected when group link host's device is online, please wait or check later! - Akkor lesz kapcsolódva, amikor a csoportos hivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később! + Akkor lesz kapcsolódva, amikor a csoporthivatkozás tulajdonosának eszköze online lesz, várjon, vagy ellenőrizze később! No comment provided by engineer. You will be connected when your connection request is accepted, please wait or check later! - Akkor lesz kapcsolódva, ha a kapcsolódási kérelme elfogadásra kerül, várjon, vagy ellenőrizze később! + Akkor lesz kapcsolódva, ha a kapcsolatkérése elfogadásra kerül, várjon, vagy ellenőrizze később! No comment provided by engineer. You will be connected when your contact's device is online, please wait or check later! - Akkor le kapcsolódva, amikor az ismerőse eszköze online lesz, várjon, vagy ellenőrizze később! + Akkor lesz kapcsolódva, amikor az ismerősének eszköze online lesz, várjon, vagy ellenőrizze később! No comment provided by engineer. @@ -7654,6 +8361,11 @@ Kapcsolódási kérés megismétlése? Továbbra is kap hívásokat és értesítéseket a némított profiloktól, ha azok aktívak. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + Ön nem fog több üzenetet kapni ebből a csevegésből, de a csevegés előzményei megmaradnak. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Ettől a csoporttól nem fog értesítéseket kapni. A csevegési előzmények megmaradnak. @@ -7666,37 +8378,27 @@ Kapcsolódási kérés megismétlése? 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 - Egy olyan ismerőst próbál meghívni, akivel inkognító profilt osztott meg abban a csoportban, amelyben saját fő profilja van használatban + Egy olyan ismerősét próbálja meghívni, akivel inkognitóprofilt osztott meg abban a csoportban, amelyben a saját fő profilja van használatban 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 - Inkognító profilt használ ehhez a csoporthoz - fő profilja megosztásának elkerülése érdekében meghívók küldése tiltott - No comment provided by engineer. - - - Your %@ servers - %@ nevű profiljához tartozó kiszolgálók + Inkognitóprofilt használ ehhez a csoporthoz - fő profilja megosztásának elkerülése érdekében a meghívók küldése le van tiltva No comment provided by engineer. Your ICE servers - ICE kiszolgálók + Saját ICE-kiszolgálók No comment provided by engineer. Your SMP servers - SMP kiszolgálók + Saját SMP-kiszolgálók No comment provided by engineer. Your SimpleX address - Az ön SimpleX címe - No comment provided by engineer. - - - Your XFTP servers - XFTP kiszolgálók + Profil SimpleX-címe No comment provided by engineer. @@ -7714,19 +8416,29 @@ Kapcsolódási kérés megismétlése? A csevegési adatbázis nincs titkosítva – adjon meg egy jelmondatot a titkosításhoz. No comment provided by engineer. + + Your chat preferences + Csevegési beállítások + alert title + Your chat profiles Csevegési profilok No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + A kapcsolata át lett helyezve ide: %@, de egy váratlan hiba történt a profilra való átirányításkor. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). - Ismerőse olyan fájlt küldött, amely meghaladja a jelenleg támogatott maximális méretet (%@). + Az ismerőse olyan fájlt küldött, amely meghaladja a jelenleg támogatott maximális méretet (%@). No comment provided by engineer. Your contacts can allow full message deletion. - Ismerősök engedélyezhetik a teljes üzenet törlést. + Az ismerősei engedélyezhetik a teljes üzenet törlést. No comment provided by engineer. @@ -7734,6 +8446,11 @@ Kapcsolódási kérés megismétlése? Az ismerősei továbbra is kapcsolódva maradnak. No comment provided by engineer. + + Your credentials may be sent unencrypted. + A hitelesítőadatai titkosítatlanul is elküldhetők. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. A jelenlegi csevegési adatbázis TÖRLŐDNI FOG, és a HELYÉRE az importált adatbázis kerül. @@ -7764,16 +8481,19 @@ Kapcsolódási kérés megismétlése? A(z) **%@** nevű profilja megosztásra fog kerülni. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Profilja az eszközön van tárolva, és csak az ismerősökkel kerül megosztásra. -A SimpleX kiszolgálók nem látjhatják profilját. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + A profilja az eszközön van tárolva és csak az ismerőseivel kerül megosztásra. A SimpleX-kiszolgálók nem láthatják a profilját. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + A profilja megváltozott. Ha elmenti, a frissített profil elküldésre kerül az összes ismerősének. + alert message + Your profile, contacts and delivered messages are stored on your device. - Profilja, ismerősei és az elküldött üzenetei az eszközön kerülnek tárolásra. + A profilja, az ismerősei és az elküldött üzenetei az eszközön kerülnek tárolásra. No comment provided by engineer. @@ -7781,14 +8501,14 @@ A SimpleX kiszolgálók nem látjhatják profilját. Véletlenszerű profil No comment provided by engineer. - - Your server - Saját kiszolgáló - No comment provided by engineer. - Your server address - Saját kiszolgáló cím + Saját SMP-kiszolgálójának címe + No comment provided by engineer. + + + Your servers + Az Ön kiszolgálói No comment provided by engineer. @@ -7808,7 +8528,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. [Star on GitHub](https://github.com/simplex-chat/simplex-chat) - [Csillag a GitHubon](https://github.com/simplex-chat/simplex-chat) + [Csillagozás a GitHubon](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. @@ -7831,19 +8551,24 @@ A SimpleX kiszolgálók nem látjhatják profilját. elfogadott hívás call status + + accepted invitation + elfogadott meghívó + chat list item title + admin - admin + adminisztrátor member role admins - adminok + adminisztrátorok feature role agreeing encryption for %@… - titkosítás jóváhagyása %@ számára… + titkosítás elfogadása %@ számára… chat item text @@ -7853,7 +8578,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. all members - minden tag + összes tag feature role @@ -7888,22 +8613,22 @@ A SimpleX kiszolgálók nem látjhatják profilját. bad message hash - téves üzenet hash + hibás az üzenet hasító értéke integrity error chat item blocked - blokkolva + letiltva marked deleted chat item preview text blocked %@ - letiltotta őt: %@ + letiltotta %@-t rcv group event chat item blocked by admin - letiltva az admin által + letiltva az adminisztrátor által marked deleted chat item preview text @@ -7918,7 +8643,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. call error - hiba a hívásban + híváshiba call status @@ -7948,7 +8673,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. changed your role to %@ - megváltoztatta a szerepkörét erre: %@ + megváltoztatta az Ön szerepkörét erre: %@ rcv group event chat item @@ -7973,17 +8698,17 @@ A SimpleX kiszolgálók nem látjhatják profilját. connect to SimpleX Chat developers. - Kapcsolódás a SimpleX Chat fejlesztőkhöz. + kapcsolódás a SimpleX Chat fejlesztőkhöz. No comment provided by engineer. connected - kapcsolódva + kapcsolódott No comment provided by engineer. connected directly - közvetlenül kapcsolódva + közvetlenül kapcsolódott rcv group event chat item @@ -8008,18 +8733,18 @@ A SimpleX kiszolgálók nem látjhatják profilját. connecting (introduction invitation) - kapcsolódás (bemutatkozó meghívó) + kapcsolódás (bemutatkozó-meghívó) No comment provided by engineer. connecting call… - hívás kapcsolódik… + kapcsolódási hívás… call status connecting… kapcsolódás… - chat list item title + No comment provided by engineer. connection established @@ -8143,12 +8868,12 @@ A SimpleX kiszolgálók nem látjhatják profilját. enabled for you - engedélyezve az ön számára + engedélyezve az Ön számára enabled status encryption agreed - titkosítás egyeztetve + titkosítás elfogadva chat item text @@ -8211,6 +8936,11 @@ A SimpleX kiszolgálók nem látjhatják profilját. lejárt No comment provided by engineer. + + for better metadata privacy. + a metaadatok jobb védelme érdekében. + No comment provided by engineer. + forwarded továbbított @@ -8248,17 +8978,17 @@ A SimpleX kiszolgálók nem látjhatják profilját. incognito via contact address link - inkognitó a kapcsolattartási hivatkozáson keresztül + inkognitó a kapcsolattartási címhivatkozáson keresztül chat list item description incognito via group link - inkognitó a csoportos hivatkozáson keresztül + inkognitó a csoporthivatkozáson keresztül chat list item description incognito via one-time link - inkognitó az egyszer használatos hivatkozáson keresztül + inkognitó egy egyszer használható meghívó-hivatkozáson keresztül chat list item description @@ -8273,7 +9003,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. invalid chat data - érvénytelen csevegés adat + érvénytelen csevegésadat No comment provided by engineer. @@ -8308,7 +9038,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. invited via your group link - meghíva az ön csoport hivatkozásán keresztül + meghíva az Ön csoporthivatkozásán keresztül rcv group event chat item @@ -8328,7 +9058,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. marked deleted - töröltnek jelölve + törlésre jelölve marked deleted chat item preview text @@ -8470,7 +9200,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. received answer… - fogadott válasz… + válasz fogadása… No comment provided by engineer. @@ -8490,24 +9220,29 @@ A SimpleX kiszolgálók nem látjhatják profilját. removed %@ - %@ eltávolítva + eltávolította őt: %@ rcv group event chat item removed contact address - törölt kapcsolattartási cím + eltávolította a kapcsolattartási címet profile update event chat item removed profile picture - törölte a profilképét + eltávolította a profilképét profile update event chat item removed you - eltávolítottak + eltávolította Önt rcv group event chat item + + requested to connect + kérelmezve a kapcsolódáshoz + chat list item title + saved mentett @@ -8515,7 +9250,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. saved from %@ - mentve innen: %@ + elmentve innen: %@ No comment provided by engineer. @@ -8552,7 +9287,7 @@ A SimpleX kiszolgálók nem látjhatják profilját. server queue info: %1$@ last received msg: %2$@ - kiszolgáló üzenet-várakotatási információ: %1$@ + a kiszolgáló üzenet-sorbaállítási információi: %1$@ utoljára fogadott üzenet: %2$@ queue info @@ -8589,7 +9324,7 @@ utoljára fogadott üzenet: %2$@ unblocked %@ - %@ feloldva + feloldotta %@ letiltását rcv group event chat item @@ -8604,12 +9339,12 @@ utoljára fogadott üzenet: %2$@ unknown status - ismeretlen státusz + ismeretlen állapot No comment provided by engineer. unmute - némítás feloldása + némítás megszüntetése No comment provided by engineer. @@ -8644,17 +9379,17 @@ utoljára fogadott üzenet: %2$@ via group link - csoport hivatkozáson keresztül + a csoporthivatkozáson keresztül chat list item description via one-time link - egyszer használatos hivatkozáson keresztül + egyszer használható meghívó-hivatkozáson keresztül chat list item description via relay - átjátszón keresztül + közvetítő-kiszolgálón keresztül No comment provided by engineer. @@ -8679,7 +9414,7 @@ utoljára fogadott üzenet: %2$@ wants to connect to you! - kapcsolatba akar lépni önnel! + kapcsolatba akar lépni Önnel! No comment provided by engineer. @@ -8699,7 +9434,7 @@ utoljára fogadott üzenet: %2$@ you - ön + Ön No comment provided by engineer. @@ -8709,12 +9444,12 @@ utoljára fogadott üzenet: %2$@ you are observer - megfigyelő szerep + Ön megfigyelő No comment provided by engineer. you blocked %@ - blokkolta őt: %@ + Ön letiltotta őt: %@ snd group event chat item @@ -8729,42 +9464,42 @@ utoljára fogadott üzenet: %2$@ you changed role for yourself to %@ - saját szerepkör megváltoztatva erre: %@ + saját szerepköre megváltozott erre: %@ snd group event chat item you changed role of %1$@ to %2$@ - %1$@ szerepkörét megváltoztatta erre: %@ + Ön megváltoztatta %1$@ szerepkörét erre: %@ snd group event chat item you left - elhagyta a csoportot + Ön elhagyta a csoportot snd group event chat item you removed %@ - eltávolította őt: %@ + Ön eltávolította őt: %@ snd group event chat item you shared one-time link - egyszer használatos hivatkozást osztott meg + Ön egy egyszer használható meghívó-hivatkozást osztott meg chat list item description you shared one-time link incognito - egyszer használatos hivatkozást osztott meg inkognitóban + Ön egy egyszer használható meghívó-hivatkozást osztott meg inkognitóban chat list item description you unblocked %@ - feloldotta %@ blokkolását + Ön feloldotta %@ letiltását snd group event chat item you: - ön: + Ön: No comment provided by engineer. @@ -8786,7 +9521,7 @@ utoljára fogadott üzenet: %2$@ SimpleX needs camera access to scan QR codes to connect to other users and for video calls. - A SimpleX-nek kamera-hozzáférésre van szüksége a QR-kódok beolvasásához, hogy kapcsolódhasson más felhasználókhoz és videohívásokhoz. + A SimpleXnek kamera-hozzáférésre van szüksége a QR-kódok beolvasásához, hogy kapcsolódhasson más felhasználókhoz és videohívásokhoz. Privacy - Camera Usage Description @@ -8801,12 +9536,12 @@ utoljára fogadott üzenet: %2$@ SimpleX needs microphone access for audio and video calls, and to record voice messages. - A SimpleX-nek mikrofon-hozzáférésre van szüksége hang- és videohívásokhoz, valamint hangüzenetek rögzítéséhez. + A SimpleXnek mikrofon-hozzáférésre van szüksége hang- és videohívásokhoz, valamint hangüzenetek rögzítéséhez. Privacy - Microphone Usage Description SimpleX needs access to Photo Library for saving captured and received media - A SimpleX-nek hozzáférésre van szüksége a Galériához a rögzített és fogadott média mentéséhez + A SimpleXnek galéria-hozzáférésre van szüksége a rögzített és fogadott média mentéséhez Privacy - Photo Library Additions Usage Description @@ -8833,6 +9568,38 @@ utoljára fogadott üzenet: %2$@ + +
+ +
+ + + %d new events + %d új esemény + notification body + + + From: %@ + Tőle: %@ + notification body + + + New events + Új események + notification + + + New messages + Új üzenetek + notification + + + New messages in %d chats + Új üzenetek %d csevegésben + notification body + + +
@@ -8892,7 +9659,7 @@ utoljára fogadott üzenet: %2$@ Currently maximum supported file size is %@. - Jelenleg a maximális támogatott fájlméret %@. + Jelenleg a maximálisan támogatott fájlméret: %@. No comment provided by engineer. @@ -8907,7 +9674,7 @@ utoljára fogadott üzenet: %2$@ Database error - Adatbázis hiba + Adatbázishiba No comment provided by engineer. @@ -8917,7 +9684,7 @@ utoljára fogadott üzenet: %2$@ Database passphrase is required to open chat. - Adatbázis jelmondat szükséges a csevegés megnyitásához. + Adatbázis-jelmondat szükséges a csevegés megnyitásához. No comment provided by engineer. @@ -8947,7 +9714,7 @@ utoljára fogadott üzenet: %2$@ Incompatible database version - Nem kompatibilis adatbázis verzió + Nem kompatibilis adatbázis-verzió No comment provided by engineer. @@ -8957,7 +9724,7 @@ utoljára fogadott üzenet: %2$@ Keychain error - Kulcstartó hiba + Kulcstartóhiba No comment provided by engineer. @@ -9022,7 +9789,7 @@ utoljára fogadott üzenet: %2$@ Unknown database error: %@ - Ismeretlen adatbázis hiba: %@ + Ismeretlen adatbázishiba: %@ No comment provided by engineer. @@ -9037,12 +9804,12 @@ utoljára fogadott üzenet: %2$@ Wrong database passphrase - Hibás adatbázis jelmondat + Hibás adatbázis-jelmondat No comment provided by engineer. You can allow sharing in Privacy & Security / SimpleX Lock settings. - A megosztást az Adatvédelem és biztonság / SimpleX zár menüben engedélyezheti. + A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/hu.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/hu.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/hu.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 137476db50..d785acda81 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ è verificato/a No comment provided by engineer. + + %@ server + %@ server + No comment provided by engineer. + + + %@ servers + %@ server + No comment provided by engineer. + %@ uploaded %@ caricati @@ -137,6 +132,11 @@ %@ si vuole connettere! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ e %lld membri @@ -157,11 +157,36 @@ %d giorni time interval + + %d file(s) are still being downloaded. + %d file è/sono ancora in scaricamento. + forward confirmation reason + + + %d file(s) failed to download. + %d file ha/hanno fallito lo scaricamento. + forward confirmation reason + + + %d file(s) were deleted. + %d file è/sono stato/i eliminato/i. + forward confirmation reason + + + %d file(s) were not downloaded. + %d file non è/sono stato/i scaricato/i. + forward confirmation reason + %d hours %d ore time interval + + %d messages not forwarded + %d messaggi non inoltrati + alert title + %d min %d min @@ -322,14 +347,9 @@ ) 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 or link for your contact. - **Aggiungi un contatto**: per creare il tuo codice QR o link una tantum per il tuo contatto. + + **Create 1-time link**: to create and share a new invitation link. + **Aggiungi contatto**: per creare un nuovo link di invito. No comment provided by engineer. @@ -337,13 +357,13 @@ **Crea gruppo**: per creare un nuovo gruppo. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Più privato**: controlla messaggi nuovi ogni 20 minuti. Viene condiviso il token del dispositivo con il server di SimpleX Chat, ma non quanti contatti o messaggi hai. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +377,16 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + **Scansiona / Incolla link**: per connetterti tramite un link che hai ricevuto. + 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. @@ -468,6 +493,16 @@ 1 settimana time interval + + 1-time link + Link una tantum + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Il link una tantum può essere usato *con un solo contatto* - condividilo di persona o tramite qualsiasi messenger. + No comment provided by engineer. + 5 minutes 5 minuti @@ -537,19 +572,13 @@ Interrompere il cambio di indirizzo? No comment provided by engineer. - - About SimpleX - Riguardo SimpleX - No comment provided by engineer. - About SimpleX Chat Riguardo SimpleX Chat No comment provided by engineer. - - About SimpleX address - Info sull'indirizzo SimpleX + + About operators No comment provided by engineer. @@ -564,6 +593,11 @@ accept incoming call via notification swipe action + + Accept conditions + Accetta le condizioni + No comment provided by engineer. + Accept connection request? Accettare la richiesta di connessione? @@ -580,6 +614,11 @@ accept contact request via notification swipe action + + Accepted conditions + Condizioni accettate + No comment provided by engineer. + Acknowledged Riconosciuto @@ -600,14 +639,9 @@ 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 + + Add friends + Aggiungi amici No comment provided by engineer. @@ -625,6 +659,11 @@ Aggiungi server scansionando codici QR. No comment provided by engineer. + + Add team members + Aggiungi membri del team + No comment provided by engineer. + Add to another device Aggiungi ad un altro dispositivo @@ -635,6 +674,21 @@ Aggiungi messaggio di benvenuto No comment provided by engineer. + + Add your team members to the conversations. + Aggiungi i membri del tuo team alle conversazioni. + No comment provided by engineer. + + + Added media & file servers + Server di multimediali e file aggiunti + No comment provided by engineer. + + + Added message servers + Server dei messaggi aggiunti + No comment provided by engineer. + Additional accent Principale aggiuntivo @@ -660,6 +714,16 @@ Il cambio di indirizzo verrà interrotto. Verrà usato il vecchio indirizzo di ricezione. No comment provided by engineer. + + Address or 1-time link? + Indirizzo o link una tantum? + No comment provided by engineer. + + + Address settings + Impostazioni dell'indirizzo + No comment provided by engineer. + Admins can block a member for all. Gli amministratori possono bloccare un membro per tutti. @@ -695,8 +759,8 @@ Tutti i dati vengono cancellati quando inserito. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Tutti i dati sono privati, nel tuo dispositivo. No comment provided by engineer. @@ -705,6 +769,11 @@ Tutti i membri del gruppo resteranno connessi. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Tutti i messaggi e i file vengono inviati **crittografati end-to-end**, con sicurezza resistenti alla quantistica nei messaggi diretti. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Tutti i messaggi verranno eliminati, non è reversibile! @@ -723,7 +792,7 @@ All profiles Tutti gli profili - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -885,6 +954,11 @@ Rispondi alla chiamata No comment provided by engineer. + + Anybody can host servers. + Chiunque può installare i server. + No comment provided by engineer. + App build: %@ Build dell'app: %@ @@ -915,6 +989,11 @@ Il codice di accesso dell'app viene sostituito da un codice di autodistruzione. No comment provided by engineer. + + App session + Sessione dell'app + No comment provided by engineer. + App version Versione dell'app @@ -1012,14 +1091,19 @@ Auto-accept contact requests - Auto-accetta richieste di contatto + Auto-accetta le richieste di contatto No comment provided by engineer. Auto-accept images - Auto-accetta immagini + Auto-accetta le immagini No comment provided by engineer. + + Auto-accept settings + Accetta automaticamente le impostazioni + alert title + Back Indietro @@ -1045,11 +1129,21 @@ Hash del messaggio errato No comment provided by engineer. + + Better calls + Chiamate migliorate + No comment provided by engineer. + Better groups Gruppi migliorati No comment provided by engineer. + + Better message dates. + Date dei messaggi migliorate. + No comment provided by engineer. + Better messages Messaggi migliorati @@ -1060,6 +1154,21 @@ Rete migliorata No comment provided by engineer. + + Better notifications + Notifiche migliorate + No comment provided by engineer. + + + Better security ✅ + Sicurezza migliorata ✅ + No comment provided by engineer. + + + Better user experience + Esperienza utente migliorata + No comment provided by engineer. + Black Nero @@ -1107,7 +1216,7 @@ Blur media - Sfocatura file multimediali + Sfocatura dei file multimediali No comment provided by engineer. @@ -1140,6 +1249,16 @@ Bulgaro, finlandese, tailandese e ucraino - grazie agli utenti e a [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Indirizzo di lavoro + No comment provided by engineer. + + + Business chats + Chat di lavoro + 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). Per profilo di chat (predefinito) o [per connessione](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1193,7 +1312,8 @@ Cancel Annulla - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1333,7 @@ Cannot receive file Impossibile ricevere il file - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1350,11 @@ Cambia No comment provided by engineer. + + Change chat profiles + Modifica profili utente + authentication reason + Change database passphrase? Cambiare password del database? @@ -1276,9 +1401,19 @@ authentication reason set passcode view - - Chat archive - Archivio chat + + Chat + Chat + No comment provided by engineer. + + + Chat already exists + La chat esiste già + No comment provided by engineer. + + + Chat already exists! + La chat esiste già! No comment provided by engineer. @@ -1341,20 +1476,50 @@ Preferenze della chat No comment provided by engineer. + + Chat preferences were changed. + Le preferenze della chat sono state cambiate. + alert message + + + Chat profile + Profilo utente + No comment provided by engineer. + Chat theme Tema della chat No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + La chat verrà eliminata per tutti i membri, non è reversibile! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + La chat verrà eliminata solo per te, non è reversibile! + No comment provided by engineer. + Chats Chat No comment provided by engineer. + + Check messages every 20 min. + Controlla i messaggi ogni 20 min. + No comment provided by engineer. + + + Check messages when allowed. + Controlla i messaggi quando consentito. + No comment provided by engineer. + Check server address and try again. Controlla l'indirizzo del server e riprova. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1441,16 +1606,56 @@ Completato No comment provided by engineer. + + Conditions accepted on: %@. + Condizioni accettate il: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Le condizioni sono state accettate per gli operatori: **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Le condizioni sono già state accettate per i seguenti operatori: **%@**. + No comment provided by engineer. + + + Conditions of use + Condizioni d'uso + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Le condizioni verranno accettate per gli operatori attivati dopo 30 giorni. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Le condizioni verranno accettate per gli operatori: **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Le condizioni verranno accettate per gli operatori: **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Le condizioni verranno accettate il: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Le condizioni verranno accettate automaticamente per gli operatori attivi il: %@. + No comment provided by engineer. + Configure ICE servers Configura server ICE No comment provided by engineer. - - Configured %@ servers - Configurati %@ server - No comment provided by engineer. - Confirm Conferma @@ -1617,7 +1822,7 @@ Questo è il tuo link una tantum! Connection and servers status. - Stato di connessione e server. + Stato della connessione e dei server. No comment provided by engineer. @@ -1640,6 +1845,11 @@ Questo è il tuo link una tantum! Richiesta di connessione inviata! No comment provided by engineer. + + Connection security + Sicurezza della connessione + No comment provided by engineer. + Connection terminated Connessione terminata @@ -1740,6 +1950,11 @@ Questo è il tuo link una tantum! Versione core: v%@ No comment provided by engineer. + + Corner + Angolo + No comment provided by engineer. + Correct name to %@? Correggere il nome a %@? @@ -1750,6 +1965,11 @@ Questo è il tuo link una tantum! Crea No comment provided by engineer. + + Create 1-time link + Crea link una tantum + No comment provided by engineer. + Create SimpleX address Crea indirizzo SimpleX @@ -1760,11 +1980,6 @@ Questo è il tuo link una tantum! Crea un gruppo usando un profilo casuale. No comment provided by engineer. - - Create an address to let people connect with you. - Crea un indirizzo per consentire alle persone di connettersi con te. - No comment provided by engineer. - Create file Crea file @@ -1825,11 +2040,6 @@ Questo è il tuo link una tantum! Creato il: %@ copied message info - - Created on %@ - Creato il %@ - No comment provided by engineer. - Creating archive link Creazione link dell'archivio @@ -1845,6 +2055,11 @@ Questo è il tuo link una tantum! Codice di accesso attuale No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + Il testo delle condizioni attuali testo non è stato caricato, puoi consultare le condizioni tramite questo link: + No comment provided by engineer. + Current passphrase… Password attuale… @@ -1865,6 +2080,11 @@ Questo è il tuo link una tantum! Tempo personalizzato No comment provided by engineer. + + Customizable message shape. + Forma dei messaggi personalizzabile. + No comment provided by engineer. + Customize theme Personalizza il tema @@ -1996,7 +2216,8 @@ Questo è il tuo link una tantum! Delete Elimina - chat item action + alert action + chat item action swipe action @@ -2034,14 +2255,9 @@ Questo è il tuo link una tantum! Elimina e avvisa il contatto No comment provided by engineer. - - Delete archive - Elimina archivio - No comment provided by engineer. - - - Delete chat archive? - Eliminare l'archivio della chat? + + Delete chat + Elimina chat No comment provided by engineer. @@ -2054,6 +2270,11 @@ Questo è il tuo link una tantum! Eliminare il profilo di chat? No comment provided by engineer. + + Delete chat? + Eliminare la chat? + No comment provided by engineer. + Delete connection Elimina connessione @@ -2159,6 +2380,11 @@ Questo è il tuo link una tantum! Eliminare il database vecchio? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Elimina o modera fino a 200 messaggi. + No comment provided by engineer. + Delete pending connection? Eliminare la connessione in attesa? @@ -2209,6 +2435,11 @@ Questo è il tuo link una tantum! Errori di eliminazione No comment provided by engineer. + + Delivered even when Apple drops them. + Consegnati anche quando Apple li scarta. + No comment provided by engineer. + Delivery Consegna @@ -2309,8 +2540,13 @@ Questo è il tuo link una tantum! Messaggi diretti chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + I messaggi diretti tra i membri sono vietati in questa chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. I messaggi diretti tra i membri sono vietati in questo gruppo. No comment provided by engineer. @@ -2349,8 +2585,8 @@ Questo è il tuo link una tantum! I messaggi a tempo sono vietati in questa chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. I messaggi a tempo sono vietati in questo gruppo. No comment provided by engineer. @@ -2409,6 +2645,11 @@ Questo è il tuo link una tantum! Non inviare la cronologia ai nuovi membri. No comment provided by engineer. + + Do not use credentials with proxy. + Non usare credenziali con proxy. + No comment provided by engineer. + Don't create address Non creare un indirizzo @@ -2432,7 +2673,8 @@ Questo è il tuo link una tantum! Download Scarica - chat item action + alert button + chat item action Download errors @@ -2449,6 +2691,11 @@ Questo è il tuo link una tantum! Scarica file server test step + + Download files + Scarica i file + alert action + Downloaded Scaricato @@ -2479,6 +2726,11 @@ Questo è il tuo link una tantum! Durata No comment provided by engineer. + + E2E encrypted notifications. + Notifiche crittografate E2E. + No comment provided by engineer. + Edit Modifica @@ -2499,6 +2751,11 @@ Questo è il tuo link una tantum! Attiva (mantieni sostituzioni) No comment provided by engineer. + + Enable Flux + Attiva Flux + No comment provided by engineer. + Enable SimpleX Lock Attiva SimpleX Lock @@ -2704,26 +2961,36 @@ Questo è il tuo link una tantum! Errore nell'interruzione del cambio di indirizzo No comment provided by engineer. + + Error accepting conditions + Errore di accettazione delle condizioni + alert title + Error accepting contact request Errore nell'accettazione della richiesta di contatto No comment provided by engineer. - - Error accessing database file - Errore nell'accesso al file del database - No comment provided by engineer. - Error adding member(s) Errore di aggiunta membro/i No comment provided by engineer. + + Error adding server + Errore di aggiunta del server + alert title + Error changing address Errore nella modifica dell'indirizzo No comment provided by engineer. + + Error changing connection profile + Errore nel cambio di profilo di connessione + No comment provided by engineer. + Error changing role Errore nel cambio di ruolo @@ -2734,6 +3001,11 @@ Questo è il tuo link una tantum! Errore nella modifica dell'impostazione No comment provided by engineer. + + Error changing to incognito! + Errore nel passaggio a incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Errore di connessione al server di inoltro %@. Riprova più tardi. @@ -2849,9 +3121,14 @@ Questo è il tuo link una tantum! Errore di ingresso nel gruppo No comment provided by engineer. - - Error loading %@ servers - Errore nel caricamento dei server %@ + + Error loading servers + Errore nel caricamento dei server + alert title + + + Error migrating settings + Errore nella migrazione delle impostazioni No comment provided by engineer. @@ -2862,7 +3139,7 @@ Questo è il tuo link una tantum! Error receiving file Errore nella ricezione del file - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3161,6 @@ Questo è il tuo link una tantum! Errore di azzeramento statistiche No comment provided by engineer. - - Error saving %@ servers - Errore nel salvataggio dei server %@ - No comment provided by engineer. - Error saving ICE servers Errore nel salvataggio dei server ICE @@ -2909,6 +3181,11 @@ Questo è il tuo link una tantum! Errore nel salvataggio della password nel portachiavi No comment provided by engineer. + + Error saving servers + Errore di salvataggio dei server + alert title + Error saving settings Errore di salvataggio delle impostazioni @@ -2954,10 +3231,15 @@ Questo è il tuo link una tantum! Errore nell'interruzione della chat No comment provided by engineer. + + Error switching profile + Errore nel cambio di profilo + No comment provided by engineer. + Error switching profile! Errore nel cambio di profilo! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3256,11 @@ Questo è il tuo link una tantum! Errore nell'aggiornamento del messaggio No comment provided by engineer. + + Error updating server + Errore di aggiornamento del server + alert title + Error updating settings Errore nell'aggiornamento delle impostazioni @@ -3002,8 +3289,7 @@ Questo è il tuo link una tantum! Error: %@ Errore: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3306,11 @@ Questo è il tuo link una tantum! Errori No comment provided by engineer. + + Errors in servers configuration. + Errori nella configurazione dei server. + servers error + Even when disabled in the conversation. Anche quando disattivato nella conversazione. @@ -3090,6 +3381,13 @@ Questo è il tuo link una tantum! Errore del file No comment provided by engineer. + + File errors: +%@ + Errori di file: +%@ + alert message + File not found - most likely file was deleted or cancelled. File non trovato - probabilmente è stato eliminato o annullato. @@ -3145,8 +3443,8 @@ Questo è il tuo link una tantum! File e multimediali chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. File e contenuti multimediali sono vietati in questo gruppo. No comment provided by engineer. @@ -3215,21 +3513,61 @@ Questo è il tuo link una tantum! Correzione non supportata dal membro del gruppo No comment provided by engineer. + + For chat profile %@: + Per il profilo di chat %@: + servers error + For console Per console No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Ad esempio, se il tuo contatto riceve messaggi tramite un server di SimpleX Chat, la tua app li consegnerà tramite un server Flux. + No comment provided by engineer. + + + For private routing + Per l'instradamento privato + No comment provided by engineer. + + + For social media + Per i social media + No comment provided by engineer. + Forward Inoltra chat item action + + Forward %d message(s)? + Inoltrare %d messaggio/i? + alert title + Forward and save messages Inoltra e salva i messaggi No comment provided by engineer. + + Forward messages + Inoltra i messaggi + alert action + + + Forward messages without files? + Inoltrare i messaggi senza file? + alert message + + + Forward up to 20 messages at once. + Inoltra fino a 20 messaggi alla volta. + No comment provided by engineer. + Forwarded Inoltrato @@ -3240,6 +3578,11 @@ Questo è il tuo link una tantum! Inoltrato da No comment provided by engineer. + + Forwarding %lld messages + Inoltro di %lld messaggi + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. Il server di inoltro %@ non è riuscito a connettersi al server di destinazione %@. Riprova più tardi. @@ -3289,11 +3632,6 @@ Errore: %2$@ Nome completo (facoltativo) No comment provided by engineer. - - Full name: - Nome completo: - No comment provided by engineer. - Fully decentralized – visible only to members. Completamente decentralizzato: visibile solo ai membri. @@ -3379,41 +3717,6 @@ Errore: %2$@ Link del gruppo No comment provided by engineer. - - 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. (24 hours) - I membri del gruppo possono eliminare irreversibilmente i messaggi inviati. (24 ore) - No comment provided by engineer. - - - Group members can send SimpleX links. - I membri del gruppo possono inviare link di Simplex. - No comment provided by engineer. - - - Group members can send direct messages. - I membri del gruppo possono inviare messaggi diretti. - No comment provided by engineer. - - - Group members can send disappearing messages. - I membri del gruppo possono inviare messaggi a tempo. - No comment provided by engineer. - - - Group members can send files and media. - I membri del gruppo possono inviare file e contenuti multimediali. - No comment provided by engineer. - - - Group members can send voice messages. - I membri del gruppo possono inviare messaggi vocali. - No comment provided by engineer. - Group message: Messaggio del gruppo: @@ -3509,9 +3812,14 @@ Errore: %2$@ Come funziona SimpleX No comment provided by engineer. - - How it works - Come funziona + + How it affects privacy + Come influisce sulla privacy + No comment provided by engineer. + + + How it helps privacy + Come aiuta la privacy No comment provided by engineer. @@ -3539,6 +3847,11 @@ Errore: %2$@ Server ICE (uno per riga) No comment provided by engineer. + + IP address + Indirizzo IP + 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. @@ -3579,8 +3892,8 @@ Errore: %2$@ Immediatamente No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Immune a spam e abusi No comment provided by engineer. @@ -3614,6 +3927,13 @@ Errore: %2$@ Importazione archivio No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Consegna migliorata, utilizzo di traffico ridotto. +Altri miglioramenti sono in arrivo! + No comment provided by engineer. + Improved message delivery Consegna dei messaggi migliorata @@ -3714,6 +4034,11 @@ Errore: %2$@ Installa [Simplex Chat per terminale](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Istantaneamente + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4046,6 @@ Errore: %2$@ No comment provided by engineer. - - Instantly - Istantaneamente - No comment provided by engineer. - Interface Interfaccia @@ -3774,7 +4094,7 @@ Errore: %2$@ Invalid server address! Indirizzo del server non valido! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4116,11 @@ Errore: %2$@ Invita membri No comment provided by engineer. + + Invite to chat + Invita in chat + No comment provided by engineer. + Invite to group Invita al gruppo @@ -3811,8 +4136,8 @@ Errore: %2$@ L'eliminazione irreversibile dei messaggi è vietata in questa chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. L'eliminazione irreversibile dei messaggi è vietata in questo gruppo. No comment provided by engineer. @@ -3902,7 +4227,7 @@ Questo è il tuo link per il gruppo %@! Keep Tieni - No comment provided by engineer. + alert action Keep conversation @@ -3917,7 +4242,7 @@ Questo è il tuo link per il gruppo %@! Keep unused invitation? Tenere l'invito inutilizzato? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4279,16 @@ Questo è il tuo link per il gruppo %@! Esci swipe action + + Leave chat + Esci dalla chat + No comment provided by engineer. + + + Leave chat? + Uscire dalla chat? + No comment provided by engineer. + Leave group Esci dal gruppo @@ -4004,11 +4339,6 @@ Questo è il tuo link per il gruppo %@! Messaggi in diretta No comment provided by engineer. - - Local - Locale - No comment provided by engineer. - Local name Nome locale @@ -4029,11 +4359,6 @@ Questo è il tuo link per il gruppo %@! Modalità di blocco No comment provided by engineer. - - Make a private connection - Crea una connessione privata - No comment provided by engineer. - Make one message disappear Fai sparire un messaggio @@ -4044,21 +4369,11 @@ Questo è il tuo link per il gruppo %@! Rendi privato il profilo! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Assicurati che gli indirizzi dei server %@ siano nel formato corretto, uno per riga e non doppi (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Assicurati che gli indirizzi dei server WebRTC ICE siano nel formato corretto, uno per riga e non doppi. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Molte persone hanno chiesto: *se SimpleX non ha identificatori utente, come può recapitare i messaggi?* - No comment provided by engineer. - Mark deleted for everyone Contrassegna eliminato per tutti @@ -4104,6 +4419,11 @@ Questo è il tuo link per il gruppo %@! Membro inattivo item status text + + Member role will be changed to "%@". All chat members will be notified. + Il ruolo del membro verrà cambiato in "%@". Verranno notificati tutti i membri della chat. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Il ruolo del membro verrà cambiato in "%@". Tutti i membri del gruppo verranno avvisati. @@ -4114,11 +4434,51 @@ Questo è il tuo link per il gruppo %@! Il ruolo del membro verrà cambiato in "%@". Il membro riceverà un invito nuovo. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + Il membro verrà rimosso dalla chat, non è reversibile! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Il membro verrà rimosso dal gruppo, non è reversibile! No comment provided by engineer. + + Members can add message reactions. + I membri del gruppo possono aggiungere reazioni ai messaggi. + No comment provided by engineer. + + + 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. + + + Members can send SimpleX links. + I membri del gruppo possono inviare link di Simplex. + No comment provided by engineer. + + + Members can send direct messages. + I membri del gruppo possono inviare messaggi diretti. + No comment provided by engineer. + + + Members can send disappearing messages. + I membri del gruppo possono inviare messaggi a tempo. + No comment provided by engineer. + + + Members can send files and media. + I membri del gruppo possono inviare file e contenuti multimediali. + No comment provided by engineer. + + + Members can send voice messages. + I membri del gruppo possono inviare messaggi vocali. + No comment provided by engineer. + Menus Menu @@ -4141,7 +4501,7 @@ Questo è il tuo link per il gruppo %@! Message draft - Bozza dei messaggi + Bozza del messaggio No comment provided by engineer. @@ -4169,8 +4529,8 @@ Questo è il tuo link per il gruppo %@! Le reazioni ai messaggi sono vietate in questa chat. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Le reazioni ai messaggi sono vietate in questo gruppo. No comment provided by engineer. @@ -4184,6 +4544,11 @@ Questo è il tuo link per il gruppo %@! Server dei messaggi No comment provided by engineer. + + Message shape + Forma del messaggio + No comment provided by engineer. + Message source remains private. La fonte del messaggio resta privata. @@ -4234,6 +4599,11 @@ Questo è il tuo link per il gruppo %@! Messaggi inviati No comment provided by engineer. + + Messages were deleted after you selected them. + I messaggi sono stati eliminati dopo che li hai selezionati. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. I messaggi, i file e le chiamate sono protetti da **crittografia end-to-end** con perfect forward secrecy, ripudio e recupero da intrusione. @@ -4299,9 +4669,9 @@ Questo è il tuo link per il gruppo %@! La migrazione è completata No comment provided by engineer. - - Migrations: %@ - Migrazioni: %@ + + Migrations: + Migrazioni: No comment provided by engineer. @@ -4329,6 +4699,11 @@ Questo è il tuo link per il gruppo %@! Connessione di rete più affidabile. No comment provided by engineer. + + More reliable notifications + Notifiche più affidabili + No comment provided by engineer. + Most likely this connection is deleted. Probabilmente questa connessione è stata eliminata. @@ -4364,6 +4739,11 @@ Questo è il tuo link per il gruppo %@! Connessione di rete No comment provided by engineer. + + Network decentralization + Decentralizzazione della rete + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Problemi di rete - messaggio scaduto dopo molti tentativi di inviarlo. @@ -4374,6 +4754,11 @@ Questo è il tuo link per il gruppo %@! Gestione della rete No comment provided by engineer. + + Network operator + Operatore di rete + No comment provided by engineer. + Network settings Impostazioni di rete @@ -4389,6 +4774,16 @@ Questo è il tuo link per il gruppo %@! Nuovo codice di accesso No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Le nuove credenziali SOCKS verranno usate ogni volta che avvii l'app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Le nuove credenziali SOCKS verranno usate per ogni server. + No comment provided by engineer. + New chat Nuova chat @@ -4409,11 +4804,6 @@ Questo è il tuo link per il gruppo %@! Nuovo contatto: notification - - New database archive - Nuovo archivio database - No comment provided by engineer. - New desktop app! Nuova app desktop! @@ -4424,6 +4814,11 @@ Questo è il tuo link per il gruppo %@! Nuovo nome da mostrare No comment provided by engineer. + + New events + Nuovi eventi + notification + New in %@ Novità nella %@ @@ -4449,6 +4844,11 @@ Questo è il tuo link per il gruppo %@! Nuova password… No comment provided by engineer. + + New server + Nuovo server + No comment provided by engineer. + No No @@ -4504,21 +4904,71 @@ Questo è il tuo link per il gruppo %@! Nessuna informazione, prova a ricaricare No comment provided by engineer. + + No media & file servers. + Nessun server di multimediali e file. + servers error + + + No message servers. + Nessun server dei messaggi. + servers error + No network connection Nessuna connessione di rete No comment provided by engineer. + + No permission to record speech + Nessuna autorizzazione per registrare l'audio + No comment provided by engineer. + + + No permission to record video + Nessuna autorizzazione per registrare il video + No comment provided by engineer. + No permission to record voice message Nessuna autorizzazione per registrare messaggi vocali No comment provided by engineer. + + No push server + Locale + No comment provided by engineer. + No received or sent files Nessun file ricevuto o inviato No comment provided by engineer. + + No servers for private message routing. + Nessun server per l'instradamento dei messaggi privati. + servers error + + + No servers to receive files. + Nessun server per ricevere file. + servers error + + + No servers to receive messages. + Nessun server per ricevere messaggi. + servers error + + + No servers to send files. + Nessun server per inviare file. + servers error + + + No user identifiers. + Nessun identificatore utente. + No comment provided by engineer. + Not compatible! Non compatibile! @@ -4529,6 +4979,11 @@ Questo è il tuo link per il gruppo %@! Nessuna selezione No comment provided by engineer. + + Nothing to forward! + Niente da inoltrare! + alert title + Notifications Notifiche @@ -4539,6 +4994,11 @@ Questo è il tuo link per il gruppo %@! Le notifiche sono disattivate! No comment provided by engineer. + + Notifications privacy + Privacy delle notifiche + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5021,13 @@ Questo è il tuo link per il gruppo %@! Ok Ok - No comment provided by engineer. + alert button Old database Database vecchio No comment provided by engineer. - - Old database archive - Vecchio archivio del database - No comment provided by engineer. - One-time invitation link Link di invito una tantum @@ -4597,8 +5052,13 @@ Richiede l'attivazione della VPN. Gli host Onion non verranno usati. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + Solo i proprietari della chat possono modificarne le preferenze. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Solo i dispositivi client archiviano profili utente, i contatti, i gruppi e i messaggi inviati con la **crittografia end-to-end a 2 livelli**. No comment provided by engineer. @@ -4682,6 +5142,11 @@ Richiede l'attivazione della VPN. Apri le impostazioni No comment provided by engineer. + + Open changes + Apri le modifiche + No comment provided by engineer. + Open chat Apri chat @@ -4692,6 +5157,11 @@ Richiede l'attivazione della VPN. Apri la console della chat authentication reason + + Open conditions + Apri le condizioni + No comment provided by engineer. + Open group Apri gruppo @@ -4702,26 +5172,26 @@ Richiede l'attivazione della VPN. Apri migrazione ad un altro dispositivo authentication reason - - Open server settings - Apri impostazioni server - No comment provided by engineer. - - - Open user profiles - Apri i profili utente - authentication reason - - - 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 app… Apertura dell'app… No comment provided by engineer. + + Operator + Operatore + No comment provided by engineer. + + + Operator server + Server dell'operatore + alert title + + + Or import archive file + O importa file archivio + No comment provided by engineer. + Or paste archive link O incolla il link dell'archivio @@ -4742,15 +5212,22 @@ Richiede l'attivazione della VPN. O mostra questo codice No comment provided by engineer. + + Or to share privately + O per condividere in modo privato + No comment provided by engineer. + Other Altro No comment provided by engineer. - - Other %@ servers - Altri %@ server - No comment provided by engineer. + + Other file errors: +%@ + Altri errori di file: +%@ + alert message PING count @@ -4787,6 +5264,11 @@ Richiede l'attivazione della VPN. Codice di accesso impostato! No comment provided by engineer. + + Password + Password + No comment provided by engineer. + Password to show Password per mostrare @@ -4822,13 +5304,8 @@ Richiede l'attivazione della VPN. In attesa No comment provided by engineer. - - People can connect to you only via the links you share. - Le persone possono connettersi a te solo tramite i link che condividi. - No comment provided by engineer. - - - Periodically + + Periodic Periodicamente No comment provided by engineer. @@ -4936,6 +5413,11 @@ Errore: %@ Interfaccia polacca No comment provided by engineer. + + Port + Porta + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Probabilmente l'impronta del certificato nell'indirizzo del server è sbagliata @@ -4946,16 +5428,16 @@ Errore: %@ Conserva la bozza dell'ultimo messaggio, con gli allegati. No comment provided by engineer. - - Preset server - Server preimpostato - No comment provided by engineer. - Preset server address Indirizzo server preimpostato No comment provided by engineer. + + Preset servers + Server preimpostati + No comment provided by engineer. + Preview Anteprima @@ -4971,6 +5453,11 @@ Errore: %@ Privacy e sicurezza No comment provided by engineer. + + Privacy for your customers. + Privacy per i tuoi clienti. + No comment provided by engineer. + Privacy redefined Privacy ridefinita @@ -5021,16 +5508,6 @@ Errore: %@ Immagini del profilo No comment provided by engineer. - - Profile name - Nome del profilo - No comment provided by engineer. - - - Profile name: - Nome del profilo: - No comment provided by engineer. - Profile password Password del profilo @@ -5044,7 +5521,7 @@ Errore: %@ Profile update will be sent to your contacts. L'aggiornamento del profilo verrà inviato ai tuoi contatti. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5133,6 +5610,11 @@ Attivalo nelle impostazioni *Rete e server*. Server via proxy No comment provided by engineer. + + Proxy requires password + Il proxy richiede una password + No comment provided by engineer. + Push notifications Notifiche push @@ -5173,26 +5655,21 @@ Attivalo nelle impostazioni *Rete e server*. Leggi tutto 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Maggiori informazioni nella [Guida per l'utente](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Maggiori informazioni nel nostro repository GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Maggiori informazioni nel nostro [repository GitHub](https://github.com/simplex-chat/simplex-chat#readme). @@ -5354,6 +5831,11 @@ Attivalo nelle impostazioni *Rete e server*. Rimuovi No comment provided by engineer. + + Remove archive? + Rimuovere l'archivio? + No comment provided by engineer. + Remove image Rimuovi immagine @@ -5504,6 +5986,16 @@ Attivalo nelle impostazioni *Rete e server*. Rivela chat item action + + Review conditions + Leggi le condizioni + No comment provided by engineer. + + + Review later + Leggi più tardi + No comment provided by engineer. + Revoke Revoca @@ -5534,6 +6026,11 @@ Attivalo nelle impostazioni *Rete e server*. Server SMP No comment provided by engineer. + + SOCKS proxy + Proxy SOCKS + No comment provided by engineer. + Safely receive files Ricevi i file in sicurezza @@ -5547,17 +6044,18 @@ Attivalo nelle impostazioni *Rete e server*. Save Salva - chat item action + alert button + chat item action Save (and notify contacts) Salva (e avvisa i contatti) - No comment provided by engineer. + alert button Save and notify contact Salva e avvisa il contatto - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6072,6 @@ Attivalo nelle impostazioni *Rete e server*. Salva e aggiorna il profilo del gruppo No comment provided by engineer. - - Save archive - Salva archivio - No comment provided by engineer. - - - Save auto-accept settings - Salva le impostazioni di accettazione automatica - No comment provided by engineer. - Save group profile Salva il profilo del gruppo @@ -5602,7 +6090,7 @@ Attivalo nelle impostazioni *Rete e server*. Save preferences? Salvare le preferenze? - No comment provided by engineer. + alert title Save profile password @@ -5617,18 +6105,18 @@ Attivalo nelle impostazioni *Rete e server*. Save servers? Salvare i server? - No comment provided by engineer. - - - Save settings? - Salvare le impostazioni? - No comment provided by engineer. + alert title Save welcome message? Salvare il messaggio di benvenuto? No comment provided by engineer. + + Save your profile? + Salvare il profilo? + alert title + Saved Salvato @@ -5649,6 +6137,11 @@ Attivalo nelle impostazioni *Rete e server*. Messaggio salvato message info title + + Saving %lld messages + Salvataggio di %lld messaggi + No comment provided by engineer. + Scale Scala @@ -5729,6 +6222,11 @@ Attivalo nelle impostazioni *Rete e server*. Seleziona chat item action + + Select chat profile + Seleziona il profilo di chat + No comment provided by engineer. + Selected %lld %lld selezionato @@ -5791,7 +6289,7 @@ Attivalo nelle impostazioni *Rete e server*. Send link previews - Invia anteprime dei link + Invia le anteprime dei link No comment provided by engineer. @@ -5819,11 +6317,6 @@ Attivalo nelle impostazioni *Rete e server*. Invia notifiche No comment provided by engineer. - - Send notifications: - Invia notifiche: - No comment provided by engineer. - Send questions and ideas Invia domande e idee @@ -5847,7 +6340,7 @@ Attivalo nelle impostazioni *Rete e server*. Sender cancelled file transfer. Il mittente ha annullato il trasferimento del file. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5944,6 +6437,16 @@ Attivalo nelle impostazioni *Rete e server*. Inviato via proxy No comment provided by engineer. + + Server + Server + No comment provided by engineer. + + + Server added to operator %@. + Server aggiunto all'operatore %@. + alert message + Server address Indirizzo server @@ -5959,6 +6462,21 @@ Attivalo nelle impostazioni *Rete e server*. L'indirizzo del server è incompatibile con le impostazioni di rete: %@. No comment provided by engineer. + + Server operator changed. + L'operatore del server è cambiato. + alert title + + + Server operators + Operatori server + No comment provided by engineer. + + + Server protocol changed. + Il protocollo del server è cambiato. + alert title + Server requires authorization to create queues, check password Il server richiede l'autorizzazione di creare code, controlla la password @@ -6064,6 +6582,11 @@ Attivalo nelle impostazioni *Rete e server*. Impostazioni No comment provided by engineer. + + Settings were changed. + Le impostazioni sono state cambiate. + alert message + Shape profile images Forma delle immagini del profilo @@ -6072,22 +6595,38 @@ Attivalo nelle impostazioni *Rete e server*. Share Condividi - chat item action + alert action + chat item action Share 1-time link Condividi link una tantum No comment provided by engineer. + + Share 1-time link with a friend + Condividi link una tantum con un amico + No comment provided by engineer. + + + Share SimpleX address on social media. + Condividi l'indirizzo SimpleX sui social media. + No comment provided by engineer. + Share address Condividi indirizzo No comment provided by engineer. + + Share address publicly + Condividi indirizzo pubblicamente + No comment provided by engineer. + Share address with contacts? Condividere l'indirizzo con i contatti? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6638,11 @@ Attivalo nelle impostazioni *Rete e server*. Condividi link No comment provided by engineer. + + Share profile + Condividi il profilo + No comment provided by engineer. + Share this 1-time invite link Condividi questo link di invito una tantum @@ -6169,6 +6713,11 @@ Attivalo nelle impostazioni *Rete e server*. Indirizzo SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + SimpleX Chat e Flux hanno concluso un accordo per includere server gestiti da Flux nell'app + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. La sicurezza di SimpleX Chat è stata verificata da Trail of Bits. @@ -6199,6 +6748,16 @@ Attivalo nelle impostazioni *Rete e server*. Indirizzo SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + L'indirizzo SimpleX e i link una tantum sono sicuri da condividere tramite qualsiasi messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + Indirizzo SimpleX o link una tantum? + No comment provided by engineer. + SimpleX contact address Indirizzo di contatto SimpleX @@ -6219,8 +6778,8 @@ Attivalo nelle impostazioni *Rete e server*. Link di SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. I link di SimpleX sono vietati in questo gruppo. No comment provided by engineer. @@ -6234,6 +6793,11 @@ Attivalo nelle impostazioni *Rete e server*. Invito SimpleX una tantum simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Protocolli di SimpleX esaminati da Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Modalità incognito semplificata @@ -6264,6 +6828,11 @@ Attivalo nelle impostazioni *Rete e server*. Leggera blur media + + Some app settings were not migrated. + Alcune impostazioni dell'app non sono state migrate. + No comment provided by engineer. + Some file(s) were not exported: Alcuni file non sono stati esportati: @@ -6279,6 +6848,13 @@ Attivalo nelle impostazioni *Rete e server*. Si sono verificati alcuni errori non fatali durante l'importazione: No comment provided by engineer. + + Some servers failed the test: +%@ + Alcuni server hanno fallito il test: +%@ + alert message + Somebody Qualcuno @@ -6329,11 +6905,6 @@ Attivalo nelle impostazioni *Rete e server*. Ferma la chat No comment provided by engineer. - - Stop chat to enable database actions - Ferma la chat per attivare le azioni del database - 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. Ferma la chat per esportare, importare o eliminare il database della chat. Non potrai ricevere e inviare messaggi mentre la chat è ferma. @@ -6362,12 +6933,12 @@ Attivalo nelle impostazioni *Rete e server*. Stop sharing Smetti di condividere - No comment provided by engineer. + alert action Stop sharing address? Smettere di condividere l'indirizzo? - No comment provided by engineer. + alert title Stopping chat @@ -6404,6 +6975,16 @@ Attivalo nelle impostazioni *Rete e server*. Supporta SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Cambia tra audio e video durante la chiamata. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Cambia profilo di chat per inviti una tantum. + No comment provided by engineer. + System Sistema @@ -6439,11 +7020,21 @@ Attivalo nelle impostazioni *Rete e server*. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Coda + No comment provided by engineer. + Take picture Scatta foto No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Tocca Crea indirizzo SimpleX nel menu per crearlo più tardi. + No comment provided by engineer. + Tap button Tocca il pulsante @@ -6502,7 +7093,7 @@ Attivalo nelle impostazioni *Rete e server*. Tests failed! Test falliti! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7110,6 @@ Attivalo nelle impostazioni *Rete e server*. Grazie agli utenti – contribuite via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - La prima piattaforma senza alcun identificatore utente – privata by design. - No comment provided by engineer. - 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. @@ -6536,6 +7122,11 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.L'app può avvisarti quando ricevi messaggi o richieste di contatto: apri le impostazioni per attivare. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + L'app protegge la tua privacy usando diversi operatori in ogni conversazione. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). L'app chiederà di confermare i download da server di file sconosciuti (eccetto .onion). @@ -6551,6 +7142,11 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.Il codice che hai scansionato non è un codice QR di link SimpleX. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + La connessione ha raggiunto il limite di messaggi non consegnati, il contatto potrebbe essere offline. + No comment provided by engineer. + The connection you accepted will be cancelled! La connessione che hai accettato verrà annullata! @@ -6571,6 +7167,11 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.La crittografia funziona e il nuovo accordo sulla crittografia non è richiesto. Potrebbero verificarsi errori di connessione! No comment provided by engineer. + + The future of messaging + La nuova generazione di messaggistica privata + No comment provided by engineer. + The hash of the previous message is different. L'hash del messaggio precedente è diverso. @@ -6596,11 +7197,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.I messaggi verranno contrassegnati come moderati per tutti i membri. No comment provided by engineer. - - The next generation of private messaging - La nuova generazione di messaggistica privata - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Il database vecchio non è stato rimosso durante la migrazione, può essere eliminato. @@ -6611,6 +7207,21 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.Il profilo è condiviso solo con i tuoi contatti. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Le stesse condizioni si applicheranno all'operatore **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Le stesse condizioni si applicheranno agli operatori **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + Il secondo operatore preimpostato nell'app! + No comment provided by engineer. + The second tick we missed! ✅ Il secondo segno di spunta che ci mancava! ✅ @@ -6626,16 +7237,31 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.I server per le nuove connessioni del profilo di chat attuale **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + I server per nuovi file del tuo 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. + + The uploaded database archive will be permanently removed from the servers. + L'archivio del database caricato verrà rimosso definitivamente dai server. + No comment provided by engineer. + Themes Temi No comment provided by engineer. + + These conditions will also apply for: **%@**. + Queste condizioni si applicheranno anche per: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Queste impostazioni sono per il tuo profilo attuale **%@**. @@ -6736,9 +7362,9 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.Per creare una nuova connessione 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. - Per proteggere la privacy, invece degli ID utente utilizzati da tutte le altre piattaforme, SimpleX ha identificatori per le code di messaggi, separati per ciascuno dei tuoi contatti. + + To protect against your link being replaced, you can compare contact security codes. + Per proteggerti dalla sostituzione del tuo link, puoi confrontare i codici di sicurezza del contatto. No comment provided by engineer. @@ -6758,6 +7384,26 @@ You will be prompted to complete authentication before this feature is enabled.< Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzionalità. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Per proteggere la privacy, invece degli ID utente utilizzati da tutte le altre piattaforme, SimpleX ha identificatori per le code di messaggi, separati per ciascuno dei tuoi contatti. + No comment provided by engineer. + + + To receive + Per ricevere + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Per registrare l'audio, concedi l'autorizzazione di usare il microfono. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Per registrare il video, concedi l'autorizzazione di usare la fotocamera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Per registrare un messaggio vocale, concedi l'autorizzazione all'uso del microfono. @@ -6768,11 +7414,21 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Per rivelare il tuo profilo nascosto, inserisci una password completa in un campo di ricerca nella pagina **I tuoi profili di chat**. No comment provided by engineer. + + To send + Per inviare + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Per supportare le notifiche push istantanee, il database della chat deve essere migrato. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + Per usare i server di **%@**, accetta le condizioni d'uso. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Per verificare la crittografia end-to-end con il tuo contatto, confrontate (o scansionate) il codice sui vostri dispositivi. @@ -6780,7 +7436,7 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Toggle chat list: - Cambia elenco chat: + Cambia l'elenco delle chat: No comment provided by engineer. @@ -6863,6 +7519,11 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Sbloccare il membro? No comment provided by engineer. + + Undelivered messages + Messaggi non consegnati + No comment provided by engineer. + Unexpected migration state Stato di migrazione imprevisto @@ -6911,7 +7572,7 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio Unknown servers! Server sconosciuti! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7681,21 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Invio dell'archivio No comment provided by engineer. + + Use %@ + Usa %@ + No comment provided by engineer. + Use .onion hosts Usa gli host .onion No comment provided by engineer. + + Use SOCKS proxy + Usa proxy SOCKS + No comment provided by engineer. + Use SimpleX Chat servers? Usare i server di SimpleX Chat? @@ -7040,6 +7711,16 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Usa il profilo attuale No comment provided by engineer. + + Use for files + Usa per i file + No comment provided by engineer. + + + Use for messages + Usa per i messaggi + No comment provided by engineer. + Use for new connections Usa per connessioni nuove @@ -7080,6 +7761,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Usa il server No comment provided by engineer. + + Use servers + Usa i server + No comment provided by engineer. + Use the app while in the call. Usa l'app mentre sei in chiamata. @@ -7090,16 +7776,16 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Usa l'app con una mano sola. No comment provided by engineer. - - User profile - Profilo utente - No comment provided by engineer. - User selection Selezione utente No comment provided by engineer. + + Username + Nome utente + No comment provided by engineer. + Using SimpleX Chat servers. Utilizzo dei server SimpleX Chat. @@ -7170,11 +7856,21 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Video e file fino a 1 GB No comment provided by engineer. + + View conditions + Vedi le condizioni + No comment provided by engineer. + View security code Vedi codice di sicurezza No comment provided by engineer. + + View updated conditions + Vedi le condizioni aggiornate + No comment provided by engineer. + Visible history Cronologia visibile @@ -7190,8 +7886,8 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e I messaggi vocali sono vietati in questa chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. I messaggi vocali sono vietati in questo gruppo. No comment provided by engineer. @@ -7285,9 +7981,9 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Quando si connettono le chiamate audio e video. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Quando le persone chiedono di connettersi, puoi accettare o rifiutare. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Quando più di un operatore è attivato, nessuno di essi ha metadati per scoprire chi comunica con chi. No comment provided by engineer. @@ -7333,7 +8029,7 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Senza Tor o VPN, il tuo indirizzo IP sarà visibile a questi relay XFTP: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8056,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Server XFTP No comment provided by engineer. - - You - Tu - No comment provided by engineer. - You **must not** use the same database on two devices. **Non devi** usare lo stesso database su due dispositivi. @@ -7390,6 +8081,11 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e Sei già connesso/a a %@. No comment provided by engineer. + + You are already connected with %@. + Sei già connesso/a con %@. + No comment provided by engineer. + You are already connecting to %@. Ti stai già connettendo a %@. @@ -7452,6 +8148,16 @@ Ripetere la richiesta di ingresso? Puoi cambiarlo nelle impostazioni dell'aspetto. No comment provided by engineer. + + You can configure operators in Network & servers settings. + Puoi configurare gli operatori nelle impostazioni di rete e server. + No comment provided by engineer. + + + You can configure servers via settings. + Puoi configurare i server nelle impostazioni. + No comment provided by engineer. + You can create it later Puoi crearlo più tardi @@ -7492,6 +8198,11 @@ Ripetere la richiesta di ingresso? Puoi inviare messaggi a %@ dai contatti archiviati. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + Puoi impostare il nome della connessione per ricordare con chi è stato condiviso il link. + No comment provided by engineer. + You can set lock screen notification preview via settings. Puoi impostare l'anteprima della notifica nella schermata di blocco tramite le impostazioni. @@ -7507,11 +8218,6 @@ Ripetere la richiesta di ingresso? Puoi condividere questo indirizzo con i tuoi contatti per consentire loro di connettersi con **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Puoi avviare la chat via Impostazioni / Database o riavviando l'app @@ -7535,23 +8241,23 @@ Ripetere la richiesta di ingresso? 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. + alert message You can't send messages! Non puoi inviare messaggi! No comment provided by engineer. - - 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. No comment provided by engineer. + + You decide who can connect. + Sei tu a decidere chi può connettersi. + No comment provided by engineer. + You have already requested connection via this address! Hai già richiesto la connessione tramite questo indirizzo! @@ -7654,6 +8360,11 @@ Ripetere la richiesta di connessione? Continuerai a ricevere chiamate e notifiche da profili silenziati quando sono attivi. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + Non riceverai più messaggi da questa chat. La cronologia della chat verrà conservata. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Non riceverai più messaggi da questo gruppo. La cronologia della chat verrà conservata. @@ -7674,11 +8385,6 @@ Ripetere la richiesta di connessione? Stai usando un profilo in incognito per questo gruppo: per impedire la condivisione del tuo profilo principale non è consentito invitare contatti No comment provided by engineer. - - Your %@ servers - I tuoi server %@ - No comment provided by engineer. - Your ICE servers I tuoi server ICE @@ -7694,11 +8400,6 @@ Ripetere la richiesta di connessione? Il tuo indirizzo SimpleX No comment provided by engineer. - - Your XFTP servers - I tuoi server XFTP - No comment provided by engineer. - Your calls Le tue chiamate @@ -7714,11 +8415,21 @@ Ripetere la richiesta di connessione? Il tuo database della chat non è crittografato: imposta la password per crittografarlo. No comment provided by engineer. + + Your chat preferences + Le tue preferenze della chat + alert title + Your chat profiles I tuoi profili di chat No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + La tua connessione è stata spostata a %@, ma si è verificato un errore imprevisto durante il reindirizzamento al profilo. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Il tuo contatto ha inviato un file più grande della dimensione massima attualmente supportata (%@). @@ -7734,6 +8445,11 @@ Ripetere la richiesta di connessione? I tuoi contatti resteranno connessi. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Le credenziali potrebbero essere inviate in chiaro. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato. @@ -7764,13 +8480,16 @@ Ripetere la richiesta di connessione? Verrà condiviso il tuo profilo **%@**. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. -I server di SimpleX non possono vedere il tuo profilo. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti. I server di SimpleX non possono vedere il tuo profilo. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Il tuo profilo è stato cambiato. Se lo salvi, il profilo aggiornato verrà inviato a tutti i tuoi contatti. + alert message + Your profile, contacts and delivered messages are stored on your device. Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo. @@ -7781,16 +8500,16 @@ I server di SimpleX non possono vedere il tuo profilo. Il tuo profilo casuale No comment provided by engineer. - - Your server - Il tuo server - No comment provided by engineer. - Your server address L'indirizzo del tuo server No comment provided by engineer. + + Your servers + I tuoi server + No comment provided by engineer. + Your settings Le tue impostazioni @@ -7831,6 +8550,10 @@ I server di SimpleX non possono vedere il tuo profilo. chiamata accettata call status + + accepted invitation + chat list item title + admin amministratore @@ -7948,7 +8671,7 @@ I server di SimpleX non possono vedere il tuo profilo. changed your role to %@ - cambiato il tuo ruolo in %@ + ha cambiato il tuo ruolo in %@ rcv group event chat item @@ -8019,7 +8742,7 @@ I server di SimpleX non possono vedere il tuo profilo. connecting… in connessione… - chat list item title + No comment provided by engineer. connection established @@ -8211,6 +8934,11 @@ I server di SimpleX non possono vedere il tuo profilo. scaduto No comment provided by engineer. + + for better metadata privacy. + per una migliore privacy dei metadati. + No comment provided by engineer. + forwarded inoltrato @@ -8508,6 +9236,10 @@ I server di SimpleX non possono vedere il tuo profilo. ti ha rimosso/a rcv group event chat item + + requested to connect + chat list item title + saved salvato @@ -8564,7 +9296,7 @@ ultimo msg ricevuto: %2$@ set new profile picture - impostata nuova immagine del profilo + ha impostato una nuova immagine del profilo profile update event chat item @@ -8833,6 +9565,38 @@ ultimo msg ricevuto: %2$@ + +
+ +
+ + + %d new events + %d nuovi eventi + notification body + + + From: %@ + Da: %@ + notification body + + + New events + Nuovi eventi + notification + + + New messages + Nuovi messaggi + notification + + + New messages in %d chats + Nuovi messaggi in %d chat + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/it.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/it.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 a545f3ba05..72e68cff48 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,14 @@ %@ は検証されています No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded %@ アップロード済 @@ -137,6 +130,10 @@ %@ が接続を希望しています! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@や%@など%lld人のメンバー @@ -157,11 +154,31 @@ %d 日 time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d 時 time interval + + %d messages not forwarded + alert title + %d min %d 分 @@ -322,28 +339,23 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **コンタクトの追加**: 新しい招待リンクを作成するか、受け取ったリンクから接続します。 No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **新しい連絡先を追加**: 連絡先のワンタイム QR コードまたはリンクを作成します。 - No comment provided by engineer. - **Create group**: to create a new group. **グループ作成**: 新しいグループを作成する。 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **よりプライベート**: 20 分ごとに新しいメッセージを確認します。 デバイス トークンは SimpleX Chat サーバーと共有されますが、連絡先やメッセージの数は共有されません。 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **最もプライベート**: SimpleX Chat 通知サーバーを使用せず、バックグラウンドで定期的にメッセージをチェックします (アプリの使用頻度によって異なります)。 No comment provided by engineer. @@ -357,11 +369,15 @@ **注意**: パスフレーズを紛失すると、パスフレーズを復元または変更できなくなります。 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **推奨**: デバイス トークンと通知は SimpleX Chat 通知サーバーに送信されますが、メッセージの内容、サイズ、送信者は送信されません。 No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **警告**: 即時の プッシュ通知には、キーチェーンに保存されたパスフレーズが必要です。 @@ -462,6 +478,14 @@ 1週間 time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5分 @@ -531,19 +555,13 @@ アドレス変更を中止しますか? No comment provided by engineer. - - About SimpleX - SimpleXについて - No comment provided by engineer. - About SimpleX Chat SimpleX Chat について No comment provided by engineer. - - About SimpleX address - SimpleXアドレスについて + + About operators No comment provided by engineer. @@ -557,6 +575,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? 接続要求を承認? @@ -573,6 +595,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged No comment provided by engineer. @@ -590,13 +616,8 @@ プロフィールにアドレスを追加し、連絡先があなたのアドレスを他の人と共有できるようにします。プロフィールの更新は連絡先に送信されます。 No comment provided by engineer. - - Add contact - No comment provided by engineer. - - - Add preset servers - 既存サーバを追加 + + Add friends No comment provided by engineer. @@ -614,6 +635,10 @@ QRコードでサーバを追加する。 No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device 別の端末に追加 @@ -624,6 +649,18 @@ ウェルカムメッセージを追加 No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent No comment provided by engineer. @@ -646,6 +683,14 @@ アドレス変更は中止されます。古い受信アドレスが使用されます。 No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. No comment provided by engineer. @@ -679,8 +724,8 @@ 入力するとすべてのデータが消去されます。 No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. No comment provided by engineer. @@ -688,6 +733,10 @@ グループ全員の接続が継続します。 No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! No comment provided by engineer. @@ -703,7 +752,7 @@ All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -861,6 +910,11 @@ 通話に応答 No comment provided by engineer. + + Anybody can host servers. + プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。 + No comment provided by engineer. + App build: %@ アプリのビルド: %@ @@ -891,6 +945,10 @@ アプリのパスコードは自己破壊パスコードに置き換えられます。 No comment provided by engineer. + + App session + No comment provided by engineer. + App version アプリのバージョン @@ -990,6 +1048,10 @@ 画像を自動的に受信 No comment provided by engineer. + + Auto-accept settings + alert title + Back 戻る @@ -1013,10 +1075,18 @@ メッセージのハッシュ値問題 No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages より良いメッセージ @@ -1026,6 +1096,18 @@ Better networking No comment provided by engineer. + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience + No comment provided by engineer. + Black No comment provided by engineer. @@ -1096,6 +1178,14 @@ ブルガリア語、フィンランド語、タイ語、ウクライナ語 - ユーザーと [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)に感謝します! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). @@ -1144,7 +1234,8 @@ Cancel 中止 - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1162,7 +1253,7 @@ Cannot receive file ファイル受信ができません - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1177,6 +1268,10 @@ 変更 No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? データベースのパスフレーズを更新しますか? @@ -1223,9 +1318,16 @@ authentication reason set passcode view - - Chat archive - チャットのアーカイブ + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1283,8 +1385,26 @@ チャット設定 No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + ユーザープロフィール + No comment provided by engineer. + Chat theme + チャットテーマ + No comment provided by engineer. + + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! No comment provided by engineer. @@ -1292,10 +1412,18 @@ チャット No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. サーバのアドレスを確認してから再度試してください。 - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1318,10 +1446,12 @@ Chunks deleted + チャンクが削除されました No comment provided by engineer. Chunks downloaded + チャンクがダウンロードされました No comment provided by engineer. @@ -1345,6 +1475,7 @@ Clear private notes? + プライベートノートを消しますか? No comment provided by engineer. @@ -1358,6 +1489,7 @@ Color mode + 色設定 No comment provided by engineer. @@ -1372,6 +1504,43 @@ Completed + 完了 + No comment provided by engineer. + + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. No comment provided by engineer. @@ -1379,10 +1548,6 @@ ICEサーバを設定 No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm 確認 @@ -1444,10 +1609,12 @@ Connect to desktop + デスクトップに接続 No comment provided by engineer. Connect to your friends faster. + 友達ともっと速くつながりましょう。 No comment provided by engineer. @@ -1484,22 +1651,27 @@ This is your own one-time link! Connected + 接続中 No comment provided by engineer. Connected desktop + デスクトップに接続済 No comment provided by engineer. Connected servers + 接続中のサーバ No comment provided by engineer. Connected to desktop + デスクトップに接続済 No comment provided by engineer. Connecting + 接続待ち No comment provided by engineer. @@ -1514,10 +1686,12 @@ This is your own one-time link! Connecting to contact, please wait or check later! + 連絡先に接続中です。しばらくお待ちいただくか、後で確認してください! No comment provided by engineer. Connecting to desktop + デスクトップに接続中 No comment provided by engineer. @@ -1527,6 +1701,7 @@ This is your own one-time link! Connection and servers status. + 接続とサーバーのステータス No comment provided by engineer. @@ -1548,8 +1723,13 @@ This is your own one-time link! 接続リクエストを送信しました! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated + 接続停止 No comment provided by engineer. @@ -1640,6 +1820,10 @@ This is your own one-time link! コアのバージョン: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? No comment provided by engineer. @@ -1649,6 +1833,10 @@ This is your own one-time link! 作成 No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address SimpleXアドレスの作成 @@ -1658,11 +1846,6 @@ This is your own one-time link! Create a group using a random profile. No comment provided by engineer. - - Create an address to let people connect with you. - 人とつながるためのアドレスを作成する。 - No comment provided by engineer. - Create file ファイルを作成 @@ -1718,11 +1901,6 @@ This is your own one-time link! Created at: %@ copied message info - - Created on %@ - %@ によって作成されました - No comment provided by engineer. - Creating archive link No comment provided by engineer. @@ -1736,6 +1914,10 @@ This is your own one-time link! 現在のパスコード No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… 現在の暗証フレーズ… @@ -1755,8 +1937,13 @@ This is your own one-time link! カスタム時間 No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme + カスタムテーマ No comment provided by engineer. @@ -1766,6 +1953,7 @@ This is your own one-time link! Dark mode colors + ダークモードカラー No comment provided by engineer. @@ -1868,6 +2056,7 @@ This is your own one-time link! Debug delivery + 配信のデバッグ No comment provided by engineer. @@ -1883,7 +2072,8 @@ This is your own one-time link! Delete 削除 - chat item action + alert action + chat item action swipe action @@ -1918,14 +2108,8 @@ This is your own one-time link! Delete and notify contact No comment provided by engineer. - - Delete archive - アーカイブを削除 - No comment provided by engineer. - - - Delete chat archive? - チャットのアーカイブを削除しますか? + + Delete chat No comment provided by engineer. @@ -1938,6 +2122,10 @@ This is your own one-time link! チャットのプロフィールを削除しますか? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection 接続を削除する @@ -2041,6 +2229,10 @@ This is your own one-time link! 古いデータベースを削除しますか? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? 接続待ちの接続を削除しますか? @@ -2087,6 +2279,10 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery 配信 @@ -2117,6 +2313,7 @@ This is your own one-time link! Desktop devices + デスクトップ機器 No comment provided by engineer. @@ -2146,6 +2343,7 @@ This is your own one-time link! Developer options + 開発者向けの設定 No comment provided by engineer. @@ -2178,8 +2376,12 @@ This is your own one-time link! ダイレクトメッセージ chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. このグループではメンバー間のダイレクトメッセージが使用禁止です。 No comment provided by engineer. @@ -2217,8 +2419,8 @@ This is your own one-time link! このチャットでは消えるメッセージが使用禁止です。 No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. このグループでは消えるメッセージが使用禁止です。 No comment provided by engineer. @@ -2272,6 +2474,10 @@ This is your own one-time link! Do not send history to new members. No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address アドレスを作成しないでください @@ -2294,7 +2500,8 @@ This is your own one-time link! Download - chat item action + alert button + chat item action Download errors @@ -2309,6 +2516,10 @@ This is your own one-time link! ファイルをダウンロード server test step + + Download files + alert action + Downloaded No comment provided by engineer. @@ -2335,6 +2546,10 @@ This is your own one-time link! 間隔 No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit 編集する @@ -2355,6 +2570,10 @@ This is your own one-time link! 有効にする(設定の優先を維持) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock SimpleXロックを有効にする @@ -2549,26 +2768,33 @@ This is your own one-time link! アドレス変更中止エラー No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request 連絡先リクエストの承諾にエラー発生 No comment provided by engineer. - - Error accessing database file - データベースファイルへのアクセスエラー - No comment provided by engineer. - Error adding member(s) メンバー追加にエラー発生 No comment provided by engineer. + + Error adding server + alert title + Error changing address アドレス変更にエラー発生 No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role 役割変更にエラー発生 @@ -2579,6 +2805,10 @@ This is your own one-time link! 設定変更にエラー発生 No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. No comment provided by engineer. @@ -2689,9 +2919,12 @@ This is your own one-time link! グループ参加にエラー発生 No comment provided by engineer. - - Error loading %@ servers - %@ サーバーのロード中にエラーが発生 + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. @@ -2701,7 +2934,7 @@ This is your own one-time link! Error receiving file ファイル受信にエラー発生 - No comment provided by engineer. + alert title Error reconnecting server @@ -2720,11 +2953,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - %@ サーバの保存エラー - No comment provided by engineer. - Error saving ICE servers ICEサーバ保存にエラー発生 @@ -2745,6 +2973,10 @@ This is your own one-time link! キーチェーンにパスフレーズを保存にエラー発生 No comment provided by engineer. + + Error saving servers + alert title + Error saving settings when migrating @@ -2787,10 +3019,14 @@ This is your own one-time link! チャット停止にエラー発生 No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! プロフィール切り替えにエラー発生! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2807,6 +3043,10 @@ This is your own one-time link! メッセージの更新にエラー発生 No comment provided by engineer. + + Error updating server + alert title + Error updating settings 設定の更新にエラー発生 @@ -2833,8 +3073,7 @@ This is your own one-time link! Error: %@ エラー : %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2850,6 +3089,10 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. 会話中に無効になっている場合でも。 @@ -2915,6 +3158,11 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. file error text @@ -2965,8 +3213,8 @@ This is your own one-time link! ファイルとメディア chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. このグループでは、ファイルとメディアは禁止されています。 No comment provided by engineer. @@ -3032,19 +3280,51 @@ This is your own one-time link! グループメンバーによる修正はサポートされていません No comment provided by engineer. + + For chat profile %@: + servers error + For console コンソール No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward chat item action + + Forward %d message(s)? + alert title + Forward and save messages No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded No comment provided by engineer. @@ -3053,6 +3333,10 @@ This is your own one-time link! Forwarded from No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. No comment provided by engineer. @@ -3094,11 +3378,6 @@ Error: %2$@ フルネーム (任意): No comment provided by engineer. - - Full name: - フルネーム: - No comment provided by engineer. - Fully decentralized – visible only to members. No comment provided by engineer. @@ -3179,40 +3458,6 @@ Error: %2$@ グループのリンク No comment provided by engineer. - - Group members can add message reactions. - グループメンバーはメッセージへのリアクションを追加できます。 - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - グループのメンバーがメッセージを完全削除することができます。(24時間) - No comment provided by engineer. - - - Group members can send SimpleX links. - No comment provided by engineer. - - - Group members can send direct messages. - グループのメンバーがダイレクトメッセージを送信できます。 - No comment provided by engineer. - - - Group members can send disappearing messages. - グループのメンバーが消えるメッセージを送信できます。 - No comment provided by engineer. - - - Group members can send files and media. - グループメンバーはファイルやメディアを送信できます。 - No comment provided by engineer. - - - Group members can send voice messages. - グループのメンバーが音声メッセージを送信できます。 - No comment provided by engineer. - Group message: グループメッセージ: @@ -3307,9 +3552,12 @@ Error: %2$@ SimpleX の仕組み No comment provided by engineer. - - How it works - 技術の説明 + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3336,6 +3584,10 @@ Error: %2$@ ICEサーバ (1行に1サーバ) No comment provided by engineer. + + IP address + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. 直接会えない場合は、ビデオ通話で QR コードを表示するか、リンクを共有してください。 @@ -3376,8 +3628,8 @@ Error: %2$@ 即座に No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam スパムや悪質送信を防止 No comment provided by engineer. @@ -3408,6 +3660,11 @@ Error: %2$@ Importing archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery No comment provided by engineer. @@ -3503,6 +3760,11 @@ Error: %2$@ インストール [ターミナル用SimpleX Chat](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + すぐに + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3510,11 +3772,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - すぐに - No comment provided by engineer. - Interface インターフェース @@ -3556,7 +3813,7 @@ Error: %2$@ Invalid server address! 無効なサーバアドレス! - No comment provided by engineer. + alert title Invalid status @@ -3578,6 +3835,10 @@ Error: %2$@ メンバーを招待する No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group グループに招待する @@ -3593,8 +3854,8 @@ Error: %2$@ このチャットではメッセージの完全削除が使用禁止です。 No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. このグループではメッセージの完全削除が使用禁止です。 No comment provided by engineer. @@ -3677,7 +3938,7 @@ This is your link for group %@! Keep - No comment provided by engineer. + alert action Keep conversation @@ -3689,7 +3950,7 @@ This is your link for group %@! Keep unused invitation? - No comment provided by engineer. + alert title Keep your connections @@ -3726,6 +3987,14 @@ This is your link for group %@! 脱退 swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group グループを脱退 @@ -3773,11 +4042,6 @@ This is your link for group %@! ライブメッセージ No comment provided by engineer. - - Local - 自分のみ - No comment provided by engineer. - Local name ローカルネーム @@ -3798,11 +4062,6 @@ This is your link for group %@! ロックモード No comment provided by engineer. - - Make a private connection - プライベートな接続をする - No comment provided by engineer. - Make one message disappear メッセージを1つ消す @@ -3813,21 +4072,11 @@ This is your link for group %@! プロフィールを非表示にできます! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - %@ サーバー アドレスが正しい形式で、行が区切られており、重複していないことを確認してください (%@)。 - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. WebRTC ICEサーバのアドレスを正しく1行ずつに分けて、重複しないように、形式もご確認ください。 No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - 多くの人が次のような質問をしました: *SimpleX にユーザー識別子がない場合、どうやってメッセージを配信できるのですか?* - No comment provided by engineer. - Mark deleted for everyone 全員に対して削除済みマークを付ける @@ -3870,6 +4119,10 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. メンバーの役割が "%@" に変更されます。 グループメンバー全員に通知されます。 @@ -3880,11 +4133,49 @@ This is your link for group %@! メンバーの役割が "%@" に変更されます。 メンバーは新たな招待を受け取ります。 No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! メンバーをグループから除名する (※元に戻せません※)! No comment provided by engineer. + + Members can add message reactions. + グループメンバーはメッセージへのリアクションを追加できます。 + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + グループのメンバーがメッセージを完全削除することができます。(24時間) + No comment provided by engineer. + + + Members can send SimpleX links. + No comment provided by engineer. + + + Members can send direct messages. + グループのメンバーがダイレクトメッセージを送信できます。 + No comment provided by engineer. + + + Members can send disappearing messages. + グループのメンバーが消えるメッセージを送信できます。 + No comment provided by engineer. + + + Members can send files and media. + グループメンバーはファイルやメディアを送信できます。 + No comment provided by engineer. + + + Members can send voice messages. + グループのメンバーが音声メッセージを送信できます。 + No comment provided by engineer. + Menus No comment provided by engineer. @@ -3929,8 +4220,8 @@ This is your link for group %@! このチャットではメッセージへのリアクションは禁止されています。 No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. このグループではメッセージへのリアクションは禁止されています。 No comment provided by engineer. @@ -3942,6 +4233,10 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3985,12 +4280,18 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. + メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**エンドツーエンドの暗号化**によって保護されます。 No comment provided by engineer. Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery. + メッセージ、ファイル、通話は、前方秘匿性、否認可能性および侵入復元性を備えた**耐量子E2E暗号化**によって保護されます。 No comment provided by engineer. @@ -4041,9 +4342,9 @@ This is your link for group %@! 移行が完了しました No comment provided by engineer. - - Migrations: %@ - 移行: %@ + + Migrations: + 移行 No comment provided by engineer. @@ -4070,6 +4371,10 @@ This is your link for group %@! More reliable network connection. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. おそらく、この接続は削除されています。 @@ -4104,6 +4409,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. snd error text @@ -4112,6 +4421,10 @@ This is your link for group %@! Network management No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings ネットワーク設定 @@ -4127,6 +4440,14 @@ This is your link for group %@! 新しいパスコード No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat No comment provided by engineer. @@ -4145,11 +4466,6 @@ This is your link for group %@! 新しい連絡先: notification - - New database archive - 新しいデータベースのアーカイブ - No comment provided by engineer. - New desktop app! 新しいデスクトップアプリ! @@ -4160,6 +4476,10 @@ This is your link for group %@! 新たな表示名 No comment provided by engineer. + + New events + notification + New in %@ %@ の新機能 @@ -4184,6 +4504,10 @@ This is your link for group %@! 新しいパスフレーズ… No comment provided by engineer. + + New server + No comment provided by engineer. + No いいえ @@ -4237,20 +4561,62 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message 音声メッセージを録音する権限がありません No comment provided by engineer. + + No push server + 自分のみ + No comment provided by engineer. + No received or sent files 送受信済みのファイルがありません No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + 世界初のユーザーIDのないプラットフォーム|設計も元からプライベート。 + No comment provided by engineer. + Not compatible! No comment provided by engineer. @@ -4259,6 +4625,10 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + alert title + Notifications 通知 @@ -4269,6 +4639,10 @@ This is your link for group %@! 通知が無効になっています! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4290,18 +4664,13 @@ This is your link for group %@! Ok OK - No comment provided by engineer. + alert button Old database 古いデータベース No comment provided by engineer. - - Old database archive - 過去のデータベースアーカイブ - No comment provided by engineer. - One-time invitation link 使い捨ての招待リンク @@ -4326,8 +4695,12 @@ VPN を有効にする必要があります。 オニオンのホストが使われません。 No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. **2 レイヤーのエンドツーエンド暗号化**を使用して送信されたユーザー プロファイル、連絡先、グループ、メッセージを保存できるのはクライアント デバイスのみです。 No comment provided by engineer. @@ -4410,6 +4783,10 @@ VPN を有効にする必要があります。 設定を開く No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat チャットを開く @@ -4420,6 +4797,10 @@ VPN を有効にする必要があります。 チャットのコンソールを開く authentication reason + + Open conditions + No comment provided by engineer. + Open group No comment provided by engineer. @@ -4428,24 +4809,22 @@ VPN を有効にする必要があります。 Open migration to another device authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - ユーザープロフィールを開く - authentication reason - - - Open-source protocol and code – anybody can run the servers. - プロトコル技術とコードはオープンソースで、どなたでもご自分のサーバを運用できます。 - No comment provided by engineer. - Opening app… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link No comment provided by engineer. @@ -4462,13 +4841,18 @@ VPN を有効にする必要があります。 Or show this code No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4505,6 +4889,10 @@ VPN を有効にする必要があります。 パスコードを設定しました! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show パスワードを表示する @@ -4535,13 +4923,8 @@ VPN を有効にする必要があります。 Pending No comment provided by engineer. - - People can connect to you only via the links you share. - あなたと繋がることができるのは、あなたからリンクを頂いた方のみです。 - No comment provided by engineer. - - - Periodically + + Periodic 定期的に No comment provided by engineer. @@ -4641,6 +5024,10 @@ Error: %@ ポーランド語UI No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect サーバアドレスの証明証IDが正しくないかもしれません @@ -4651,16 +5038,15 @@ Error: %@ 添付を含めて、下書きを保存する。 No comment provided by engineer. - - Preset server - プレセットサーバ - No comment provided by engineer. - Preset server address プレセットサーバのアドレス No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview プレビュー @@ -4675,6 +5061,10 @@ Error: %@ プライバシーとセキュリティ No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined プライバシーの基準を新境地に @@ -4719,14 +5109,6 @@ Error: %@ Profile images No comment provided by engineer. - - Profile name - No comment provided by engineer. - - - Profile name: - No comment provided by engineer. - Profile password プロフィールのパスワード @@ -4739,7 +5121,7 @@ Error: %@ Profile update will be sent to your contacts. 連絡先にプロフィール更新のお知らせが届きます。 - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4822,6 +5204,10 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + No comment provided by engineer. + Push notifications プッシュ通知 @@ -4859,28 +5245,23 @@ Enable in *Network & servers* settings. 続きを読む 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). No comment provided by engineer. + + Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 詳しくは[ユーザーガイド](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)をご覧ください。 + 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)をご覧ください。 No comment provided by engineer. - - Read more in our GitHub repository. - GitHubリポジトリで詳細をご確認ください。 - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). - 詳しくは[GitHubリポジトリ](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)をご覧ください。 + 詳しくは[GitHubリポジトリ](https://github.com/simplex-chat/simplex-chat#readme)をご覧ください。 No comment provided by engineer. @@ -5027,6 +5408,10 @@ Enable in *Network & servers* settings. 削除 No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image No comment provided by engineer. @@ -5165,6 +5550,14 @@ Enable in *Network & servers* settings. 開示する chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke 取り消す @@ -5194,6 +5587,10 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + No comment provided by engineer. + Safely receive files No comment provided by engineer. @@ -5205,17 +5602,18 @@ Enable in *Network & servers* settings. Save 保存 - chat item action + alert button + chat item action Save (and notify contacts) 保存(連絡先に通知) - No comment provided by engineer. + alert button Save and notify contact 保存して、連絡先にに知らせる - No comment provided by engineer. + alert button Save and notify group members @@ -5231,16 +5629,6 @@ Enable in *Network & servers* settings. グループプロファイルの保存と更新 No comment provided by engineer. - - Save archive - アーカイブを保存 - No comment provided by engineer. - - - Save auto-accept settings - 自動受け入れ設定を保存する - No comment provided by engineer. - Save group profile グループプロフィールの保存 @@ -5259,7 +5647,7 @@ Enable in *Network & servers* settings. Save preferences? この設定でよろしいですか? - No comment provided by engineer. + alert title Save profile password @@ -5274,18 +5662,17 @@ Enable in *Network & servers* settings. Save servers? サーバを保存しますか? - No comment provided by engineer. - - - Save settings? - 設定を保存しますか? - No comment provided by engineer. + alert title Save welcome message? ウェルカムメッセージを保存しますか? No comment provided by engineer. + + Save your profile? + alert title + Saved No comment provided by engineer. @@ -5303,6 +5690,10 @@ Enable in *Network & servers* settings. Saved message message info title + + Saving %lld messages + No comment provided by engineer. + Scale No comment provided by engineer. @@ -5376,6 +5767,10 @@ Enable in *Network & servers* settings. 選択 chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld No comment provided by engineer. @@ -5459,11 +5854,6 @@ Enable in *Network & servers* settings. 通知を送信する No comment provided by engineer. - - Send notifications: - 通知を送信する: - No comment provided by engineer. - Send questions and ideas 質問やアイデアを送る @@ -5485,7 +5875,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. 送信者がファイル転送をキャンセルしました。 - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5571,6 +5961,14 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address No comment provided by engineer. @@ -5583,6 +5981,18 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password キューを作成するにはサーバーの認証が必要です。パスワードを確認してください @@ -5680,6 +6090,10 @@ Enable in *Network & servers* settings. 設定 No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images No comment provided by engineer. @@ -5687,22 +6101,35 @@ Enable in *Network & servers* settings. Share 共有する - chat item action + alert action + chat item action Share 1-time link 使い捨てのリンクを共有 No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address アドレスを共有する No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? アドレスを連絡先と共有しますか? - No comment provided by engineer. + alert title Share from other apps. @@ -5713,6 +6140,10 @@ Enable in *Network & servers* settings. リンクを送る No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link No comment provided by engineer. @@ -5776,6 +6207,10 @@ Enable in *Network & servers* settings. SimpleXアドレス No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. SimpleX Chat のセキュリティは Trail of Bits によって監査されました。 @@ -5806,6 +6241,14 @@ Enable in *Network & servers* settings. SimpleXアドレス No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX連絡先アドレス @@ -5826,8 +6269,8 @@ Enable in *Network & servers* settings. SimpleXリンク chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. No comment provided by engineer. @@ -5839,6 +6282,10 @@ Enable in *Network & servers* settings. SimpleX使い捨て招待リンク simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode シークレットモードの簡素化 @@ -5867,6 +6314,10 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: No comment provided by engineer. @@ -5880,6 +6331,11 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody 誰か @@ -5925,11 +6381,6 @@ Enable in *Network & servers* settings. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - チャットを停止してデータベースアクションを有効にします - 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. データベースのエクスポート、読み込み、削除するにはチャットを閉じてからです。チャットを閉じると送受信ができなくなります。 @@ -5958,12 +6409,12 @@ Enable in *Network & servers* settings. Stop sharing 共有を停止 - No comment provided by engineer. + alert action Stop sharing address? アドレスの共有を停止しますか? - No comment provided by engineer. + alert title Stopping chat @@ -5995,6 +6446,14 @@ Enable in *Network & servers* settings. Simplex Chatを支援 No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System システム @@ -6029,11 +6488,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture 写真を撮影 No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button ボタンをタップ @@ -6088,7 +6555,7 @@ Enable in *Network & servers* settings. Tests failed! テストは失敗しました! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6105,11 +6572,6 @@ Enable in *Network & servers* settings. ユーザーに感謝します – Weblate 経由で貢献してください! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - 世界初のユーザーIDのないプラットフォーム|設計も元からプライベート。 - No comment provided by engineer. - 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. @@ -6122,6 +6584,10 @@ It can happen because of some bug or when the connection is compromised.アプリは、メッセージや連絡先のリクエストを受信したときに通知することができます - 設定を開いて有効にしてください。 No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). No comment provided by engineer. @@ -6135,6 +6601,10 @@ It can happen because of some bug or when the connection is compromised.The code you scanned is not a SimpleX link QR code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! 承認済の接続がキャンセルされます! @@ -6155,6 +6625,11 @@ It can happen because of some bug or when the connection is compromised.暗号化は機能しており、新しい暗号化への同意は必要ありません。接続エラーが発生する可能性があります! No comment provided by engineer. + + The future of messaging + 次世代のプライバシー・メッセンジャー + No comment provided by engineer. + The hash of the previous message is different. 以前のメッセージとハッシュ値が異なります。 @@ -6178,11 +6653,6 @@ It can happen because of some bug or when the connection is compromised.The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - 次世代のプライバシー・メッセンジャー - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. 古いデータベースは移行時に削除されなかったので、削除することができます。 @@ -6193,6 +6663,18 @@ It can happen because of some bug or when the connection is compromised.プロフィールは連絡先にしか共有されません。 No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ 長らくお待たせしました! ✅ @@ -6208,14 +6690,26 @@ It can happen because of some bug or when the connection is compromised.現在のチャットプロフィールの新しい接続のサーバ **%@**。 No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + No comment provided by engineer. + The text you pasted is not a SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. これらの設定は現在のプロファイル **%@** 用です。 @@ -6306,9 +6800,8 @@ It can happen because of some bug or when the connection is compromised.新規に接続する場合 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. - プライバシーを保護するために、SimpleX には、他のすべてのプラットフォームで使用されるユーザー ID の代わりに、連絡先ごとに個別のメッセージ キューの識別子があります。 + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6327,6 +6820,23 @@ You will be prompted to complete authentication before this feature is enabled.< オンにするには、認証ステップが行われます。 No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + プライバシーを保護するために、SimpleX には、他のすべてのプラットフォームで使用されるユーザー ID の代わりに、連絡先ごとに個別のメッセージ キューの識別子があります。 + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. 音声メッセージを録音する場合は、マイクの使用を許可してください。 @@ -6337,11 +6847,19 @@ You will be prompted to complete authentication before this feature is enabled.< 非表示のプロフィールを表示するには、**チャット プロフィール** ページの検索フィールドに完全なパスワードを入力します。 No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. インスタント プッシュ通知をサポートするには、チャット データベースを移行する必要があります。 No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. エンドツーエンド暗号化を確認するには、ご自分の端末と連絡先の端末のコードを比べます (スキャンします)。 @@ -6421,6 +6939,10 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state 予期しない移行状態 @@ -6468,7 +6990,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6568,11 +7090,19 @@ To connect, please ask your contact to create another connection link and check Uploading archive No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts .onionホストを使う No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? SimpleX チャット サーバーを使用しますか? @@ -6588,6 +7118,14 @@ To connect, please ask your contact to create another connection link and check 現在のプロファイルを使用する No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections 新しい接続に使う @@ -6624,6 +7162,10 @@ To connect, please ask your contact to create another connection link and check サーバを使う No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. No comment provided by engineer. @@ -6632,15 +7174,14 @@ To connect, please ask your contact to create another connection link and check Use the app with one hand. No comment provided by engineer. - - User profile - ユーザープロフィール - No comment provided by engineer. - User selection No comment provided by engineer. + + Username + No comment provided by engineer. + Using SimpleX Chat servers. SimpleX チャット サーバーを使用する。 @@ -6705,11 +7246,19 @@ To connect, please ask your contact to create another connection link and check 1GBまでのビデオとファイル No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code セキュリティコードを確認 No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history chat feature @@ -6724,8 +7273,8 @@ To connect, please ask your contact to create another connection link and check このチャットでは音声メッセージが使用禁止です。 No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. このグループでは音声メッセージが使用禁止です。 No comment provided by engineer. @@ -6812,9 +7361,8 @@ To connect, please ask your contact to create another connection link and check When connecting audio and video calls. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - 接続が要求されたら、それを受け入れるか拒否するかを選択できます。 + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -6853,7 +7401,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -6877,11 +7425,6 @@ To connect, please ask your contact to create another connection link and check XFTP server No comment provided by engineer. - - You - あなた - No comment provided by engineer. - You **must not** use the same database on two devices. No comment provided by engineer. @@ -6906,6 +7449,10 @@ To connect, please ask your contact to create another connection link and check すでに %@ に接続されています。 No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. No comment provided by engineer. @@ -6958,6 +7505,14 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + No comment provided by engineer. + You can create it later 後からでも作成できます @@ -6995,6 +7550,10 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. 設定からロック画面の通知プレビューを設定できます。 @@ -7010,11 +7569,6 @@ Repeat join request? このアドレスを連絡先と共有して、**%@** に接続できるようにすることができます。 No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - アドレスをリンクやQRコードとして共有することで、誰でも接続することができます。 - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app アプリの設定/データベースから、またはアプリを再起動することでチャットを開始できます @@ -7036,23 +7590,23 @@ Repeat join request? You can view invitation link again in connection details. - No comment provided by engineer. + alert message You can't send messages! メッセージを送信できませんでした! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - あなたはメッセージの受信に使用するサーバーを制御し、連絡先はあなたがメッセージの送信に使用するサーバーを使用することができます。 - No comment provided by engineer. - You could not be verified; please try again. 確認できませんでした。 もう一度お試しください。 No comment provided by engineer. + + You decide who can connect. + あなたと繋がることができるのは、あなたからリンクを頂いた方のみです。 + No comment provided by engineer. + You have already requested connection via this address! No comment provided by engineer. @@ -7147,6 +7701,10 @@ Repeat connection request? ミュートされたプロフィールがアクティブな場合でも、そのプロフィールからの通話や通知は引き続き受信します。 No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. このグループからのメッセージが届かなくなります。チャットの履歴が残ります。 @@ -7167,11 +7725,6 @@ Repeat connection request? シークレットモードのプロフィールでこのグループに参加しています。メインのプロフィールを守るために、招待することができません No comment provided by engineer. - - Your %@ servers - あなたの %@ サーバー - No comment provided by engineer. - Your ICE servers あなたのICEサーバ @@ -7187,11 +7740,6 @@ Repeat connection request? あなたのSimpleXアドレス No comment provided by engineer. - - Your XFTP servers - あなたのXFTPサーバ - No comment provided by engineer. - Your calls あなたの通話 @@ -7207,11 +7755,19 @@ Repeat connection request? チャット データベースは暗号化されていません - 暗号化するにはパスフレーズを設定してください。 No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles あなたのチャットプロフィール No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). 連絡先が現在サポートされている最大サイズ (%@) より大きいファイルを送信しました。 @@ -7227,6 +7783,10 @@ Repeat connection request? 連絡先は接続されたままになります。 No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. 現在のチャット データベースは削除され、インポートされたデータベースに置き換えられます。 @@ -7256,13 +7816,15 @@ Repeat connection request? あなたのプロファイル **%@** が共有されます。 No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - プロフィールはデバイスに保存され、連絡先とのみ共有されます。 -SimpleX サーバーはあなたのプロファイルを参照できません。 + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + プロフィールはデバイスに保存され、連絡先とのみ共有されます。 SimpleX サーバーはあなたのプロファイルを参照できません。 No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。 @@ -7273,16 +7835,15 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 あなたのランダム・プロフィール No comment provided by engineer. - - Your server - あなたのサーバ - No comment provided by engineer. - Your server address あなたのサーバアドレス No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings あなたの設定 @@ -7323,6 +7884,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 受けた通話 call status + + accepted invitation + chat list item title + admin 管理者 @@ -7501,7 +8066,7 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 connecting… 接続待ち… - chat list item title + No comment provided by engineer. connection established @@ -7688,6 +8253,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 expired No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded No comment provided by engineer. @@ -7973,6 +8542,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。 あなたを除名しました rcv group event chat item + + requested to connect + chat list item title + saved No comment provided by engineer. @@ -8275,6 +8848,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/ja.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - diff --git a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff index 511536427d..9aaa83afc3 100644 --- a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff +++ b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff @@ -152,20 +152,16 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - No comment provided by engineer. - **Create link / QR code** for your contact to use. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. No comment provided by engineer. @@ -176,8 +172,8 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. No comment provided by engineer. @@ -1013,8 +1009,8 @@ Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1029,8 +1025,8 @@ Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1421,16 +1417,16 @@ Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1537,8 +1533,8 @@ Image will be received when your contact is online, please wait or check later! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1642,8 +1638,8 @@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -1961,8 +1957,8 @@ We will be adding server redundancy to prevent lost messages. Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2013,8 +2009,8 @@ We will be adding server redundancy to prevent lost messages. Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2049,8 +2045,8 @@ We will be adding server redundancy to prevent lost messages. Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -2670,8 +2666,8 @@ We will be adding server redundancy to prevent lost messages. Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -2706,8 +2702,8 @@ We will be adding server redundancy to prevent lost messages. The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -2774,8 +2770,8 @@ We will be adding server redundancy to prevent lost messages. To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -2968,8 +2964,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -3093,10 +3089,6 @@ SimpleX Lock must be enabled. You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff index 6df24149e9..54a713478f 100644 --- a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff +++ b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff @@ -162,20 +162,16 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - No comment provided by engineer. - **Create link / QR code** for your contact to use. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. No comment provided by engineer. @@ -187,8 +183,8 @@ **Turėkite omenyje**: jeigu prarasite slaptafrazę, NEBEGALĖSITE jos atkurti ar pakeisti. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. No comment provided by engineer. @@ -1033,8 +1029,8 @@ Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1049,8 +1045,8 @@ Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1417,16 +1413,16 @@ Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1513,8 +1509,8 @@ Image will be received when your contact is online, please wait or check later! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1614,8 +1610,8 @@ Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -1919,8 +1915,8 @@ We will be adding server redundancy to prevent lost messages. Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -1971,8 +1967,8 @@ We will be adding server redundancy to prevent lost messages. Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2003,8 +1999,8 @@ We will be adding server redundancy to prevent lost messages. Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -2591,8 +2587,8 @@ We will be adding server redundancy to prevent lost messages. Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -2627,8 +2623,8 @@ We will be adding server redundancy to prevent lost messages. The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -2687,8 +2683,8 @@ We will be adding server redundancy to prevent lost messages. To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -2873,8 +2869,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -2993,10 +2989,6 @@ To connect, please ask your contact to create another connection link and check You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. 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 dfec7b0b05..ab3499a4dc 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ is geverifieerd No comment provided by engineer. + + %@ server + %@ server + No comment provided by engineer. + + + %@ servers + %@ servers + No comment provided by engineer. + %@ uploaded %@ geüpload @@ -137,6 +132,11 @@ %@ wil verbinding maken! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ en %lld leden @@ -157,11 +157,36 @@ %d dagen time interval + + %d file(s) are still being downloaded. + %d bestand(en) worden nog gedownload. + forward confirmation reason + + + %d file(s) failed to download. + %d bestand(en) konden niet worden gedownload. + forward confirmation reason + + + %d file(s) were deleted. + %d bestand(en) zijn verwijderd. + forward confirmation reason + + + %d file(s) were not downloaded. + %d bestand(en) zijn niet gedownload. + forward confirmation reason + %d hours %d uren time interval + + %d messages not forwarded + %d berichten niet doorgestuurd + alert title + %d min %d min @@ -322,28 +347,23 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **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 or link for your contact. - **Nieuw contact toevoegen**: om uw eenmalige QR-code of link voor uw contact te maken. - No comment provided by engineer. - **Create group**: to create a new group. **Groep aanmaken**: om een nieuwe groep aan te maken. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Meer privé**: bekijk elke 20 minuten nieuwe berichten. Apparaattoken wordt gedeeld met de SimpleX Chat-server, maar niet hoeveel contacten of berichten u heeft. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +377,16 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received. + **Link scannen/plakken**: om verbinding te maken via een link die u hebt ontvangen. + 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. @@ -468,6 +493,16 @@ 1 week time interval + + 1-time link + Eenmalige link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Eenmalige link die *slechts met één contactpersoon* kan worden gebruikt - deel persoonlijk of via een messenger. + No comment provided by engineer. + 5 minutes 5 minuten @@ -512,7 +547,7 @@ A separate TCP connection will be used **for each chat profile you have in the app**. - Er wordt een aparte TCP-verbinding gebruikt **voor elk chat profiel dat je in de app hebt**. + Er wordt een aparte TCP-verbinding gebruikt **voor elk chatprofiel dat je in de app hebt**. No comment provided by engineer. @@ -537,19 +572,14 @@ Adres wijziging afbreken? No comment provided by engineer. - - About SimpleX - Over SimpleX - No comment provided by engineer. - About SimpleX Chat Over SimpleX Chat No comment provided by engineer. - - About SimpleX address - Over SimpleX adres + + About operators + Over operatoren No comment provided by engineer. @@ -564,6 +594,11 @@ accept incoming call via notification swipe action + + Accept conditions + Accepteer voorwaarden + No comment provided by engineer. + Accept connection request? Accepteer contact @@ -580,6 +615,11 @@ accept contact request via notification swipe action + + Accepted conditions + Geaccepteerde voorwaarden + No comment provided by engineer. + Acknowledged Erkend @@ -600,14 +640,9 @@ 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 + + Add friends + Vrienden toevoegen No comment provided by engineer. @@ -625,6 +660,11 @@ Servers toevoegen door QR-codes te scannen. No comment provided by engineer. + + Add team members + Teamleden toevoegen + No comment provided by engineer. + Add to another device Toevoegen aan een ander apparaat @@ -635,6 +675,21 @@ Welkom bericht toevoegen No comment provided by engineer. + + Add your team members to the conversations. + Voeg uw teamleden toe aan de gesprekken. + No comment provided by engineer. + + + Added media & file servers + Media- en bestandsservers toegevoegd + No comment provided by engineer. + + + Added message servers + Berichtservers toegevoegd + No comment provided by engineer. + Additional accent Extra accent @@ -660,6 +715,16 @@ Adres wijziging wordt afgebroken. Het oude ontvangstadres wordt gebruikt. No comment provided by engineer. + + Address or 1-time link? + Adres of eenmalige link? + No comment provided by engineer. + + + Address settings + Adres instellingen + No comment provided by engineer. + Admins can block a member for all. Beheerders kunnen een lid voor iedereen blokkeren. @@ -695,8 +760,8 @@ Alle gegevens worden bij het invoeren gewist. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Alle gegevens zijn privé op uw apparaat. No comment provided by engineer. @@ -705,6 +770,11 @@ Alle groepsleden blijven verbonden. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Alle berichten en bestanden worden **end-to-end versleuteld** verzonden, met post-quantumbeveiliging in directe berichten. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Alle berichten worden verwijderd. Dit kan niet ongedaan worden gemaakt! @@ -723,7 +793,7 @@ All profiles Alle profielen - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -767,7 +837,7 @@ 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) + Sta het definitief verwijderen van berichten alleen toe als uw contact dit toestaat. (24 uur) No comment provided by engineer. @@ -797,7 +867,7 @@ Allow to irreversibly delete sent messages. (24 hours) - Sta toe om verzonden berichten onomkeerbaar te verwijderen. (24 uur) + Sta toe om verzonden berichten definitief te verwijderen. (24 uur) No comment provided by engineer. @@ -837,7 +907,7 @@ Allow your contacts to irreversibly delete sent messages. (24 hours) - Laat uw contacten verzonden berichten onomkeerbaar verwijderen. (24 uur) + Laat uw contacten verzonden berichten definitief verwijderen. (24 uur) No comment provided by engineer. @@ -885,6 +955,11 @@ Beantwoord oproep No comment provided by engineer. + + Anybody can host servers. + Iedereen kan servers hosten. + No comment provided by engineer. + App build: %@ App build: %@ @@ -915,6 +990,11 @@ De app-toegangscode wordt vervangen door een zelfvernietigings wachtwoord. No comment provided by engineer. + + App session + Appsessie + No comment provided by engineer. + App version App versie @@ -982,7 +1062,7 @@ Audio/video calls are prohibited. - Audio/video gesprekken zijn verboden. + Audio/video gesprekken zijn niet toegestaan. No comment provided by engineer. @@ -1020,6 +1100,11 @@ Afbeeldingen automatisch accepteren No comment provided by engineer. + + Auto-accept settings + Instellingen automatisch accepteren + alert title + Back Terug @@ -1045,11 +1130,21 @@ Onjuiste bericht hash No comment provided by engineer. + + Better calls + Betere gesprekken + No comment provided by engineer. + Better groups Betere groepen No comment provided by engineer. + + Better message dates. + Betere datums voor berichten. + No comment provided by engineer. + Better messages Betere berichten @@ -1060,6 +1155,21 @@ Beter netwerk No comment provided by engineer. + + Better notifications + Betere meldingen + No comment provided by engineer. + + + Better security ✅ + Betere beveiliging ✅ + No comment provided by engineer. + + + Better user experience + Betere gebruikerservaring + No comment provided by engineer. + Black Zwart @@ -1140,9 +1250,19 @@ Bulgaars, Fins, Thais en Oekraïens - dankzij de gebruikers en [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Zakelijk adres + No comment provided by engineer. + + + Business chats + Zakelijke chats + 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). - Via chat profiel (standaard) of [via verbinding](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). + Via chatprofiel (standaard) of [via verbinding](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). No comment provided by engineer. @@ -1157,7 +1277,7 @@ Calls prohibited! - Bellen verboden! + Bellen niet toegestaan! No comment provided by engineer. @@ -1193,7 +1313,8 @@ Cancel Annuleren - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1334,7 @@ Cannot receive file Kan bestand niet ontvangen - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1351,11 @@ Veranderen No comment provided by engineer. + + Change chat profiles + Gebruikersprofielen wijzigen + authentication reason + Change database passphrase? Wachtwoord database wijzigen? @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Gesprek archief + + Chat + Chat + No comment provided by engineer. + + + Chat already exists + Chat bestaat al + No comment provided by engineer. + + + Chat already exists! + Chat bestaat al! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Gesprek voorkeuren No comment provided by engineer. + + Chat preferences were changed. + Chatvoorkeuren zijn gewijzigd. + alert message + + + Chat profile + Gebruikers profiel + No comment provided by engineer. + Chat theme Chat thema No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + De chat wordt voor alle leden verwijderd - dit kan niet ongedaan worden gemaakt! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + De chat wordt voor je verwijderd - dit kan niet ongedaan worden gemaakt! + No comment provided by engineer. + Chats - Gesprekken + Chats + No comment provided by engineer. + + + Check messages every 20 min. + Controleer uw berichten elke 20 minuten. + No comment provided by engineer. + + + Check messages when allowed. + Controleer berichten indien toegestaan. No comment provided by engineer. Check server address and try again. Controleer het server adres en probeer het opnieuw. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1438,7 +1604,52 @@ Completed - voltooid + Voltooid + No comment provided by engineer. + + + Conditions accepted on: %@. + Voorwaarden geaccepteerd op: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Voorwaarden worden geaccepteerd voor de operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Voorwaarden zijn reeds geaccepteerd voor de volgende operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + Gebruiksvoorwaarden + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Voor ingeschakelde operators worden de voorwaarden na 30 dagen geaccepteerd. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Voorwaarden worden geaccepteerd voor operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Voorwaarden worden geaccepteerd voor de operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Voorwaarden worden geaccepteerd op: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Voorwaarden worden automatisch geaccepteerd voor ingeschakelde operators op: %@. No comment provided by engineer. @@ -1446,11 +1657,6 @@ ICE servers configureren No comment provided by engineer. - - Configured %@ servers - %@ servers geconfigureerd - No comment provided by engineer. - Confirm Bevestigen @@ -1640,6 +1846,11 @@ Dit is uw eigen eenmalige link! Verbindingsverzoek verzonden! No comment provided by engineer. + + Connection security + Beveiliging van de verbinding + No comment provided by engineer. + Connection terminated Verbinding beëindigd @@ -1740,6 +1951,11 @@ Dit is uw eigen eenmalige link! Core versie: v% @ No comment provided by engineer. + + Corner + Hoek + No comment provided by engineer. + Correct name to %@? Juiste naam voor %@? @@ -1750,6 +1966,11 @@ Dit is uw eigen eenmalige link! Maak No comment provided by engineer. + + Create 1-time link + Eenmalige link maken + No comment provided by engineer. + Create SimpleX address Maak een SimpleX adres aan @@ -1760,11 +1981,6 @@ Dit is uw eigen eenmalige link! Maak een groep met een willekeurig profiel. No comment provided by engineer. - - Create an address to let people connect with you. - Maak een adres aan zodat mensen contact met je kunnen opnemen. - No comment provided by engineer. - Create file Bestand maken @@ -1825,11 +2041,6 @@ Dit is uw eigen eenmalige link! Aangemaakt op: %@ copied message info - - Created on %@ - Gemaakt op %@ - No comment provided by engineer. - Creating archive link Archief link maken @@ -1845,6 +2056,11 @@ Dit is uw eigen eenmalige link! Huidige toegangscode No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + De tekst van de huidige voorwaarden kon niet worden geladen. U kunt de voorwaarden bekijken via deze link: + No comment provided by engineer. + Current passphrase… Huidige wachtwoord… @@ -1865,6 +2081,11 @@ Dit is uw eigen eenmalige link! Aangepaste tijd No comment provided by engineer. + + Customizable message shape. + Aanpasbare berichtvorm. + No comment provided by engineer. + Customize theme Thema aanpassen @@ -1951,7 +2172,7 @@ Dit is uw eigen eenmalige link! Database passphrase is required to open chat. - Database wachtwoord is vereist om je gesprekken te openen. + Database wachtwoord is vereist om je chats te openen. No comment provided by engineer. @@ -1996,7 +2217,8 @@ Dit is uw eigen eenmalige link! Delete Verwijderen - chat item action + alert action + chat item action swipe action @@ -2034,24 +2256,24 @@ Dit is uw eigen eenmalige link! Verwijderen en contact op de hoogte stellen No comment provided by engineer. - - Delete archive - Archief verwijderen - No comment provided by engineer. - - - Delete chat archive? - Chat archief verwijderen? + + Delete chat + Chat verwijderen No comment provided by engineer. Delete chat profile - Chat profiel verwijderen + Chatprofiel verwijderen No comment provided by engineer. Delete chat profile? - Chat profiel verwijderen? + Chatprofiel verwijderen? + No comment provided by engineer. + + + Delete chat? + Chat verwijderen? No comment provided by engineer. @@ -2091,7 +2313,7 @@ Dit is uw eigen eenmalige link! Delete files for all chat profiles - Verwijder bestanden voor alle chat profielen + Verwijder bestanden voor alle chatprofielen No comment provided by engineer. @@ -2159,6 +2381,11 @@ Dit is uw eigen eenmalige link! Oude database verwijderen? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Maximaal 200 berichten verwijderen of modereren. + No comment provided by engineer. + Delete pending connection? Wachtende verbinding verwijderen? @@ -2209,6 +2436,11 @@ Dit is uw eigen eenmalige link! Verwijderingsfouten No comment provided by engineer. + + Delivered even when Apple drops them. + Geleverd ook als Apple ze verliest + No comment provided by engineer. + Delivery Bezorging @@ -2309,9 +2541,14 @@ Dit is uw eigen eenmalige link! Directe berichten chat feature - - Direct messages between members are prohibited in this group. - Directe berichten tussen leden zijn verboden in deze groep. + + Direct messages between members are prohibited in this chat. + Directe berichten tussen leden zijn in deze chat niet toegestaan. + No comment provided by engineer. + + + Direct messages between members are prohibited. + Directe berichten tussen leden zijn niet toegestaan. No comment provided by engineer. @@ -2346,12 +2583,12 @@ Dit is uw eigen eenmalige link! Disappearing messages are prohibited in this chat. - Verdwijnende berichten zijn verboden in dit gesprek. + Verdwijnende berichten zijn niet toegestaan in dit gesprek. No comment provided by engineer. - - Disappearing messages are prohibited in this group. - Verdwijnende berichten zijn verboden in deze groep. + + Disappearing messages are prohibited. + Verdwijnende berichten zijn niet toegestaan. No comment provided by engineer. @@ -2409,6 +2646,11 @@ Dit is uw eigen eenmalige link! Stuur geen geschiedenis naar nieuwe leden. No comment provided by engineer. + + Do not use credentials with proxy. + Gebruik geen inloggegevens met proxy. + No comment provided by engineer. + Don't create address Maak geen adres aan @@ -2432,7 +2674,8 @@ Dit is uw eigen eenmalige link! Download Downloaden - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ Dit is uw eigen eenmalige link! Download bestand server test step + + Download files + ‐Bestanden downloaden + alert action + Downloaded Gedownload @@ -2479,6 +2727,11 @@ Dit is uw eigen eenmalige link! Duur No comment provided by engineer. + + E2E encrypted notifications. + E2E versleutelde meldingen. + No comment provided by engineer. + Edit Bewerk @@ -2499,6 +2752,11 @@ Dit is uw eigen eenmalige link! Inschakelen (overschrijvingen behouden) No comment provided by engineer. + + Enable Flux + Flux inschakelen + No comment provided by engineer. + Enable SimpleX Lock SimpleX Vergrendelen inschakelen @@ -2704,26 +2962,36 @@ Dit is uw eigen eenmalige link! Fout bij het afbreken van adres wijziging No comment provided by engineer. + + Error accepting conditions + Fout bij het accepteren van voorwaarden + alert title + Error accepting contact request Fout bij het accepteren van een contactverzoek No comment provided by engineer. - - Error accessing database file - Fout bij toegang tot database bestand - No comment provided by engineer. - Error adding member(s) Fout bij het toevoegen van leden No comment provided by engineer. + + Error adding server + Fout bij toevoegen server + alert title + Error changing address Fout bij wijzigen van adres No comment provided by engineer. + + Error changing connection profile + Fout bij wijzigen van verbindingsprofiel + No comment provided by engineer. + Error changing role Fout bij wisselen van rol @@ -2734,6 +3002,11 @@ Dit is uw eigen eenmalige link! Fout bij wijzigen van instelling No comment provided by engineer. + + Error changing to incognito! + Fout bij het overschakelen naar incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Fout bij het verbinden met doorstuurserver %@. Probeer het later opnieuw. @@ -2849,9 +3122,14 @@ Dit is uw eigen eenmalige link! Fout bij lid worden van groep No comment provided by engineer. - - Error loading %@ servers - Fout bij het laden van %@ servers + + Error loading servers + Fout bij het laden van servers + alert title + + + Error migrating settings + Fout bij migreren van instellingen No comment provided by engineer. @@ -2862,7 +3140,7 @@ Dit is uw eigen eenmalige link! Error receiving file Fout bij ontvangen van bestand - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3162,6 @@ Dit is uw eigen eenmalige link! Fout bij het resetten van statistieken No comment provided by engineer. - - Error saving %@ servers - Fout bij opslaan van %@ servers - No comment provided by engineer. - Error saving ICE servers Fout bij opslaan van ICE servers @@ -2909,6 +3182,11 @@ Dit is uw eigen eenmalige link! Fout bij opslaan van wachtwoord in de keychain No comment provided by engineer. + + Error saving servers + Fout bij het opslaan van servers + alert title + Error saving settings Fout bij opslaan van instellingen @@ -2954,10 +3232,15 @@ Dit is uw eigen eenmalige link! Fout bij het stoppen van de chat No comment provided by engineer. + + Error switching profile + Fout bij wisselen van profiel + No comment provided by engineer. + Error switching profile! Fout bij wisselen van profiel! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3257,11 @@ Dit is uw eigen eenmalige link! Fout bij updaten van bericht No comment provided by engineer. + + Error updating server + Fout bij het updaten van de server + alert title + Error updating settings Fout bij bijwerken van instellingen @@ -3002,8 +3290,7 @@ Dit is uw eigen eenmalige link! Error: %@ Fout: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3307,11 @@ Dit is uw eigen eenmalige link! Fouten No comment provided by engineer. + + Errors in servers configuration. + Fouten in de serverconfiguratie. + servers error + Even when disabled in the conversation. Zelfs wanneer uitgeschakeld in het gesprek. @@ -3090,6 +3382,13 @@ Dit is uw eigen eenmalige link! Bestandsfout No comment provided by engineer. + + File errors: +%@ + Bestandsfouten: +%@ + alert message + File not found - most likely file was deleted or cancelled. Bestand niet gevonden - hoogstwaarschijnlijk is het bestand verwijderd of geannuleerd. @@ -3145,9 +3444,9 @@ Dit is uw eigen eenmalige link! Bestanden en media chat feature - - Files and media are prohibited in this group. - Bestanden en media zijn verboden in deze groep. + + Files and media are prohibited. + Bestanden en media zijn niet toegestaan. No comment provided by engineer. @@ -3157,7 +3456,7 @@ Dit is uw eigen eenmalige link! Files and media prohibited! - Bestanden en media verboden! + Bestanden en media niet toegestaan! No comment provided by engineer. @@ -3182,7 +3481,7 @@ Dit is uw eigen eenmalige link! Find chats faster - Vind gesprekken sneller + Vind chats sneller No comment provided by engineer. @@ -3215,21 +3514,61 @@ Dit is uw eigen eenmalige link! Herstel wordt niet ondersteund door groepslid No comment provided by engineer. + + For chat profile %@: + Voor chatprofiel %@: + servers error + For console Voor console No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Als uw contactpersoon bijvoorbeeld berichten ontvangt via een SimpleX Chat-server, worden deze door uw app via een Flux-server verzonden. + No comment provided by engineer. + + + For private routing + Voor privé-routering + No comment provided by engineer. + + + For social media + Voor social media + No comment provided by engineer. + Forward Doorsturen chat item action + + Forward %d message(s)? + %d bericht(en) doorsturen? + alert title + Forward and save messages Berichten doorsturen en opslaan No comment provided by engineer. + + Forward messages + Berichten doorsturen + alert action + + + Forward messages without files? + Berichten doorsturen zonder bestanden? + alert message + + + Forward up to 20 messages at once. + Stuur maximaal 20 berichten tegelijk door. + No comment provided by engineer. + Forwarded Doorgestuurd @@ -3240,6 +3579,11 @@ Dit is uw eigen eenmalige link! Doorgestuurd vanuit No comment provided by engineer. + + Forwarding %lld messages + %lld berichten doorsturen + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. De doorstuurserver %@ kon geen verbinding maken met de bestemmingsserver %@. Probeer het later opnieuw. @@ -3289,11 +3633,6 @@ Fout: %2$@ Volledige naam (optioneel) No comment provided by engineer. - - Full name: - Volledige naam: - No comment provided by engineer. - Fully decentralized – visible only to members. Volledig gedecentraliseerd – alleen zichtbaar voor leden. @@ -3379,41 +3718,6 @@ Fout: %2$@ Groep links No comment provided by engineer. - - Group members can add message reactions. - Groepsleden kunnen bericht reacties toevoegen. - No comment provided by engineer. - - - 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 SimpleX links. - Groepsleden kunnen SimpleX-links verzenden. - No comment provided by engineer. - - - Group members can send direct messages. - Groepsleden kunnen directe berichten sturen. - No comment provided by engineer. - - - Group members can send disappearing messages. - Groepsleden kunnen verdwijnende berichten sturen. - No comment provided by engineer. - - - Group members can send files and media. - Groepsleden kunnen bestanden en media verzenden. - No comment provided by engineer. - - - Group members can send voice messages. - Groepsleden kunnen spraak berichten verzenden. - No comment provided by engineer. - Group message: Groep bericht: @@ -3466,7 +3770,7 @@ Fout: %2$@ Hidden chat profiles - Verborgen chat profielen + Verborgen chatprofielen No comment provided by engineer. @@ -3509,9 +3813,14 @@ Fout: %2$@ Hoe SimpleX werkt No comment provided by engineer. - - How it works - Hoe het werkt + + How it affects privacy + Hoe het de privacy beïnvloedt + No comment provided by engineer. + + + How it helps privacy + Hoe het de privacy helpt No comment provided by engineer. @@ -3539,6 +3848,11 @@ Fout: %2$@ ICE servers (één per lijn) No comment provided by engineer. + + IP address + IP-adres + 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. @@ -3546,7 +3860,7 @@ Fout: %2$@ 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! + Als u deze toegangscode invoert bij het openen van de app, worden alle app-gegevens definitief verwijderd! No comment provided by engineer. @@ -3579,8 +3893,8 @@ Fout: %2$@ Onmiddellijk No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Immuun voor spam en misbruik No comment provided by engineer. @@ -3614,6 +3928,13 @@ Fout: %2$@ Archief importeren No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Verbeterde levering, minder data gebruik. +Binnenkort meer verbeteringen! + No comment provided by engineer. + Improved message delivery Verbeterde berichtbezorging @@ -3714,6 +4035,11 @@ Fout: %2$@ Installeer [SimpleX Chat voor terminal](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Direct + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4047,6 @@ Fout: %2$@ No comment provided by engineer. - - Instantly - Direct - No comment provided by engineer. - Interface Interface @@ -3774,7 +4095,7 @@ Fout: %2$@ Invalid server address! Ongeldig server adres! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4117,11 @@ Fout: %2$@ Nodig leden uit No comment provided by engineer. + + Invite to chat + Uitnodigen voor een chat + No comment provided by engineer. + Invite to group Uitnodigen voor groep @@ -3808,17 +4134,17 @@ Fout: %2$@ Irreversible message deletion is prohibited in this chat. - Het onomkeerbaar verwijderen van berichten is verboden in dit gesprek. + Het definitief verwijderen van berichten is niet toegestaan in dit gesprek. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. - Het onomkeerbaar verwijderen van berichten is verboden in deze groep. + + Irreversible message deletion is prohibited. + Het definitief verwijderen van berichten is verbHet definitief verwijderen van berichten is niet toegestaan.. No comment provided by engineer. It allows having many anonymous connections without any shared data between them in a single chat profile. - Het maakt het mogelijk om veel anonieme verbindingen te hebben zonder enige gedeelde gegevens tussen hen in een enkel chat profiel. + Het maakt het mogelijk om veel anonieme verbindingen te hebben zonder enige gedeelde gegevens tussen hen in een enkel chatprofiel. No comment provided by engineer. @@ -3902,11 +4228,11 @@ Dit is jouw link voor groep %@! Keep Bewaar - No comment provided by engineer. + alert action Keep conversation - Blijf in gesprek + Behoud het gesprek No comment provided by engineer. @@ -3917,7 +4243,7 @@ Dit is jouw link voor groep %@! Keep unused invitation? Ongebruikte uitnodiging bewaren? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4280,16 @@ Dit is jouw link voor groep %@! Verlaten swipe action + + Leave chat + Chat verlaten + No comment provided by engineer. + + + Leave chat? + Chat verlaten? + No comment provided by engineer. + Leave group Groep verlaten @@ -4004,11 +4340,6 @@ Dit is jouw link voor groep %@! Live berichten No comment provided by engineer. - - Local - Lokaal - No comment provided by engineer. - Local name Lokale naam @@ -4029,11 +4360,6 @@ Dit is jouw link voor groep %@! Vergrendeling modus No comment provided by engineer. - - Make a private connection - Maak een privéverbinding - No comment provided by engineer. - Make one message disappear Eén bericht laten verdwijnen @@ -4044,21 +4370,11 @@ Dit is jouw link voor groep %@! Profiel privé maken! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Zorg ervoor dat %@ server adressen de juiste indeling hebben, regel gescheiden zijn en niet gedupliceerd zijn (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Zorg ervoor dat WebRTC ICE server adressen de juiste indeling hebben, regel gescheiden zijn en niet gedupliceerd zijn. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Veel mensen vroegen: *als SimpleX geen gebruikers-ID's heeft, hoe kan het dan berichten bezorgen?* - No comment provided by engineer. - Mark deleted for everyone Markeer verwijderd voor iedereen @@ -4104,6 +4420,11 @@ Dit is jouw link voor groep %@! Lid inactief item status text + + Member role will be changed to "%@". All chat members will be notified. + De rol van het lid wordt gewijzigd naar "%@". Alle chatleden worden op de hoogte gebracht. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. De rol van lid wordt gewijzigd in "%@". Alle groepsleden worden op de hoogte gebracht. @@ -4114,11 +4435,51 @@ Dit is jouw link voor groep %@! De rol van lid wordt gewijzigd in "%@". Het lid ontvangt een nieuwe uitnodiging. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + Lid wordt verwijderd uit de chat - dit kan niet ongedaan worden gemaakt! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Lid wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt! No comment provided by engineer. + + Members can add message reactions. + Groepsleden kunnen bericht reacties toevoegen. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Groepsleden kunnen verzonden berichten onherroepelijk verwijderen. (24 uur) + No comment provided by engineer. + + + Members can send SimpleX links. + Groepsleden kunnen SimpleX-links verzenden. + No comment provided by engineer. + + + Members can send direct messages. + Groepsleden kunnen directe berichten sturen. + No comment provided by engineer. + + + Members can send disappearing messages. + Groepsleden kunnen verdwijnende berichten sturen. + No comment provided by engineer. + + + Members can send files and media. + Groepsleden kunnen bestanden en media verzenden. + No comment provided by engineer. + + + Members can send voice messages. + Groepsleden kunnen spraak berichten verzenden. + No comment provided by engineer. + Menus Menu's @@ -4166,12 +4527,12 @@ Dit is jouw link voor groep %@! Message reactions are prohibited in this chat. - Reacties op berichten zijn verboden in deze chat. + Reacties op berichten zijn niet toegestaan in deze chat. No comment provided by engineer. - - Message reactions are prohibited in this group. - Reacties op berichten zijn verboden in deze groep. + + Message reactions are prohibited. + Reacties op berichten zijn niet toegestaan. No comment provided by engineer. @@ -4184,6 +4545,11 @@ Dit is jouw link voor groep %@! Berichtservers No comment provided by engineer. + + Message shape + Berichtvorm + No comment provided by engineer. + Message source remains private. Berichtbron blijft privé. @@ -4234,6 +4600,11 @@ Dit is jouw link voor groep %@! Berichten verzonden No comment provided by engineer. + + Messages were deleted after you selected them. + Berichten zijn verwijderd nadat u ze had geselecteerd. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Berichten, bestanden en oproepen worden beschermd door **end-to-end codering** met perfecte voorwaartse geheimhouding, afwijzing en inbraakherstel. @@ -4299,9 +4670,9 @@ Dit is jouw link voor groep %@! Migratie is voltooid No comment provided by engineer. - - Migrations: %@ - Migraties: %@ + + Migrations: + Migraties: No comment provided by engineer. @@ -4329,6 +4700,11 @@ Dit is jouw link voor groep %@! Betrouwbaardere netwerkverbinding. No comment provided by engineer. + + More reliable notifications + Betrouwbaardere meldingen + No comment provided by engineer. + Most likely this connection is deleted. Hoogstwaarschijnlijk is deze verbinding verwijderd. @@ -4336,7 +4712,7 @@ Dit is jouw link voor groep %@! Multiple chat profiles - Meerdere chat profielen + Meerdere chatprofielen No comment provided by engineer. @@ -4364,6 +4740,11 @@ Dit is jouw link voor groep %@! Netwerkverbinding No comment provided by engineer. + + Network decentralization + Netwerk decentralisatie + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Netwerkproblemen - bericht is verlopen na vele pogingen om het te verzenden. @@ -4374,6 +4755,11 @@ Dit is jouw link voor groep %@! Netwerkbeheer No comment provided by engineer. + + Network operator + Netwerkbeheerder + No comment provided by engineer. + Network settings Netwerk instellingen @@ -4389,6 +4775,16 @@ Dit is jouw link voor groep %@! Nieuwe toegangscode No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Elke keer dat u de app start, worden er nieuwe SOCKS-inloggegevens gebruikt. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Voor elke server worden nieuwe SOCKS-inloggegevens gebruikt. + No comment provided by engineer. + New chat Nieuw gesprek @@ -4409,11 +4805,6 @@ Dit is jouw link voor groep %@! Nieuw contact: notification - - New database archive - Nieuw database archief - No comment provided by engineer. - New desktop app! Nieuwe desktop app! @@ -4424,6 +4815,11 @@ Dit is jouw link voor groep %@! Nieuwe weergavenaam No comment provided by engineer. + + New events + Nieuwe gebeurtenissen + notification + New in %@ Nieuw in %@ @@ -4449,6 +4845,11 @@ Dit is jouw link voor groep %@! Nieuw wachtwoord… No comment provided by engineer. + + New server + Nieuwe server + No comment provided by engineer. + No Nee @@ -4486,7 +4887,7 @@ Dit is jouw link voor groep %@! No filtered chats - Geen gefilterde gesprekken + Geen gefilterde chats No comment provided by engineer. @@ -4504,21 +4905,71 @@ Dit is jouw link voor groep %@! Geen info, probeer opnieuw te laden No comment provided by engineer. + + No media & file servers. + Geen media- en bestandsservers. + servers error + + + No message servers. + Geen berichtenservers. + servers error + No network connection Geen netwerkverbinding No comment provided by engineer. + + No permission to record speech + Geen toestemming om spraak op te nemen + No comment provided by engineer. + + + No permission to record video + Geen toestemming om video op te nemen + No comment provided by engineer. + No permission to record voice message Geen toestemming om spraakbericht op te nemen No comment provided by engineer. + + No push server + Lokaal + No comment provided by engineer. + No received or sent files Geen ontvangen of verzonden bestanden No comment provided by engineer. + + No servers for private message routing. + Geen servers voor het routeren van privéberichten. + servers error + + + No servers to receive files. + Geen servers om bestanden te ontvangen. + servers error + + + No servers to receive messages. + Geen servers om berichten te ontvangen. + servers error + + + No servers to send files. + Geen servers om bestanden te verzenden. + servers error + + + No user identifiers. + Geen gebruikers-ID's. + No comment provided by engineer. + Not compatible! Niet compatibel! @@ -4529,6 +4980,11 @@ Dit is jouw link voor groep %@! Niets geselecteerd No comment provided by engineer. + + Nothing to forward! + Niets om door te sturen! + alert title + Notifications Meldingen @@ -4539,6 +4995,11 @@ Dit is jouw link voor groep %@! Meldingen zijn uitgeschakeld! No comment provided by engineer. + + Notifications privacy + Privacy van meldingen + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5022,13 @@ Dit is jouw link voor groep %@! Ok OK - No comment provided by engineer. + alert button Old database Oude database No comment provided by engineer. - - Old database archive - Oud database archief - No comment provided by engineer. - One-time invitation link Eenmalige uitnodiging link @@ -4597,8 +5053,13 @@ Vereist het inschakelen van VPN. Onion hosts worden niet gebruikt. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + Alleen chateigenaren kunnen voorkeuren wijzigen. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Alleen client apparaten slaan gebruikers profielen, contacten, groepen en berichten op die zijn verzonden met **2-laags end-to-end-codering**. No comment provided by engineer. @@ -4629,7 +5090,7 @@ Vereist het inschakelen van VPN. 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) + Alleen jij kunt berichten definitief verwijderen (je contact kan ze markeren voor verwijdering). (24 uur) No comment provided by engineer. @@ -4682,6 +5143,11 @@ Vereist het inschakelen van VPN. Open instellingen No comment provided by engineer. + + Open changes + Wijzigingen openen + No comment provided by engineer. + Open chat Chat openen @@ -4692,6 +5158,11 @@ Vereist het inschakelen van VPN. Chat console openen authentication reason + + Open conditions + Open voorwaarden + No comment provided by engineer. + Open group Open groep @@ -4702,26 +5173,26 @@ Vereist het inschakelen van VPN. Open de migratie naar een ander apparaat authentication reason - - Open server settings - Server instellingen openen - No comment provided by engineer. - - - Open user profiles - Gebruikers profielen openen - authentication reason - - - 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 app… App openen… No comment provided by engineer. + + Operator + Operator + No comment provided by engineer. + + + Operator server + Operatorserver + alert title + + + Or import archive file + Of importeer archiefbestand + No comment provided by engineer. + Or paste archive link Of plak de archief link @@ -4742,15 +5213,22 @@ Vereist het inschakelen van VPN. Of laat deze code zien No comment provided by engineer. + + Or to share privately + Of om privé te delen + No comment provided by engineer. + Other Ander No comment provided by engineer. - - Other %@ servers - Andere %@ servers - No comment provided by engineer. + + Other file errors: +%@ + Andere bestandsfouten: +%@ + alert message PING count @@ -4787,6 +5265,11 @@ Vereist het inschakelen van VPN. Toegangscode ingesteld! No comment provided by engineer. + + Password + Wachtwoord + No comment provided by engineer. + Password to show Wachtwoord om weer te geven @@ -4822,13 +5305,8 @@ Vereist het inschakelen van VPN. in behandeling No comment provided by engineer. - - People can connect to you only via the links you share. - Mensen kunnen alleen verbinding met u maken via de links die u deelt. - No comment provided by engineer. - - - Periodically + + Periodic Periodiek No comment provided by engineer. @@ -4844,7 +5322,7 @@ Vereist het inschakelen van VPN. Play from the chat list. - Afspelen via de gesprekken lijst. + Afspelen via de chat lijst. No comment provided by engineer. @@ -4923,7 +5401,7 @@ Fout: %@ Please store passphrase securely, you will NOT be able to access chat if you lose it. - Sla het wachtwoord veilig op. Als u deze kwijtraakt, heeft u GEEN toegang tot de gesprekken. + Sla het wachtwoord veilig op. Als u deze kwijtraakt, heeft u GEEN toegang tot de chats. No comment provided by engineer. @@ -4936,6 +5414,11 @@ Fout: %@ Poolse interface No comment provided by engineer. + + Port + Poort + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Mogelijk is de certificaat vingerafdruk in het server adres onjuist @@ -4946,16 +5429,16 @@ Fout: %@ Bewaar het laatste berichtconcept, met bijlagen. No comment provided by engineer. - - Preset server - Vooraf ingestelde server - No comment provided by engineer. - Preset server address Vooraf ingesteld server adres No comment provided by engineer. + + Preset servers + Vooraf ingestelde servers + No comment provided by engineer. + Preview Voorbeeld @@ -4971,6 +5454,11 @@ Fout: %@ Privacy en beveiliging No comment provided by engineer. + + Privacy for your customers. + Privacy voor uw klanten. + No comment provided by engineer. + Privacy redefined Privacy opnieuw gedefinieerd @@ -5021,16 +5509,6 @@ Fout: %@ Profiel afbeeldingen No comment provided by engineer. - - Profile name - Profielnaam - No comment provided by engineer. - - - Profile name: - Profielnaam: - No comment provided by engineer. - Profile password Profiel wachtwoord @@ -5044,7 +5522,7 @@ Fout: %@ Profile update will be sent to your contacts. Profiel update wordt naar uw contacten verzonden. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5053,7 +5531,7 @@ Fout: %@ Prohibit irreversible message deletion. - Verbied het onomkeerbaar verwijderen van berichten. + Verbied het definitief verwijderen van berichten. No comment provided by engineer. @@ -5110,7 +5588,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Protect your chat profiles with a password! - Bescherm je chat profielen met een wachtwoord! + Bescherm je chatprofielen met een wachtwoord! No comment provided by engineer. @@ -5133,6 +5611,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Proxied servers No comment provided by engineer. + + Proxy requires password + Proxy vereist wachtwoord + No comment provided by engineer. + Push notifications Push meldingen @@ -5173,26 +5656,21 @@ Schakel dit in in *Netwerk en servers*-instellingen. Lees meer 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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/readme.html#connect-to-friends). Lees meer in de [Gebruikershandleiding](https://simplex.chat/docs/guide/readme.html#connect-to-friends). No comment provided by engineer. - - Read more in our GitHub repository. - Lees meer in onze GitHub repository. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Lees meer in onze [GitHub-repository](https://github.com/simplex-chat/simplex-chat#readme). @@ -5354,6 +5832,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Verwijderen No comment provided by engineer. + + Remove archive? + Archief verwijderen? + No comment provided by engineer. + Remove image Verwijder afbeelding @@ -5466,7 +5949,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Restart the app to create a new chat profile - Start de app opnieuw om een nieuw chat profiel aan te maken + Start de app opnieuw om een nieuw chatprofiel aan te maken No comment provided by engineer. @@ -5504,6 +5987,16 @@ Schakel dit in in *Netwerk en servers*-instellingen. Onthullen chat item action + + Review conditions + Voorwaarden bekijken + No comment provided by engineer. + + + Review later + Later beoordelen + No comment provided by engineer. + Revoke Intrekken @@ -5534,6 +6027,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. SMP server No comment provided by engineer. + + SOCKS proxy + SOCKS proxy + No comment provided by engineer. + Safely receive files Veilig bestanden ontvangen @@ -5547,17 +6045,18 @@ Schakel dit in in *Netwerk en servers*-instellingen. Save Opslaan - chat item action + alert button + chat item action Save (and notify contacts) Bewaar (en informeer contacten) - No comment provided by engineer. + alert button Save and notify contact Opslaan en Contact melden - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6073,6 @@ Schakel dit in in *Netwerk en servers*-instellingen. Groep profiel opslaan en bijwerken No comment provided by engineer. - - Save archive - Bewaar archief - No comment provided by engineer. - - - Save auto-accept settings - Sla instellingen voor automatisch accepteren op - No comment provided by engineer. - Save group profile Groep profiel opslaan @@ -5591,7 +6080,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Save passphrase and open chat - Bewaar het wachtwoord en open je gesprekken + Bewaar het wachtwoord en open je chats No comment provided by engineer. @@ -5602,7 +6091,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Save preferences? Voorkeuren opslaan? - No comment provided by engineer. + alert title Save profile password @@ -5611,24 +6100,24 @@ Schakel dit in in *Netwerk en servers*-instellingen. Save servers - Bewaar servers + Servers opslaan No comment provided by engineer. Save servers? Servers opslaan? - No comment provided by engineer. - - - Save settings? - Instellingen opslaan? - No comment provided by engineer. + alert title Save welcome message? Welkom bericht opslaan? No comment provided by engineer. + + Save your profile? + Uw profiel opslaan? + alert title + Saved Opgeslagen @@ -5649,6 +6138,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Opgeslagen bericht message info title + + Saving %lld messages + %lld berichten opslaan + No comment provided by engineer. + Scale Schaal @@ -5729,6 +6223,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Selecteer chat item action + + Select chat profile + Selecteer chatprofiel + No comment provided by engineer. + Selected %lld %lld geselecteerd @@ -5819,11 +6318,6 @@ Schakel dit in in *Netwerk en servers*-instellingen. Meldingen verzenden No comment provided by engineer. - - Send notifications: - Meldingen verzenden: - No comment provided by engineer. - Send questions and ideas Stuur vragen en ideeën @@ -5847,7 +6341,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Sender cancelled file transfer. Afzender heeft bestandsoverdracht geannuleerd. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5944,6 +6438,16 @@ Schakel dit in in *Netwerk en servers*-instellingen. Verzonden via proxy No comment provided by engineer. + + Server + Server + No comment provided by engineer. + + + Server added to operator %@. + Server toegevoegd aan operator %@. + alert message + Server address Server adres @@ -5959,6 +6463,21 @@ Schakel dit in in *Netwerk en servers*-instellingen. Serveradres is incompatibel met netwerkinstellingen: %@. No comment provided by engineer. + + Server operator changed. + Serveroperator gewijzigd. + alert title + + + Server operators + Serverbeheerders + No comment provided by engineer. + + + Server protocol changed. + Serverprotocol gewijzigd. + alert title + Server requires authorization to create queues, check password Server vereist autorisatie om wachtrijen te maken, controleer wachtwoord @@ -6064,6 +6583,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Instellingen No comment provided by engineer. + + Settings were changed. + Instellingen zijn gewijzigd. + alert message + Shape profile images Vorm profiel afbeeldingen @@ -6072,22 +6596,38 @@ Schakel dit in in *Netwerk en servers*-instellingen. Share Deel - chat item action + alert action + chat item action Share 1-time link Eenmalige link delen No comment provided by engineer. + + Share 1-time link with a friend + Deel eenmalig een link met een vriend + No comment provided by engineer. + + + Share SimpleX address on social media. + Deel het SimpleX-adres op sociale media. + No comment provided by engineer. + Share address Adres delen No comment provided by engineer. + + Share address publicly + Adres openbaar delen + No comment provided by engineer. + Share address with contacts? Adres delen met contacten? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6639,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Deel link No comment provided by engineer. + + Share profile + Profiel delen + No comment provided by engineer. + Share this 1-time invite link Deel deze eenmalige uitnodigingslink @@ -6169,6 +6714,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. SimpleX adres No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + Simplex-chat en flux hebben een overeenkomst gemaakt om door flux geëxploiteerde servers in de app op te nemen. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. De beveiliging van SimpleX Chat is gecontroleerd door Trail of Bits. @@ -6199,6 +6749,16 @@ Schakel dit in in *Netwerk en servers*-instellingen. SimpleX adres No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + SimpleX-adressen en eenmalige links kunnen veilig worden gedeeld via elke messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + SimpleX adres of eenmalige link? + No comment provided by engineer. + SimpleX contact address SimpleX contact adres @@ -6219,9 +6779,9 @@ Schakel dit in in *Netwerk en servers*-instellingen. SimpleX links chat feature - - SimpleX links are prohibited in this group. - SimpleX-links zijn in deze groep verboden. + + SimpleX links are prohibited. + SimpleX-links zijn niet toegestaan. No comment provided by engineer. @@ -6234,6 +6794,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Eenmalige SimpleX uitnodiging simplex link type + + SimpleX protocols reviewed by Trail of Bits. + SimpleX-protocollen beoordeeld door Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Vereenvoudigde incognitomodus @@ -6264,6 +6829,11 @@ Schakel dit in in *Netwerk en servers*-instellingen. Soft blur media + + Some app settings were not migrated. + Sommige app-instellingen zijn niet gemigreerd. + No comment provided by engineer. + Some file(s) were not exported: Sommige bestanden zijn niet geëxporteerd: @@ -6279,6 +6849,13 @@ Schakel dit in in *Netwerk en servers*-instellingen. Er zijn enkele niet-fatale fouten opgetreden tijdens het importeren: No comment provided by engineer. + + Some servers failed the test: +%@ + Sommige servers zijn niet geslaagd voor de test: +%@ + alert message + Somebody Iemand @@ -6329,11 +6906,6 @@ Schakel dit in in *Netwerk en servers*-instellingen. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - Stop de chat om database acties mogelijk te maken - 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. Stop de chat om de chat database te exporteren, importeren of verwijderen. U kunt geen berichten ontvangen en verzenden terwijl de chat is gestopt. @@ -6362,12 +6934,12 @@ Schakel dit in in *Netwerk en servers*-instellingen. Stop sharing Stop met delen - No comment provided by engineer. + alert action Stop sharing address? Stop met het delen van adres? - No comment provided by engineer. + alert title Stopping chat @@ -6386,17 +6958,17 @@ Schakel dit in in *Netwerk en servers*-instellingen. Subscribed - Ingeschreven + Subscribed No comment provided by engineer. Subscription errors - Inschrijving fouten + Subscription fouten No comment provided by engineer. Subscriptions ignored - Inschrijvingen genegeerd + Subscriptions genegeerd No comment provided by engineer. @@ -6404,6 +6976,16 @@ Schakel dit in in *Netwerk en servers*-instellingen. Ondersteuning van SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Wisselen tussen audio en video tijdens het gesprek. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Wijzig chatprofiel voor eenmalige uitnodigingen. + No comment provided by engineer. + System Systeem @@ -6439,11 +7021,21 @@ Schakel dit in in *Netwerk en servers*-instellingen. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Staart + No comment provided by engineer. + Take picture Foto nemen No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Tik op SimpleX-adres maken in het menu om het later te maken. + No comment provided by engineer. + Tap button Tik op de knop @@ -6502,7 +7094,7 @@ Schakel dit in in *Netwerk en servers*-instellingen. Tests failed! Testen mislukt! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7111,6 @@ Schakel dit in in *Netwerk en servers*-instellingen. Dank aan de gebruikers – draag bij via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Het eerste platform zonder gebruikers-ID's, privé door ontwerp. - No comment provided by engineer. - 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. @@ -6536,6 +7123,11 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De app kan u op de hoogte stellen wanneer u berichten of contact verzoeken ontvangt - open de instellingen om dit in te schakelen. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + De app beschermt uw privacy door in elk gesprek andere operatoren te gebruiken. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). De app vraagt om downloads van onbekende bestandsservers (behalve .onion) te bevestigen. @@ -6551,6 +7143,11 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De code die u heeft gescand is geen SimpleX link QR-code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + De verbinding heeft de limiet van niet-afgeleverde berichten bereikt. Uw contactpersoon is mogelijk offline. + No comment provided by engineer. + The connection you accepted will be cancelled! De door u geaccepteerde verbinding wordt geannuleerd! @@ -6571,6 +7168,11 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De versleuteling werkt en de nieuwe versleutelingsovereenkomst is niet vereist. Dit kan leiden tot verbindingsfouten! No comment provided by engineer. + + The future of messaging + De volgende generatie privéberichten + No comment provided by engineer. + The hash of the previous message is different. De hash van het vorige bericht is anders. @@ -6596,11 +7198,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De berichten worden voor alle leden als gemodereerd gemarkeerd. No comment provided by engineer. - - The next generation of private messaging - De volgende generatie privéberichten - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. De oude database is niet verwijderd tijdens de migratie, deze kan worden verwijderd. @@ -6611,6 +7208,21 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. Het profiel wordt alleen gedeeld met uw contacten. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Dezelfde voorwaarden gelden voor operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Dezelfde voorwaarden gelden voor operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + De tweede vooraf ingestelde operator in de app! + No comment provided by engineer. + The second tick we missed! ✅ De tweede vink die we gemist hebben! ✅ @@ -6623,7 +7235,12 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. The servers for new connections of your current chat profile **%@**. - De servers voor nieuwe verbindingen van uw huidige chat profiel **%@**. + De servers voor nieuwe verbindingen van uw huidige chatprofiel **%@**. + No comment provided by engineer. + + + The servers for new files of your current chat profile **%@**. + De servers voor nieuwe bestanden van uw huidige chatprofiel **%@**. No comment provided by engineer. @@ -6631,11 +7248,21 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. De tekst die u hebt geplakt is geen SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + Het geüploade databasearchief wordt permanent van de servers verwijderd. + No comment provided by engineer. + Themes Thema's No comment provided by engineer. + + These conditions will also apply for: **%@**. + Deze voorwaarden zijn ook van toepassing op: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Deze instellingen zijn voor uw huidige profiel **%@**. @@ -6658,7 +7285,7 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost. - Deze actie kan niet ongedaan worden gemaakt. Uw profiel, contacten, berichten en bestanden gaan onomkeerbaar verloren. + Deze actie kan niet ongedaan worden gemaakt. Uw profiel, contacten, berichten en bestanden gaan definitief verloren. No comment provided by engineer. @@ -6708,7 +7335,7 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. This setting applies to messages in your current chat profile **%@**. - Deze instelling is van toepassing op berichten in je huidige chat profiel **%@**. + Deze instelling is van toepassing op berichten in je huidige chatprofiel **%@**. No comment provided by engineer. @@ -6736,9 +7363,9 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast. Om een nieuwe verbinding te maken 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. - Om de privacy te beschermen, heeft SimpleX in plaats van gebruikers-ID's die door alle andere platforms worden gebruikt, ID's voor berichten wachtrijen, afzonderlijk voor elk van uw contacten. + + To protect against your link being replaced, you can compare contact security codes. + Om te voorkomen dat uw link wordt vervangen, kunt u contactbeveiligingscodes vergelijken. No comment provided by engineer. @@ -6758,6 +7385,26 @@ You will be prompted to complete authentication before this feature is enabled.< U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingeschakeld. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Om de privacy te beschermen, heeft SimpleX in plaats van gebruikers-ID's die door alle andere platforms worden gebruikt, ID's voor berichten wachtrijen, afzonderlijk voor elk van uw contacten. + No comment provided by engineer. + + + To receive + Om te ontvangen + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Geef toestemming om de microfoon te gebruiken om spraak op te nemen. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Om video op te nemen, dient u toestemming te geven om de camera te gebruiken. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Geef toestemming om de microfoon te gebruiken om een spraakbericht op te nemen. @@ -6765,7 +7412,12 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page. - Om uw verborgen profiel te onthullen, voert u een volledig wachtwoord in een zoek veld in op de pagina **Uw chat profielen**. + Om uw verborgen profiel te onthullen, voert u een volledig wachtwoord in een zoek veld in op de pagina **Uw chatprofielen**. + No comment provided by engineer. + + + To send + Om te verzenden No comment provided by engineer. @@ -6773,6 +7425,11 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Om directe push meldingen te ondersteunen, moet de chat database worden gemigreerd. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + Om de servers van **%@** te gebruiken, moet u de gebruiksvoorwaarden accepteren. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Vergelijk (of scan) de code op uw apparaten om end-to-end-codering met uw contact te verifiëren. @@ -6863,6 +7520,11 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Lid deblokkeren? No comment provided by engineer. + + Undelivered messages + Niet afgeleverde berichten + No comment provided by engineer. + Unexpected migration state Onverwachte migratiestatus @@ -6880,7 +7542,7 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Unhide chat profile - Chat profiel zichtbaar maken + Chatprofiel zichtbaar maken No comment provided by engineer. @@ -6911,7 +7573,7 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc Unknown servers! Onbekende servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7682,21 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Archief uploaden No comment provided by engineer. + + Use %@ + Gebruik %@ + No comment provided by engineer. + Use .onion hosts Gebruik .onion-hosts No comment provided by engineer. + + Use SOCKS proxy + Gebruik SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? SimpleX Chat servers gebruiken? @@ -7040,6 +7712,16 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Gebruik het huidige profiel No comment provided by engineer. + + Use for files + Gebruik voor bestanden + No comment provided by engineer. + + + Use for messages + Gebruik voor berichten + No comment provided by engineer. + Use for new connections Gebruik voor nieuwe verbindingen @@ -7080,6 +7762,11 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Gebruik server No comment provided by engineer. + + Use servers + Gebruik servers + No comment provided by engineer. + Use the app while in the call. Gebruik de app tijdens het gesprek. @@ -7090,16 +7777,16 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Gebruik de app met één hand. No comment provided by engineer. - - User profile - Gebruikers profiel - No comment provided by engineer. - User selection Gebruikersselectie No comment provided by engineer. + + Username + Gebruikersnaam + No comment provided by engineer. + Using SimpleX Chat servers. SimpleX Chat servers gebruiken. @@ -7170,11 +7857,21 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Video's en bestanden tot 1 GB No comment provided by engineer. + + View conditions + Bekijk voorwaarden + No comment provided by engineer. + View security code Beveiligingscode bekijken No comment provided by engineer. + + View updated conditions + Bekijk de bijgewerkte voorwaarden + No comment provided by engineer. + Visible history Zichtbare geschiedenis @@ -7187,12 +7884,12 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Voice messages are prohibited in this chat. - Spraak berichten zijn verboden in deze chat. + Spraak berichten zijn niet toegestaan in dit gesprek. No comment provided by engineer. - - Voice messages are prohibited in this group. - Spraak berichten zijn verboden in deze groep. + + Voice messages are prohibited. + Spraak berichten zijn niet toegestaan. No comment provided by engineer. @@ -7202,7 +7899,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Voice messages prohibited! - Spraak berichten verboden! + Spraak berichten niet toegestaan! No comment provided by engineer. @@ -7285,9 +7982,9 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Bij het verbinden van audio- en video-oproepen. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Wanneer mensen vragen om verbinding te maken, kunt u dit accepteren of weigeren. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Wanneer er meer dan één operator is ingeschakeld, beschikt geen enkele operator over metagegevens om te achterhalen wie met wie communiceert. No comment provided by engineer. @@ -7333,7 +8030,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Zonder Tor of VPN zal uw IP-adres zichtbaar zijn voor deze XFTP-relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8057,6 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak XFTP server No comment provided by engineer. - - You - Jij - No comment provided by engineer. - You **must not** use the same database on two devices. U **mag** niet dezelfde database op twee apparaten gebruiken. @@ -7382,7 +8074,7 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak You already have a chat profile with the same display name. Please choose another name. - Je hebt al een chat profiel met dezelfde weergave naam. Kies een andere naam. + Je hebt al een chatprofiel met dezelfde weergave naam. Kies een andere naam. No comment provided by engineer. @@ -7390,6 +8082,11 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak U bent al verbonden met %@. No comment provided by engineer. + + You are already connected with %@. + U bent al verbonden met %@. + No comment provided by engineer. + You are already connecting to %@. U maakt al verbinding met %@. @@ -7452,6 +8149,16 @@ Deelnameverzoek herhalen? U kunt dit wijzigen in de instellingen onder uiterlijk. No comment provided by engineer. + + You can configure operators in Network & servers settings. + U kunt operators configureren in Netwerk- en serverinstellingen. + No comment provided by engineer. + + + You can configure servers via settings. + U kunt servers configureren via instellingen. + No comment provided by engineer. + You can create it later U kan het later maken @@ -7492,6 +8199,11 @@ Deelnameverzoek herhalen? U kunt berichten naar %@ sturen vanuit gearchiveerde contacten. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + U kunt een verbindingsnaam instellen, zodat u kunt onthouden met wie de link is gedeeld. + No comment provided by engineer. + You can set lock screen notification preview via settings. U kunt een voorbeeld van een melding op het vergrendeld scherm instellen via instellingen. @@ -7507,11 +8219,6 @@ Deelnameverzoek herhalen? U kunt dit adres delen met uw contacten om hen verbinding te laten maken met **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - U kunt uw adres delen als een link of als een QR-code. Iedereen kan verbinding met u maken. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app U kunt de chat starten via app Instellingen / Database of door de app opnieuw op te starten @@ -7535,23 +8242,23 @@ Deelnameverzoek herhalen? You can view invitation link again in connection details. U kunt de uitnodigingslink opnieuw bekijken in de verbindingsdetails. - No comment provided by engineer. + alert message You can't send messages! Je kunt geen berichten versturen! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - U bepaalt via welke server(s) de berichten **ontvangen**, uw contacten de servers die u gebruikt om ze berichten te sturen. - No comment provided by engineer. - You could not be verified; please try again. U kon niet worden geverifieerd; probeer het opnieuw. No comment provided by engineer. + + You decide who can connect. + Jij bepaalt wie er verbinding mag maken. + No comment provided by engineer. + You have already requested connection via this address! U heeft al een verbinding aangevraagd via dit adres! @@ -7654,6 +8361,11 @@ Verbindingsverzoek herhalen? U ontvangt nog steeds oproepen en meldingen van gedempte profielen wanneer deze actief zijn. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + U ontvangt geen berichten meer van deze chat. De chatgeschiedenis blijft bewaard. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Je ontvangt geen berichten meer van deze groep. Je gesprek geschiedenis blijft behouden. @@ -7674,11 +8386,6 @@ Verbindingsverzoek herhalen? Je gebruikt een incognito profiel voor deze groep. Om te voorkomen dat je je hoofdprofiel deelt, is het niet toegestaan om contacten uit te nodigen No comment provided by engineer. - - Your %@ servers - Uw %@ servers - No comment provided by engineer. - Your ICE servers Uw ICE servers @@ -7694,11 +8401,6 @@ Verbindingsverzoek herhalen? Uw SimpleX adres No comment provided by engineer. - - Your XFTP servers - Uw XFTP servers - No comment provided by engineer. - Your calls Uw oproepen @@ -7714,11 +8416,21 @@ Verbindingsverzoek herhalen? Uw chat database is niet versleuteld, stel een wachtwoord in om deze te versleutelen. No comment provided by engineer. + + Your chat preferences + Uw chat voorkeuren + alert title + Your chat profiles Uw chat profielen No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Uw verbinding is verplaatst naar %@, maar er is een onverwachte fout opgetreden tijdens het omleiden naar het profiel. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Uw contact heeft een bestand verzonden dat groter is dan de momenteel ondersteunde maximale grootte (%@). @@ -7734,6 +8446,11 @@ Verbindingsverzoek herhalen? Uw contacten blijven verbonden. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Uw inloggegevens worden mogelijk niet-versleuteld verzonden. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Uw huidige chat database wordt VERWIJDERD en VERVANGEN door de geïmporteerde. @@ -7764,13 +8481,16 @@ Verbindingsverzoek herhalen? Uw profiel **%@** wordt gedeeld. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. -SimpleX servers kunnen uw profiel niet zien. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten. SimpleX servers kunnen uw profiel niet zien. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Je profiel is gewijzigd. Als je het opslaat, wordt het bijgewerkte profiel naar al je contacten verzonden. + alert message + Your profile, contacts and delivered messages are stored on your device. Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen. @@ -7781,16 +8501,16 @@ SimpleX servers kunnen uw profiel niet zien. Je willekeurige profiel No comment provided by engineer. - - Your server - Uw server - No comment provided by engineer. - Your server address Uw server adres No comment provided by engineer. + + Your servers + Uw servers + No comment provided by engineer. + Your settings Uw instellingen @@ -7831,6 +8551,11 @@ SimpleX servers kunnen uw profiel niet zien. geaccepteerde oproep call status + + accepted invitation + geaccepteerde uitnodiging + chat list item title + admin Beheerder @@ -8019,7 +8744,7 @@ SimpleX servers kunnen uw profiel niet zien. connecting… Verbinden… - chat list item title + No comment provided by engineer. connection established @@ -8211,6 +8936,11 @@ SimpleX servers kunnen uw profiel niet zien. verlopen No comment provided by engineer. + + for better metadata privacy. + voor betere privacy van metagegevens. + No comment provided by engineer. + forwarded doorgestuurd @@ -8508,6 +9238,11 @@ SimpleX servers kunnen uw profiel niet zien. heeft je verwijderd rcv group event chat item + + requested to connect + gevraagd om verbinding te maken + chat list item title + saved opgeslagen @@ -8709,7 +9444,7 @@ laatst ontvangen bericht: %2$@ you are observer - jij bent waarnemer + je bent waarnemer No comment provided by engineer. @@ -8739,7 +9474,7 @@ laatst ontvangen bericht: %2$@ you left - jij bent vertrokken + je bent vertrokken snd group event chat item @@ -8833,6 +9568,38 @@ laatst ontvangen bericht: %2$@ + +
+ +
+ + + %d new events + ‐%d nieuwe gebeurtenissen + notification body + + + From: %@ + Van: %@ + notification body + + + New events + Nieuwe gebeurtenissen + notification + + + New messages + Nieuwe berichten + notification + + + New messages in %d chats + Nieuwe berichten in %d chats + notification body + + +
@@ -8917,7 +9684,7 @@ laatst ontvangen bericht: %2$@ Database passphrase is required to open chat. - Database wachtwoord is vereist om je gesprekken te openen. + Database wachtwoord is vereist om je chats te openen. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/nl.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 f0f4670dd6..8cfdf56f66 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,14 @@ %@ jest zweryfikowany No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded %@ wgrane @@ -137,6 +130,11 @@ %@ chce się połączyć! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ i %lld członków @@ -157,11 +155,36 @@ %d dni time interval + + %d file(s) are still being downloaded. + %d plik(ów) jest dalej pobieranych. + forward confirmation reason + + + %d file(s) failed to download. + %d plik(ów) nie udało się pobrać. + forward confirmation reason + + + %d file(s) were deleted. + %d plik(ów) zostało usuniętych. + forward confirmation reason + + + %d file(s) were not downloaded. + %d plik(ów) nie zostało pobranych. + forward confirmation reason + %d hours %d godzin time interval + + %d messages not forwarded + %d wiadomości nie przekazanych + alert title + %d min %d min @@ -322,28 +345,23 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **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 or link for your contact. - **Dodaj nowy kontakt**: aby stworzyć swój jednorazowy kod QR lub link dla kontaktu. - No comment provided by engineer. - **Create group**: to create a new group. **Utwórz grupę**: aby utworzyć nową grupę. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Bardziej prywatny**: sprawdzanie nowych wiadomości odbywa się co 20 minut. Współdzielony z serwerem SimpleX Chat jest token urządzenia, lecz nie informacje o liczbie kontaktów lub wiadomości. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Najbardziej prywatny**: nie korzystaj z serwera powiadomień SimpleX Chat, wiadomości sprawdzane są co jakiś czas w tle (zależne od tego jak często korzystasz z aplikacji). No comment provided by engineer. @@ -357,11 +375,15 @@ **Uwaga**: NIE będziesz w stanie odzyskać lub zmienić kodu dostępu, jeśli go 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Zalecane**: do serwera powiadomień SimpleX Chat wysyłany jest token urządzenia i powiadomienia, lecz nie treść wiadomości, jej rozmiar lub od kogo ona jest. No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **Uwaga**: Natychmiastowe powiadomienia push wymagają zapisania kodu dostępu w Keychain. @@ -468,6 +490,14 @@ 1 tydzień time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 minut @@ -537,19 +567,13 @@ Przerwać zmianę adresu? No comment provided by engineer. - - About SimpleX - O SimpleX - No comment provided by engineer. - About SimpleX Chat O SimpleX Chat No comment provided by engineer. - - About SimpleX address - O adresie SimpleX + + About operators No comment provided by engineer. @@ -564,6 +588,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Zaakceptować prośbę o połączenie? @@ -580,6 +608,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged Potwierdzono @@ -600,14 +632,8 @@ 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 + + Add friends No comment provided by engineer. @@ -625,6 +651,10 @@ Dodaj serwery, skanując kody QR. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Dodaj do innego urządzenia @@ -635,6 +665,18 @@ Dodaj wiadomość powitalną No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent Dodatkowy akcent @@ -660,6 +702,14 @@ Zmiana adresu zostanie przerwana. Użyty zostanie stary adres odbiorczy. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. Administratorzy mogą blokować członka dla wszystkich. @@ -695,8 +745,8 @@ Wszystkie dane są usuwane po jego wprowadzeniu. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Wszystkie dane są prywatne na Twoim urządzeniu. No comment provided by engineer. @@ -705,6 +755,10 @@ Wszyscy członkowie grupy pozostaną połączeni. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + 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ąć! @@ -723,7 +777,7 @@ All profiles Wszystkie profile - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -752,6 +806,7 @@ Allow calls? + Zezwolić na połączenia? No comment provided by engineer. @@ -791,6 +846,7 @@ Allow sharing + Zezwól na udostępnianie No comment provided by engineer. @@ -883,6 +939,11 @@ Odbierz połączenie No comment provided by engineer. + + Anybody can host servers. + Każdy może hostować serwery. + No comment provided by engineer. + App build: %@ Kompilacja aplikacji: %@ @@ -913,6 +974,11 @@ Pin aplikacji został zastąpiony pinem samozniszczenia. No comment provided by engineer. + + App session + Sesja aplikacji + No comment provided by engineer. + App version Wersja aplikacji @@ -945,10 +1011,12 @@ Archive contacts to chat later. + Archiwizuj kontakty aby porozmawiać później. No comment provided by engineer. Archived contacts + Zarchiwizowane kontakty No comment provided by engineer. @@ -1016,6 +1084,11 @@ Automatyczne akceptowanie obrazów No comment provided by engineer. + + Auto-accept settings + Ustawienia automatycznej akceptacji + alert title + Back Wstecz @@ -1041,11 +1114,19 @@ Zły hash wiadomości No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups Lepsze grupy No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages Lepsze wiadomości @@ -1053,6 +1134,19 @@ Better networking + Lepsze sieciowanie + No comment provided by engineer. + + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience No comment provided by engineer. @@ -1097,10 +1191,12 @@ Blur for better privacy. + Rozmycie dla lepszej prywatności. No comment provided by engineer. Blur media + Rozmycie mediów No comment provided by engineer. @@ -1133,6 +1229,14 @@ Bułgarski, fiński, tajski i ukraiński – dzięki użytkownikom i [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). Według profilu czatu (domyślnie) lub [według połączenia](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA). @@ -1150,6 +1254,7 @@ Calls prohibited! + Połączenia zakazane! No comment provided by engineer. @@ -1159,10 +1264,12 @@ Can't call contact + Nie można zadzwonić do kontaktu No comment provided by engineer. Can't call member + Nie można zadzwonić do członka No comment provided by engineer. @@ -1177,12 +1284,14 @@ Can't message member + Nie można wysłać wiadomości do członka No comment provided by engineer. Cancel Anuluj - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1202,7 +1311,7 @@ Cannot receive file Nie można odebrać pliku - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1219,6 +1328,10 @@ Zmień No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Zmienić hasło bazy danych? @@ -1265,9 +1378,16 @@ authentication reason set passcode view - - Chat archive - Archiwum czatu + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1292,6 +1412,7 @@ Chat database exported + Wyeksportowano bazę danych czatu No comment provided by engineer. @@ -1316,6 +1437,7 @@ Chat list + Lista czatów No comment provided by engineer. @@ -1328,20 +1450,46 @@ Preferencje czatu No comment provided by engineer. + + Chat preferences were changed. + Preferencje czatu zostały zmienione. + alert message + + + Chat profile + Profil użytkownika + No comment provided by engineer. + Chat theme Motyw czatu No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats Czaty No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Sprawdź adres serwera i spróbuj ponownie. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1405,6 +1553,7 @@ Color chats with the new themes. + Koloruj czaty z nowymi motywami. No comment provided by engineer. @@ -1427,16 +1576,47 @@ Zakończono No comment provided by engineer. + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers Skonfiguruj serwery ICE No comment provided by engineer. - - Configured %@ servers - Skonfigurowano %@ serwerów - No comment provided by engineer. - Confirm Potwierdź @@ -1449,6 +1629,7 @@ Confirm contact deletion? + Potwierdzić usunięcie kontaktu? No comment provided by engineer. @@ -1508,6 +1689,7 @@ Connect to your friends faster. + Szybciej łącz się ze znajomymi. No comment provided by engineer. @@ -1586,6 +1768,7 @@ To jest twój jednorazowy link! Connecting to contact, please wait or check later! + Łączenie z kontaktem, poczekaj lub sprawdź później! No comment provided by engineer. @@ -1600,6 +1783,7 @@ To jest twój jednorazowy link! Connection and servers status. + Stan połączenia i serwerów. No comment provided by engineer. @@ -1614,6 +1798,7 @@ To jest twój jednorazowy link! Connection notifications + Powiadomienia o połączeniu No comment provided by engineer. @@ -1621,6 +1806,10 @@ To jest twój jednorazowy link! Prośba o połączenie wysłana! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated Połączenie zakończone @@ -1653,6 +1842,7 @@ To jest twój jednorazowy link! Contact deleted! + Kontakt usunięty! No comment provided by engineer. @@ -1667,6 +1857,7 @@ To jest twój jednorazowy link! Contact is deleted. + Kontakt jest usunięty. No comment provided by engineer. @@ -1681,6 +1872,7 @@ To jest twój jednorazowy link! Contact will be deleted - this cannot be undone! + Kontakt zostanie usunięty – nie można tego cofnąć! No comment provided by engineer. @@ -1700,6 +1892,7 @@ To jest twój jednorazowy link! Conversation deleted! + Rozmowa usunięta! No comment provided by engineer. @@ -1717,6 +1910,11 @@ To jest twój jednorazowy link! Wersja rdzenia: v%@ No comment provided by engineer. + + Corner + Róg + No comment provided by engineer. + Correct name to %@? Poprawić imię na %@? @@ -1727,6 +1925,10 @@ To jest twój jednorazowy link! Utwórz No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address Utwórz adres SimpleX @@ -1737,11 +1939,6 @@ To jest twój jednorazowy link! Utwórz grupę używając losowego profilu. No comment provided by engineer. - - Create an address to let people connect with you. - Utwórz adres, aby ludzie mogli się z Tobą połączyć. - No comment provided by engineer. - Create file Utwórz plik @@ -1802,11 +1999,6 @@ To jest twój jednorazowy link! Utworzony o: %@ copied message info - - Created on %@ - Utworzony w dniu %@ - No comment provided by engineer. - Creating archive link Tworzenie linku archiwum @@ -1822,6 +2014,10 @@ To jest twój jednorazowy link! Aktualny Pin No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Obecne hasło… @@ -1842,6 +2038,10 @@ To jest twój jednorazowy link! Niestandardowy czas No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme Dostosuj motyw @@ -1973,11 +2173,13 @@ To jest twój jednorazowy link! Delete Usuń - chat item action + alert action + chat item action swipe action Delete %lld messages of members? + Usunąć %lld wiadomości członków? No comment provided by engineer. @@ -2010,14 +2212,8 @@ To jest twój jednorazowy link! Usuń i powiadom kontakt No comment provided by engineer. - - Delete archive - Usuń archiwum - No comment provided by engineer. - - - Delete chat archive? - Usunąć archiwum czatu? + + Delete chat No comment provided by engineer. @@ -2030,6 +2226,10 @@ To jest twój jednorazowy link! Usunąć profil czatu? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Usuń połączenie @@ -2042,6 +2242,7 @@ To jest twój jednorazowy link! Delete contact? + Usunąć kontakt? No comment provided by engineer. @@ -2134,6 +2335,10 @@ To jest twój jednorazowy link! Usunąć starą bazę danych? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? Usunąć oczekujące połączenie? @@ -2151,6 +2356,7 @@ To jest twój jednorazowy link! Delete up to 20 messages at once. + Usuń do 20 wiadomości na raz. No comment provided by engineer. @@ -2160,6 +2366,7 @@ To jest twój jednorazowy link! Delete without notification + Usuń bez powiadomienia No comment provided by engineer. @@ -2182,6 +2389,10 @@ To jest twój jednorazowy link! Błędy usuwania No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery Dostarczenie @@ -2219,6 +2430,7 @@ To jest twój jednorazowy link! Destination server address of %@ is incompatible with forwarding server %@ settings. + Adres serwera docelowego %@ jest niekompatybilny z ustawieniami serwera przekazującego %@. No comment provided by engineer. @@ -2228,6 +2440,7 @@ To jest twój jednorazowy link! Destination server version of %@ is incompatible with forwarding server %@. + Wersja serwera docelowego %@ jest niekompatybilna z serwerem przekierowującym %@. No comment provided by engineer. @@ -2247,6 +2460,7 @@ To jest twój jednorazowy link! Developer options + Opcje deweloperskie No comment provided by engineer. @@ -2279,8 +2493,12 @@ To jest twój jednorazowy link! Bezpośrednie wiadomości chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Bezpośrednie wiadomości między członkami są zabronione w tej grupie. No comment provided by engineer. @@ -2301,6 +2519,7 @@ To jest twój jednorazowy link! Disabled + Wyłączony No comment provided by engineer. @@ -2318,8 +2537,8 @@ To jest twój jednorazowy link! Znikające wiadomości są zabronione na tym czacie. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Znikające wiadomości są zabronione w tej grupie. No comment provided by engineer. @@ -2378,6 +2597,11 @@ To jest twój jednorazowy link! Nie wysyłaj historii do nowych członków. No comment provided by engineer. + + Do not use credentials with proxy. + Nie używaj danych logowania do proxy. + No comment provided by engineer. + Don't create address Nie twórz adresu @@ -2401,7 +2625,8 @@ To jest twój jednorazowy link! Download Pobierz - chat item action + alert button + chat item action Download errors @@ -2418,6 +2643,11 @@ To jest twój jednorazowy link! Pobierz plik server test step + + Download files + Pobierz pliki + alert action + Downloaded Pobrane @@ -2448,6 +2678,10 @@ To jest twój jednorazowy link! Czas trwania No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Edytuj @@ -2468,6 +2702,10 @@ To jest twój jednorazowy link! Włącz (zachowaj nadpisania) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock Włącz blokadę SimpleX @@ -2530,6 +2768,7 @@ To jest twój jednorazowy link! Enabled + Włączony No comment provided by engineer. @@ -2672,26 +2911,34 @@ To jest twój jednorazowy link! Błąd przerwania zmiany adresu No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request Błąd przyjmowania prośby o kontakt No comment provided by engineer. - - Error accessing database file - Błąd dostępu do pliku bazy danych - No comment provided by engineer. - Error adding member(s) Błąd dodawania członka(ów) No comment provided by engineer. + + Error adding server + alert title + Error changing address Błąd zmiany adresu No comment provided by engineer. + + Error changing connection profile + Błąd zmiany połączenia profilu + No comment provided by engineer. + Error changing role Błąd zmiany roli @@ -2702,8 +2949,14 @@ To jest twój jednorazowy link! Błąd zmiany ustawienia No comment provided by engineer. + + Error changing to incognito! + Błąd zmiany na incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. + Błąd połączenia z serwerem przekierowania %@. Spróbuj ponownie później. No comment provided by engineer. @@ -2816,9 +3069,13 @@ To jest twój jednorazowy link! Błąd dołączenia do grupy No comment provided by engineer. - - Error loading %@ servers - Błąd ładowania %@ serwerów + + Error loading servers + alert title + + + Error migrating settings + Błąd migracji ustawień No comment provided by engineer. @@ -2829,7 +3086,7 @@ To jest twój jednorazowy link! Error receiving file Błąd odbioru pliku - No comment provided by engineer. + alert title Error reconnecting server @@ -2851,11 +3108,6 @@ To jest twój jednorazowy link! Błąd resetowania statystyk No comment provided by engineer. - - Error saving %@ servers - Błąd zapisu %@ serwerów - No comment provided by engineer. - Error saving ICE servers Błąd zapisu serwerów ICE @@ -2876,6 +3128,10 @@ To jest twój jednorazowy link! Błąd zapisu hasła do pęku kluczy No comment provided by engineer. + + Error saving servers + alert title + Error saving settings Błąd zapisywania ustawień @@ -2921,10 +3177,15 @@ To jest twój jednorazowy link! Błąd zatrzymania czatu No comment provided by engineer. + + Error switching profile + Błąd zmiany profilu + No comment provided by engineer. + Error switching profile! Błąd przełączania profilu! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2941,6 +3202,10 @@ To jest twój jednorazowy link! Błąd aktualizacji wiadomości No comment provided by engineer. + + Error updating server + alert title + Error updating settings Błąd aktualizacji ustawień @@ -2969,8 +3234,7 @@ To jest twój jednorazowy link! Error: %@ Błąd: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2987,6 +3251,10 @@ To jest twój jednorazowy link! Błędy No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. Nawet po wyłączeniu w rozmowie. @@ -3057,6 +3325,13 @@ To jest twój jednorazowy link! Błąd pliku No comment provided by engineer. + + File errors: +%@ + Błędy pliku: +%@ + alert message + File not found - most likely file was deleted or cancelled. Nie odnaleziono pliku - najprawdopodobniej plik został usunięty lub anulowany. @@ -3112,8 +3387,8 @@ To jest twój jednorazowy link! Pliki i media chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Pliki i media są zabronione w tej grupie. No comment provided by engineer. @@ -3182,21 +3457,56 @@ To jest twój jednorazowy link! Naprawa nie jest obsługiwana przez członka grupy No comment provided by engineer. + + For chat profile %@: + servers error + For console Dla konsoli No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward Przekaż dalej chat item action + + Forward %d message(s)? + Przekazać %d wiadomość(i)? + alert title + Forward and save messages Przesyłaj dalej i zapisuj wiadomości No comment provided by engineer. + + Forward messages + Przekaż wiadomości + alert action + + + Forward messages without files? + Przekazać wiadomości bez plików? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded Przekazane dalej @@ -3207,16 +3517,24 @@ To jest twój jednorazowy link! Przekazane dalej od No comment provided by engineer. + + Forwarding %lld messages + Przekazywanie %lld wiadomości + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. + Serwer przekazujący %@ nie mógł połączyć się z serwerem docelowym %@. Spróbuj ponownie później. No comment provided by engineer. Forwarding server address is incompatible with network settings: %@. + Adres serwera przekierowującego jest niekompatybilny z ustawieniami sieciowymi: %@. No comment provided by engineer. Forwarding server version is incompatible with network settings: %@. + Wersja serwera przekierowującego jest niekompatybilna z ustawieniami sieciowymi: %@. No comment provided by engineer. @@ -3253,11 +3571,6 @@ Błąd: %2$@ Pełna nazwa (opcjonalna) No comment provided by engineer. - - Full name: - Pełna nazwa: - No comment provided by engineer. - Fully decentralized – visible only to members. W pełni zdecentralizowana – widoczna tylko dla członków. @@ -3343,41 +3656,6 @@ Błąd: %2$@ Linki grupowe No comment provided by engineer. - - 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. (24 hours) - Członkowie grupy mogą nieodwracalnie usuwać wysłane wiadomości. (24 godziny) - No comment provided by engineer. - - - Group members can send SimpleX links. - Członkowie grupy mogą wysyłać linki SimpleX. - No comment provided by engineer. - - - Group members can send direct messages. - Członkowie grupy mogą wysyłać bezpośrednie wiadomości. - No comment provided by engineer. - - - Group members can send disappearing messages. - Członkowie grupy mogą wysyłać znikające wiadomości. - No comment provided by engineer. - - - Group members can send files and media. - Członkowie grupy mogą wysyłać pliki i media. - No comment provided by engineer. - - - Group members can send voice messages. - Członkowie grupy mogą wysyłać wiadomości głosowe. - No comment provided by engineer. - Group message: Wiadomość grupowa: @@ -3473,9 +3751,12 @@ Błąd: %2$@ Jak działa SimpleX No comment provided by engineer. - - How it works - Jak to działa + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3503,6 +3784,11 @@ Błąd: %2$@ Serwery ICE (po jednym na linię) No comment provided by engineer. + + IP address + Adres IP + 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. @@ -3543,8 +3829,8 @@ Błąd: %2$@ Natychmiast No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Odporność na spam i nadużycia No comment provided by engineer. @@ -3578,6 +3864,11 @@ Błąd: %2$@ Importowanie archiwum No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery Ulepszona dostawa wiadomości @@ -3678,6 +3969,11 @@ Błąd: %2$@ Zainstaluj [SimpleX Chat na terminal](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Natychmiastowo + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3685,11 +3981,6 @@ Błąd: %2$@ No comment provided by engineer. - - Instantly - Natychmiastowo - No comment provided by engineer. - Interface Interfejs @@ -3738,7 +4029,7 @@ Błąd: %2$@ Invalid server address! Nieprawidłowy adres serwera! - No comment provided by engineer. + alert title Invalid status @@ -3760,6 +4051,10 @@ Błąd: %2$@ Zaproś członków No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Zaproś do grupy @@ -3775,8 +4070,8 @@ Błąd: %2$@ Nieodwracalne usuwanie wiadomości jest na tym czacie zabronione. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Nieodwracalne usuwanie wiadomości jest w tej grupie zabronione. No comment provided by engineer. @@ -3803,6 +4098,7 @@ Błąd: %2$@ It protects your IP address and connections. + Chroni Twój adres IP i połączenia. No comment provided by engineer. @@ -3865,10 +4161,11 @@ To jest twój link do grupy %@! Keep Zachowaj - No comment provided by engineer. + alert action Keep conversation + Zachowaj rozmowę No comment provided by engineer. @@ -3879,7 +4176,7 @@ To jest twój link do grupy %@! Keep unused invitation? Zachować nieużyte zaproszenie? - No comment provided by engineer. + alert title Keep your connections @@ -3916,6 +4213,14 @@ To jest twój link do grupy %@! Opuść swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Opuść grupę @@ -3966,11 +4271,6 @@ To jest twój link do grupy %@! Wiadomości na żywo No comment provided by engineer. - - Local - Lokalnie - No comment provided by engineer. - Local name Nazwa lokalna @@ -3991,11 +4291,6 @@ To jest twój link do grupy %@! Tryb blokady No comment provided by engineer. - - Make a private connection - Nawiąż prywatne połączenie - No comment provided by engineer. - Make one message disappear Spraw, aby jedna wiadomość zniknęła @@ -4006,21 +4301,11 @@ To jest twój link do grupy %@! Ustaw profil jako prywatny! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Upewnij się, że adresy serwerów %@ są w poprawnym formacie, rozdzielone liniami i nie są zduplikowane (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Upewnij się, że adresy serwerów WebRTC ICE są w poprawnym formacie, rozdzielone liniami i nie są zduplikowane. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Wiele osób pytało: *jeśli SimpleX nie ma identyfikatora użytkownika, jak może dostarczać wiadomości?* - No comment provided by engineer. - Mark deleted for everyone Oznacz jako usunięty dla wszystkich @@ -4048,10 +4333,12 @@ To jest twój link do grupy %@! Media & file servers + Serwery mediów i plików No comment provided by engineer. Medium + Średni blur media @@ -4064,6 +4351,10 @@ To jest twój link do grupy %@! Członek nieaktywny item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Rola członka grupy zostanie zmieniona na "%@". Wszyscy członkowie grupy zostaną powiadomieni. @@ -4074,11 +4365,50 @@ To jest twój link do grupy %@! Rola członka zostanie zmieniona na "%@". Członek otrzyma nowe zaproszenie. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Członek zostanie usunięty z grupy - nie można tego cofnąć! No comment provided by engineer. + + Members can add message reactions. + Członkowie grupy mogą dodawać reakcje wiadomości. + No comment provided by engineer. + + + 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. + + + Members can send SimpleX links. + Członkowie grupy mogą wysyłać linki SimpleX. + No comment provided by engineer. + + + Members can send direct messages. + Członkowie grupy mogą wysyłać bezpośrednie wiadomości. + No comment provided by engineer. + + + Members can send disappearing messages. + Członkowie grupy mogą wysyłać znikające wiadomości. + No comment provided by engineer. + + + Members can send files and media. + Członkowie grupy mogą wysyłać pliki i media. + No comment provided by engineer. + + + Members can send voice messages. + Członkowie grupy mogą wysyłać wiadomości głosowe. + No comment provided by engineer. + Menus Menu @@ -4129,8 +4459,8 @@ To jest twój link do grupy %@! Reakcje wiadomości są zabronione na tym czacie. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Reakcje wiadomości są zabronione w tej grupie. No comment provided by engineer. @@ -4141,6 +4471,12 @@ To jest twój link do grupy %@! Message servers + Serwery wiadomości + No comment provided by engineer. + + + Message shape + Kształt wiadomości No comment provided by engineer. @@ -4193,6 +4529,11 @@ To jest twój link do grupy %@! Wysłane wiadomości No comment provided by engineer. + + Messages were deleted after you selected them. + Wiadomości zostały usunięte po wybraniu ich. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Wiadomości, pliki i połączenia są chronione przez **szyfrowanie end-to-end** z doskonałym utajnianiem z wyprzedzeniem i odzyskiem po złamaniu. @@ -4258,9 +4599,9 @@ To jest twój link do grupy %@! Migracja została zakończona No comment provided by engineer. - - Migrations: %@ - Migracje: %@ + + Migrations: + Migracje: No comment provided by engineer. @@ -4288,6 +4629,10 @@ To jest twój link do grupy %@! Bardziej niezawodne połączenia sieciowe. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Najprawdopodobniej to połączenie jest usunięte. @@ -4323,6 +4668,10 @@ To jest twój link do grupy %@! Połączenie z siecią No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Błąd sieciowy - wiadomość wygasła po wielu próbach wysłania jej. @@ -4333,6 +4682,10 @@ To jest twój link do grupy %@! Zarządzenie sieciowe No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Ustawienia sieci @@ -4348,6 +4701,16 @@ To jest twój link do grupy %@! Nowy Pin No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Nowe poświadczenia SOCKS będą używane przy każdym uruchomieniu aplikacji. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Dla każdego serwera zostaną użyte nowe poświadczenia SOCKS. + No comment provided by engineer. + New chat Nowy czat @@ -4355,6 +4718,7 @@ To jest twój link do grupy %@! New chat experience 🎉 + Nowe możliwości czatu 🎉 No comment provided by engineer. @@ -4367,11 +4731,6 @@ To jest twój link do grupy %@! Nowy kontakt: notification - - New database archive - Nowe archiwum bazy danych - No comment provided by engineer. - New desktop app! Nowa aplikacja desktopowa! @@ -4382,6 +4741,10 @@ To jest twój link do grupy %@! Nowa wyświetlana nazwa No comment provided by engineer. + + New events + notification + New in %@ Nowość w %@ @@ -4389,6 +4752,7 @@ To jest twój link do grupy %@! New media options + Nowe opcje mediów No comment provided by engineer. @@ -4406,6 +4770,10 @@ To jest twój link do grupy %@! Nowe hasło… No comment provided by engineer. + + New server + No comment provided by engineer. + No Nie @@ -4461,21 +4829,65 @@ To jest twój link do grupy %@! Brak informacji, spróbuj przeładować No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection Brak połączenia z siecią No comment provided by engineer. + + No permission to record speech + Brak zezwoleń do nagrania rozmowy + No comment provided by engineer. + + + No permission to record video + Brak zezwoleń do nagrania wideo + No comment provided by engineer. + No permission to record voice message Brak uprawnień do nagrywania wiadomości głosowej No comment provided by engineer. + + No push server + Lokalnie + No comment provided by engineer. + No received or sent files Brak odebranych lub wysłanych plików No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Brak identyfikatorów użytkownika. + No comment provided by engineer. + Not compatible! Nie kompatybilny! @@ -4483,8 +4895,14 @@ To jest twój link do grupy %@! Nothing selected + Nic nie jest zaznaczone No comment provided by engineer. + + Nothing to forward! + Nic do przekazania! + alert title + Notifications Powiadomienia @@ -4495,6 +4913,10 @@ To jest twój link do grupy %@! Powiadomienia są wyłączone! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4517,18 +4939,13 @@ To jest twój link do grupy %@! Ok Ok - No comment provided by engineer. + alert button Old database Stara baza danych No comment provided by engineer. - - Old database archive - Stare archiwum bazy danych - No comment provided by engineer. - One-time invitation link Jednorazowy link zaproszenia @@ -4553,13 +4970,18 @@ Wymaga włączenia VPN. Hosty onion nie będą używane. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Tylko urządzenia klienckie przechowują profile użytkowników, kontakty, grupy i wiadomości wysyłane za pomocą **2-warstwowego szyfrowania end-to-end**. No comment provided by engineer. Only delete conversation + Usuń tylko rozmowę No comment provided by engineer. @@ -4637,6 +5059,10 @@ Wymaga włączenia VPN. Otwórz Ustawienia No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Otwórz czat @@ -4647,6 +5073,10 @@ Wymaga włączenia VPN. Otwórz konsolę czatu authentication reason + + Open conditions + No comment provided by engineer. + Open group Grupa otwarta @@ -4657,26 +5087,23 @@ Wymaga włączenia VPN. Otwórz migrację na innym urządzeniu authentication reason - - Open server settings - Otwórz ustawienia serwera - No comment provided by engineer. - - - Open user profiles - Otwórz profile użytkownika - authentication reason - - - 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 app… Otwieranie aplikacji… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link Lub wklej link archiwum @@ -4697,15 +5124,21 @@ Wymaga włączenia VPN. Lub pokaż ten kod No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other Inne No comment provided by engineer. - - Other %@ servers - Inne %@ serwery - No comment provided by engineer. + + Other file errors: +%@ + Inne błędy pliku: +%@ + alert message PING count @@ -4742,6 +5175,11 @@ Wymaga włączenia VPN. Pin ustawiony! No comment provided by engineer. + + Password + Hasło + No comment provided by engineer. + Password to show Hasło do wyświetlenia @@ -4777,13 +5215,8 @@ Wymaga włączenia VPN. Oczekujące No comment provided by engineer. - - People can connect to you only via the links you share. - Ludzie mogą się z Tobą połączyć tylko poprzez linki, które udostępniasz. - No comment provided by engineer. - - - Periodically + + Periodic Okresowo No comment provided by engineer. @@ -4799,10 +5232,12 @@ Wymaga włączenia VPN. Play from the chat list. + Odtwórz z listy czatów. No comment provided by engineer. Please ask your contact to enable calls. + Poproś kontakt o włącznie połączeń. No comment provided by engineer. @@ -4889,6 +5324,11 @@ Błąd: %@ Polski interfejs No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Możliwe, że odcisk palca certyfikatu w adresie serwera jest nieprawidłowy @@ -4899,16 +5339,15 @@ Błąd: %@ Zachowaj ostatnią wersję roboczą wiadomości wraz z załącznikami. No comment provided by engineer. - - Preset server - Wstępnie ustawiony serwer - No comment provided by engineer. - Preset server address Wstępnie ustawiony adres serwera No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview Podgląd @@ -4924,6 +5363,10 @@ Błąd: %@ Prywatność i bezpieczeństwo No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Redefinicja prywatności @@ -4974,16 +5417,6 @@ Błąd: %@ Zdjęcia profilowe No comment provided by engineer. - - Profile name - Nazwa profilu - No comment provided by engineer. - - - Profile name: - Nazwa profilu: - No comment provided by engineer. - Profile password Hasło profilu @@ -4997,7 +5430,7 @@ Błąd: %@ Profile update will be sent to your contacts. Aktualizacja profilu zostanie wysłana do Twoich kontaktów. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5086,6 +5519,11 @@ Włącz w ustawianiach *Sieć i serwery* . Serwery trasowane przez proxy No comment provided by engineer. + + Proxy requires password + Proxy wymaga hasła + No comment provided by engineer. + Push notifications Powiadomienia push @@ -5108,6 +5546,7 @@ Włącz w ustawianiach *Sieć i serwery* . Reachable chat toolbar + Osiągalny pasek narzędzi czatu No comment provided by engineer. @@ -5125,26 +5564,21 @@ Włącz w ustawianiach *Sieć i serwery* . Przeczytaj więcej 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Przeczytaj więcej w [Podręczniku Użytkownika](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Przeczytaj więcej na naszym repozytorium GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Przeczytaj więcej na naszym [repozytorium GitHub](https://github.com/simplex-chat/simplex-chat#readme). @@ -5306,6 +5740,11 @@ Włącz w ustawianiach *Sieć i serwery* . Usuń No comment provided by engineer. + + Remove archive? + Usunąć archiwum? + No comment provided by engineer. + Remove image Usuń obraz @@ -5383,6 +5822,7 @@ Włącz w ustawianiach *Sieć i serwery* . Reset all hints + Zresetuj wszystkie wskazówki No comment provided by engineer. @@ -5455,6 +5895,14 @@ Włącz w ustawianiach *Sieć i serwery* . Ujawnij chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke Odwołaj @@ -5485,6 +5933,11 @@ Włącz w ustawianiach *Sieć i serwery* . Serwer SMP No comment provided by engineer. + + SOCKS proxy + Proxy SOCKS + No comment provided by engineer. + Safely receive files Bezpiecznie otrzymuj pliki @@ -5498,17 +5951,18 @@ Włącz w ustawianiach *Sieć i serwery* . Save Zapisz - chat item action + alert button + chat item action Save (and notify contacts) Zapisz (i powiadom kontakty) - No comment provided by engineer. + alert button Save and notify contact Zapisz i powiadom kontakt - No comment provided by engineer. + alert button Save and notify group members @@ -5517,6 +5971,7 @@ Włącz w ustawianiach *Sieć i serwery* . Save and reconnect + Zapisz i połącz ponownie No comment provided by engineer. @@ -5524,16 +5979,6 @@ Włącz w ustawianiach *Sieć i serwery* . Zapisz i zaktualizuj profil grupowy No comment provided by engineer. - - Save archive - Zapisz archiwum - No comment provided by engineer. - - - Save auto-accept settings - Zapisz ustawienia automatycznej akceptacji - No comment provided by engineer. - Save group profile Zapisz profil grupy @@ -5552,7 +5997,7 @@ Włącz w ustawianiach *Sieć i serwery* . Save preferences? Zapisać preferencje? - No comment provided by engineer. + alert title Save profile password @@ -5567,18 +6012,18 @@ Włącz w ustawianiach *Sieć i serwery* . Save servers? Zapisać serwery? - No comment provided by engineer. - - - Save settings? - Zapisać ustawienia? - No comment provided by engineer. + alert title Save welcome message? Zapisać wiadomość powitalną? No comment provided by engineer. + + Save your profile? + Zapisać Twój profil? + alert title + Saved Zapisane @@ -5599,6 +6044,11 @@ Włącz w ustawianiach *Sieć i serwery* . Zachowano wiadomość message info title + + Saving %lld messages + Zapisywanie %lld wiadomości + No comment provided by engineer. + Scale Skaluj @@ -5679,8 +6129,14 @@ Włącz w ustawianiach *Sieć i serwery* . Wybierz chat item action + + Select chat profile + Wybierz profil czatu + No comment provided by engineer. + Selected %lld + Zaznaczono %lld No comment provided by engineer. @@ -5750,6 +6206,7 @@ Włącz w ustawianiach *Sieć i serwery* . Send message to enable calls. + Wyślij wiadomość aby włączyć połączenia. No comment provided by engineer. @@ -5767,11 +6224,6 @@ Włącz w ustawianiach *Sieć i serwery* . Wyślij powiadomienia No comment provided by engineer. - - Send notifications: - Wyślij powiadomienia: - No comment provided by engineer. - Send questions and ideas Wyślij pytania i pomysły @@ -5795,7 +6247,7 @@ Włącz w ustawianiach *Sieć i serwery* . Sender cancelled file transfer. Nadawca anulował transfer pliku. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5892,6 +6344,15 @@ Włącz w ustawianiach *Sieć i serwery* . Wysłano przez proxy No comment provided by engineer. + + Server + Serwer + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address Adres serwera @@ -5907,6 +6368,18 @@ Włącz w ustawianiach *Sieć i serwery* . Adres serwera jest niekompatybilny z ustawieniami sieci: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Serwer wymaga autoryzacji do tworzenia kolejek, sprawdź hasło @@ -6012,6 +6485,11 @@ Włącz w ustawianiach *Sieć i serwery* . Ustawienia No comment provided by engineer. + + Settings were changed. + Ustawienia zostały zmienione. + alert message + Shape profile images Kształtuj obrazy profilowe @@ -6020,25 +6498,39 @@ Włącz w ustawianiach *Sieć i serwery* . Share Udostępnij - chat item action + alert action + chat item action Share 1-time link Udostępnij 1-razowy link No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Udostępnij adres No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Udostępnić adres kontaktom? - No comment provided by engineer. + alert title Share from other apps. + Udostępnij z innych aplikacji. No comment provided by engineer. @@ -6046,6 +6538,11 @@ Włącz w ustawianiach *Sieć i serwery* . Udostępnij link No comment provided by engineer. + + Share profile + Udostępnij profil + No comment provided by engineer. + Share this 1-time invite link Udostępnij ten jednorazowy link @@ -6053,6 +6550,7 @@ Włącz w ustawianiach *Sieć i serwery* . Share to SimpleX + Udostępnij do SimpleX No comment provided by engineer. @@ -6115,6 +6613,10 @@ Włącz w ustawianiach *Sieć i serwery* . Adres SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Bezpieczeństwo SimpleX Chat zostało zaudytowane przez Trail of Bits. @@ -6145,6 +6647,14 @@ Włącz w ustawianiach *Sieć i serwery* . Adres SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address Adres kontaktowy SimpleX @@ -6165,8 +6675,8 @@ Włącz w ustawianiach *Sieć i serwery* . Linki SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. Linki SimpleX są zablokowane na tej grupie. No comment provided by engineer. @@ -6180,6 +6690,10 @@ Włącz w ustawianiach *Sieć i serwery* . Zaproszenie jednorazowe SimpleX simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Uproszczony tryb incognito @@ -6207,10 +6721,17 @@ Włącz w ustawianiach *Sieć i serwery* . Soft + Łagodny blur media + + Some app settings were not migrated. + Niektóre ustawienia aplikacji nie zostały zmigrowane. + No comment provided by engineer. + Some file(s) were not exported: + Niektóre plik(i) nie zostały wyeksportowane: No comment provided by engineer. @@ -6220,8 +6741,14 @@ Włącz w ustawianiach *Sieć i serwery* . Some non-fatal errors occurred during import: + Podczas importu wystąpiły niekrytyczne błędy: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Ktoś @@ -6272,11 +6799,6 @@ Włącz w ustawianiach *Sieć i serwery* . Zatrzymaj czat No comment provided by engineer. - - Stop chat to enable database actions - Zatrzymaj czat, aby umożliwić działania na bazie danych - 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. Zatrzymaj czat, aby wyeksportować, zaimportować lub usunąć bazę danych czatu. Podczas zatrzymania chatu nie będzie można odbierać ani wysyłać wiadomości. @@ -6305,12 +6827,12 @@ Włącz w ustawianiach *Sieć i serwery* . Stop sharing Przestań udostępniać - No comment provided by engineer. + alert action Stop sharing address? Przestać udostępniać adres? - No comment provided by engineer. + alert title Stopping chat @@ -6319,6 +6841,7 @@ Włącz w ustawianiach *Sieć i serwery* . Strong + Silne blur media @@ -6346,6 +6869,14 @@ Włącz w ustawianiach *Sieć i serwery* . Wspieraj SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System System @@ -6358,6 +6889,7 @@ Włącz w ustawianiach *Sieć i serwery* . TCP connection + Połączenie TCP No comment provided by engineer. @@ -6380,11 +6912,20 @@ Włącz w ustawianiach *Sieć i serwery* . TCP_KEEPINTVL No comment provided by engineer. + + Tail + Ogon + No comment provided by engineer. + Take picture Zrób zdjęcie No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Naciśnij przycisk @@ -6443,7 +6984,7 @@ Włącz w ustawianiach *Sieć i serwery* . Tests failed! Testy nie powiodły się! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6460,11 +7001,6 @@ Włącz w ustawianiach *Sieć i serwery* . Podziękowania dla użytkowników - wkład za pośrednictwem Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Pierwsza platforma bez żadnych identyfikatorów użytkowników – z założenia prywatna. - No comment provided by engineer. - 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. @@ -6477,6 +7013,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Aplikacja może powiadamiać Cię, gdy otrzymujesz wiadomości lub prośby o kontakt — otwórz ustawienia, aby włączyć. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). Aplikacja zapyta o potwierdzenie pobierania od nieznanych serwerów plików (poza .onion). @@ -6492,6 +7032,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Kod, który zeskanowałeś nie jest kodem QR linku SimpleX. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Zaakceptowane przez Ciebie połączenie zostanie anulowane! @@ -6512,6 +7056,11 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Szyfrowanie działa, a nowe uzgodnienie szyfrowania nie jest wymagane. Może to spowodować błędy w połączeniu! No comment provided by engineer. + + The future of messaging + Następna generacja prywatnych wiadomości + No comment provided by engineer. + The hash of the previous message is different. Hash poprzedniej wiadomości jest inny. @@ -6529,15 +7078,12 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom The messages will be deleted for all members. + Wiadomości zostaną usunięte dla wszystkich członków. No comment provided by engineer. The messages will be marked as moderated for all members. - No comment provided by engineer. - - - The next generation of private messaging - Następna generacja prywatnych wiadomości + Wiadomości zostaną oznaczone jako moderowane dla wszystkich członków. No comment provided by engineer. @@ -6550,6 +7096,18 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Profil jest udostępniany tylko Twoim kontaktom. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Drugi tik, który przegapiliśmy! ✅ @@ -6565,16 +7123,29 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Serwery dla nowych połączeń bieżącego profilu czatu **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + 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. + + The uploaded database archive will be permanently removed from the servers. + Przesłane archiwum bazy danych zostanie trwale usunięte z serwerów. + No comment provided by engineer. + Themes Motywy No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Te ustawienia dotyczą Twojego bieżącego profilu **%@**. @@ -6675,9 +7246,8 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom Aby nawiązać nowe połączenie 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. - Aby chronić prywatność, zamiast identyfikatorów użytkowników używanych przez wszystkie inne platformy, SimpleX ma identyfikatory dla kolejek wiadomości, oddzielne dla każdego z Twoich kontaktów. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6697,6 +7267,25 @@ You will be prompted to complete authentication before this feature is enabled.< Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Aby chronić prywatność, zamiast identyfikatorów użytkowników używanych przez wszystkie inne platformy, SimpleX ma identyfikatory dla kolejek wiadomości, oddzielne dla każdego z Twoich kontaktów. + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Aby nagrać rozmowę, proszę zezwolić na użycie Mikrofonu. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Aby nagrać wideo, proszę zezwolić na użycie Aparatu. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Aby nagrać wiadomość głosową należy udzielić zgody na użycie Mikrofonu. @@ -6707,11 +7296,19 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.Aby ujawnić Twój ukryty profil, wprowadź pełne hasło w pole wyszukiwania na stronie **Twoich profili czatu**. No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Aby obsługiwać natychmiastowe powiadomienia push, należy zmigrować bazę danych czatu. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Aby zweryfikować szyfrowanie end-to-end z Twoim kontaktem porównaj (lub zeskanuj) kod na waszych urządzeniach. @@ -6719,6 +7316,7 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania. Toggle chat list: + Przełącz listę czatów: No comment provided by engineer. @@ -6728,6 +7326,7 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania. Toolbar opacity + Nieprzezroczystość paska narzędzi No comment provided by engineer. @@ -6800,6 +7399,10 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.Odblokować członka? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state Nieoczekiwany stan migracji @@ -6848,7 +7451,7 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania. Unknown servers! Nieznane serwery! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6914,6 +7517,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Update settings? + Zaktualizować ustawienia? No comment provided by engineer. @@ -6956,11 +7560,20 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Wgrywanie archiwum No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts Użyj hostów .onion No comment provided by engineer. + + Use SOCKS proxy + Użyj proxy SOCKS + No comment provided by engineer. + Use SimpleX Chat servers? Użyć serwerów SimpleX Chat? @@ -6976,6 +7589,14 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Użyj obecnego profilu No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Użyj dla nowych połączeń @@ -7016,6 +7637,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Użyj serwera No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. Używaj aplikacji podczas połączenia. @@ -7023,11 +7648,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Use the app with one hand. - No comment provided by engineer. - - - User profile - Profil użytkownika + Korzystaj z aplikacji jedną ręką. No comment provided by engineer. @@ -7035,6 +7656,11 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Wybór użytkownika No comment provided by engineer. + + Username + Nazwa użytkownika + No comment provided by engineer. + Using SimpleX Chat servers. Używanie serwerów SimpleX Chat. @@ -7105,11 +7731,19 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Filmy i pliki do 1gb No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Pokaż kod bezpieczeństwa No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history Widoczna historia @@ -7125,8 +7759,8 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Wiadomości głosowe są zabronione na tym czacie. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Wiadomości głosowe są zabronione w tej grupie. No comment provided by engineer. @@ -7220,9 +7854,8 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Podczas łączenia połączeń audio i wideo. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Kiedy ludzie proszą o połączenie, możesz je zaakceptować lub odrzucić. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7268,7 +7901,7 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Bez Tor lub VPN, Twój adres IP będzie widoczny dla tych przekaźników XFTP: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7295,11 +7928,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Serwer XFTP No comment provided by engineer. - - You - Ty - No comment provided by engineer. - You **must not** use the same database on two devices. **Nie możesz** używać tej samej bazy na dwóch urządzeniach. @@ -7325,6 +7953,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc Jesteś już połączony z %@. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. Już się łączysz z %@. @@ -7384,6 +8016,15 @@ Powtórzyć prośbę dołączenia? You can change it in Appearance settings. + Możesz to zmienić w ustawieniach wyglądu. + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. No comment provided by engineer. @@ -7423,6 +8064,11 @@ Powtórzyć prośbę dołączenia? You can send messages to %@ from Archived contacts. + Możesz wysyłać wiadomości do %@ ze zarchiwizowanych kontaktów. + No comment provided by engineer. + + + You can set connection name, to remember who the link was shared with. No comment provided by engineer. @@ -7440,11 +8086,6 @@ Powtórzyć prośbę dołączenia? Możesz udostępnić ten adres Twoim kontaktom, aby umożliwić im połączenie z **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Możesz udostępnić swój adres jako link lub jako kod QR - każdy będzie mógł się z Tobą połączyć. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Możesz rozpocząć czat poprzez Ustawienia aplikacji / Baza danych lub poprzez ponowne uruchomienie aplikacji @@ -7452,6 +8093,7 @@ Powtórzyć prośbę dołączenia? You can still view conversation with %@ in the list of chats. + Nadal możesz przeglądać rozmowę z %@ na liście czatów. No comment provided by engineer. @@ -7467,23 +8109,23 @@ Powtórzyć prośbę dołączenia? 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. + alert message You can't send messages! Nie możesz wysyłać wiadomości! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Kontrolujesz przez który serwer(y) **odbierać** wiadomości, Twoje kontakty - serwery, których używasz do wysyłania im wiadomości. - No comment provided by engineer. - You could not be verified; please try again. Nie można zweryfikować użytkownika; proszę spróbować ponownie. No comment provided by engineer. + + You decide who can connect. + Ty decydujesz, kto może się połączyć. + No comment provided by engineer. + You have already requested connection via this address! Już prosiłeś o połączenie na ten adres! @@ -7518,10 +8160,12 @@ Powtórzyć prośbę połączenia? You may migrate the exported database. + Możesz zmigrować wyeksportowaną bazy danych. No comment provided by engineer. You may save the exported archive. + Możesz zapisać wyeksportowane archiwum. No comment provided by engineer. @@ -7531,6 +8175,7 @@ Powtórzyć prośbę połączenia? You need to allow your contact to call to be able to call them. + Aby móc dzwonić, musisz zezwolić kontaktowi na połączenia. No comment provided by engineer. @@ -7583,6 +8228,10 @@ Powtórzyć prośbę połączenia? Nadal będziesz otrzymywać połączenia i powiadomienia z wyciszonych profili, gdy są one aktywne. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Przestaniesz otrzymywać wiadomości od tej grupy. Historia czatu zostanie zachowana. @@ -7603,11 +8252,6 @@ Powtórzyć prośbę połączenia? Używasz profilu incognito dla tej grupy - aby zapobiec udostępnianiu głównego profilu zapraszanie kontaktów jest zabronione No comment provided by engineer. - - Your %@ servers - Twoje serwery %@ - No comment provided by engineer. - Your ICE servers Twoje serwery ICE @@ -7623,11 +8267,6 @@ Powtórzyć prośbę połączenia? Twój adres SimpleX No comment provided by engineer. - - Your XFTP servers - Twoje serwery XFTP - No comment provided by engineer. - Your calls Twoje połączenia @@ -7643,11 +8282,21 @@ Powtórzyć prośbę połączenia? Baza danych czatu nie jest szyfrowana - ustaw hasło, aby ją zaszyfrować. No comment provided by engineer. + + Your chat preferences + Twoje preferencje czatu + alert title + Your chat profiles Twoje profile czatu No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Twoje połączenie zostało przeniesione do %@, ale podczas przekierowywania do profilu wystąpił nieoczekiwany błąd. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Twój kontakt wysłał plik, który jest większy niż obecnie obsługiwany maksymalny rozmiar (%@). @@ -7663,6 +8312,11 @@ Powtórzyć prośbę połączenia? Twoje kontakty pozostaną połączone. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Twoje poświadczenia mogą zostać wysłane niezaszyfrowane. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Twoja obecna baza danych czatu zostanie usunięta i zastąpiona zaimportowaną. @@ -7693,13 +8347,16 @@ Powtórzyć prośbę połączenia? Twój profil **%@** zostanie udostępniony. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. -Serwery SimpleX nie mogą zobaczyć Twojego profilu. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie mogą zobaczyć Twojego profilu. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Twój profil został zmieniony. Jeśli go zapiszesz, zaktualizowany profil zostanie wysłany do wszystkich kontaktów. + alert message + Your profile, contacts and delivered messages are stored on your device. Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu. @@ -7710,16 +8367,15 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. Twój losowy profil No comment provided by engineer. - - Your server - Twój serwer - No comment provided by engineer. - Your server address Twój adres serwera No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings Twoje ustawienia @@ -7760,6 +8416,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. zaakceptowane połączenie call status + + accepted invitation + chat list item title + admin administrator @@ -7842,6 +8502,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. call + zadzwoń No comment provided by engineer. @@ -7947,7 +8608,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. connecting… łączenie… - chat list item title + No comment provided by engineer. connection established @@ -8139,6 +8800,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. wygasły No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded przekazane dalej @@ -8216,6 +8881,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. invite + zaproś No comment provided by engineer. @@ -8275,6 +8941,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. message + wiadomość No comment provided by engineer. @@ -8309,6 +8976,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. mute + wycisz No comment provided by engineer. @@ -8433,6 +9101,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. usunął cię rcv group event chat item + + requested to connect + chat list item title + saved zapisane @@ -8445,6 +9117,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu. search + szukaj No comment provided by engineer. @@ -8533,6 +9206,7 @@ ostatnia otrzymana wiadomość: %2$@ unmute + wyłącz wyciszenie No comment provided by engineer. @@ -8582,6 +9256,7 @@ ostatnia otrzymana wiadomość: %2$@ video + wideo No comment provided by engineer. @@ -8755,6 +9430,33 @@ ostatnia otrzymana wiadomość: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
@@ -8762,14 +9464,17 @@ ostatnia otrzymana wiadomość: %2$@ SimpleX SE + SimpleX SE Bundle display name SimpleX SE + SimpleX SE Bundle name Copyright © 2024 SimpleX Chat. All rights reserved. + Copyright © 2024 SimpleX Chat. Wszelkie prawa zastrzeżone. Copyright (human-readable) @@ -8781,150 +9486,187 @@ ostatnia otrzymana wiadomość: %2$@ %@ + %@ No comment provided by engineer. App is locked! + Aplikacja zablokowana! No comment provided by engineer. Cancel + Anuluj No comment provided by engineer. Cannot access keychain to save database password + Nie można uzyskać dostępu do pęku kluczy aby zapisać hasło do bazy danych No comment provided by engineer. Cannot forward message + Nie można przekazać wiadomości No comment provided by engineer. Comment + Komentarz No comment provided by engineer. Currently maximum supported file size is %@. + Obecnie maksymalny obsługiwany rozmiar pliku to %@. No comment provided by engineer. Database downgrade required + Wymagane obniżenie wersji bazy danych No comment provided by engineer. Database encrypted! + Baza danych zaszyfrowana! No comment provided by engineer. Database error + Błąd bazy danych No comment provided by engineer. Database passphrase is different from saved in the keychain. + Hasło bazy danych jest inne niż zapisane w pęku kluczy. No comment provided by engineer. Database passphrase is required to open chat. + Hasło do bazy danych jest wymagane do otwarcia czatu. No comment provided by engineer. Database upgrade required + Wymagana aktualizacja bazy danych No comment provided by engineer. Error preparing file + Błąd przygotowania pliku No comment provided by engineer. Error preparing message + Błąd przygotowania wiadomości No comment provided by engineer. Error: %@ + Błąd: %@ No comment provided by engineer. File error + Błąd pliku No comment provided by engineer. Incompatible database version + Niekompatybilna wersja bazy danych No comment provided by engineer. Invalid migration confirmation + Nieprawidłowe potwierdzenie migracji No comment provided by engineer. Keychain error + Błąd pęku kluczy No comment provided by engineer. Large file! + Duży plik! No comment provided by engineer. No active profile + Brak aktywnego profilu No comment provided by engineer. Ok + Ok No comment provided by engineer. Open the app to downgrade the database. + Otwórz aplikację aby obniżyć wersję bazy danych. No comment provided by engineer. Open the app to upgrade the database. + Otwórz aplikację aby zaktualizować bazę danych. No comment provided by engineer. Passphrase + Hasło No comment provided by engineer. Please create a profile in the SimpleX app + Proszę utworzyć profil w aplikacji SimpleX No comment provided by engineer. Selected chat preferences prohibit this message. + Wybrane preferencje czatu zabraniają tej wiadomości. No comment provided by engineer. Sending a message takes longer than expected. + Wysłanie wiadomości trwa dłużej niż oczekiwano. No comment provided by engineer. Sending message… + Wysyłanie wiadomości… No comment provided by engineer. Share + Udostępnij No comment provided by engineer. Slow network? + Wolna sieć? No comment provided by engineer. Unknown database error: %@ + Nieznany błąd bazy danych: %@ No comment provided by engineer. Unsupported format + Niewspierany format No comment provided by engineer. Wait + Czekaj No comment provided by engineer. Wrong database passphrase + Nieprawidłowe hasło bazy danych No comment provided by engineer. You can allow sharing in Privacy & Security / SimpleX Lock settings. + Możesz zezwolić na udostępnianie w ustawieniach Prywatność i bezpieczeństwo / Blokada SimpleX. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/pl.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - diff --git a/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff b/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff index 0abab468fd..93ba6f357b 100644 --- a/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff +++ b/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff @@ -187,23 +187,18 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **Adicionar novo contato**: para criar seu QR Code ou link único para seu contato. - No comment provided by engineer. - **Create link / QR code** for your contact to use. **Crie um link / QR code** para seu contato usar. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Mais privado**: verifique as novas mensagens a cada 20 minutos. O token do dispositivo é compartilhado com o servidor do SimpleX Chat, mas não quantos contatos ou mensagens você tem. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Mais privado**: não use o servidor de notificações do SimpleX Chat, verifique as mensagens periodicamente em segundo plano (depende da frequência com que você usa o aplicativo). No comment provided by engineer. @@ -217,8 +212,8 @@ **Observação**: NÃO será possível recuperar ou alterar a frase secreta se você a perder. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Recomendado**: o token do dispositivo e as notificações são enviados para o servidor de notificações do SimpleX Chat, mas não o conteúdo, o tamanho ou o remetente da mensagem. No comment provided by engineer. @@ -1209,8 +1204,8 @@ Mensagens diretas chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. Mensagens diretas entre membros são proibidas neste grupo. No comment provided by engineer. @@ -1229,8 +1224,8 @@ Mensagens temporárias são proibidas nesse chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Mensagens que temporárias são proibidas neste grupo. No comment provided by engineer. @@ -1643,18 +1638,18 @@ Os membros do grupo podem excluir mensagens enviadas de forma irreversível. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. Os membros do grupo podem enviar DMs. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. Os membros do grupo podem enviar mensagens que desaparecem. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. Os membros do grupo podem enviar mensagens de voz. No comment provided by engineer. @@ -1761,8 +1756,8 @@ A imagem será recebida quando seu contato estiver online, aguarde ou verifique mais tarde! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Imune a spam e abuso No comment provided by engineer. @@ -1878,8 +1873,8 @@ A exclusão irreversível de mensagens é proibida neste chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. A exclusão irreversível de mensagens é proibida neste grupo. No comment provided by engineer. @@ -2209,8 +2204,8 @@ We will be adding server redundancy to prevent lost messages. Hosts Onion não serão usados. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2267,8 +2262,8 @@ We will be adding server redundancy to prevent lost messages. Abrir console de chat authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. Protocolo de código aberto – qualquer um pode executar os servidores. No comment provided by engineer. @@ -2306,8 +2301,8 @@ We will be adding server redundancy to prevent lost messages. Cole o link que você recebeu na caixa abaixo para conectar com o seu contato. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. Pessoas podem se conectar com você somente via links compartilhados. No comment provided by engineer. @@ -2961,8 +2956,8 @@ We will be adding server redundancy to prevent lost messages. Thank you for installing SimpleX Chat! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. A 1ª plataforma sem nenhum identificador de usuário – privada por design. No comment provided by engineer. @@ -2998,8 +2993,8 @@ We will be adding server redundancy to prevent lost messages. The microphone does not work when the app is in the background. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging A próxima geração de mensageiros privados No comment provided by engineer. @@ -3071,8 +3066,8 @@ We will be adding server redundancy to prevent lost messages. To prevent the call interruption, enable Do Not Disturb mode. 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -3274,8 +3269,8 @@ Para se conectar, peça ao seu contato para criar outro link de conexão e verif Mensagens de voz são proibidas neste chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Mensagens de voz são proibidas neste grupo. No comment provided by engineer. @@ -3402,10 +3397,6 @@ Para se conectar, peça ao seu contato para criar outro link de conexão e verif Você pode usar markdown para formatar mensagens: No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. Você não pôde ser verificado; por favor, tente novamente. @@ -5234,6 +5225,426 @@ Isso pode acontecer por causa de algum bug ou quando a conexão está comprometi %1$@ em %2$@: copied message info, <sender> at <time> + + Allow your contacts to irreversibly delete sent messages. (24 hours) + Permitir que seus contatos deletem mensagens enviadas de maneira irreversível. (24 horas) + + + %@ downloaded + baixado + + + %@ uploaded + transferido + + + A new random profile will be shared. + Um novo perfil aleatório será compartilhado. + + + Camera not available + Câmera indisponível + + + Admins can block a member for all. + Administradores podem bloquear um membro para todos. + + + Allow to irreversibly delete sent messages. (24 hours) + Permitir que mensagens enviadas sejam deletadas de maneira irreversível. (24 horas) + + + Apply + Aplicar + + + Accent + Esquema + + + Accept connection request? + Aceitar solicitação de conexão? + + + Active connections + Conexões ativas + + + Add contact + Adicionar contato + + + Additional accent + Esquema adicional + + + All new messages from %@ will be hidden! + Todas as novas mensagens de %@ serão ocultas! + + + All profiles + Todos perfis + + + Allow calls? + Permitir chamadas? + + + Archive contacts to chat later. + Arquivar contatos para conversar depois. + + + Blur media + Censurar mídia + + + Calls prohibited! + Chamadas proibidas! + + + Can't call contact + Não foi possível ligar para o contato + + + %lld messages marked deleted + mensagens deletadas + + + 0 sec + 0 seg + + + %lld messages blocked + mensagens bloqueadas + + + %lld messages blocked by admin + mensagens bloqueadas pelo administrador + + + **Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection. + **Nota**: usar o mesmo banco de dados em dois dispositivos irá quebrar a desencriptação das mensagens de suas conexões como uma medida de segurança. + + + - more stable message delivery. +- a bit better groups. +- and more! + - entrega de mensagens mais estável. +- grupos melhorados. +- e muito mais! + + + All messages will be deleted - this cannot be undone! + Todas as mensagens serão deletadas - isto não pode ser desfeito! + + + Allow to send files and media. + Permitir o envio de arquivos e mídia. + + + Allow to send SimpleX links. + Permitir envio de links SimpleX. + + + Block for all + Bloquear para todos + + + Block member + Bloquear membro + + + Blocked by admin + Bloqueado por um administrador + + + Block group members + Bloquear membros de grupo + + + Block member for all? + Bloquear membro para todos? + + + Block member? + Bloquear membro? + + + Both you and your contact can irreversibly delete sent messages. (24 hours) + Você e seu contato podem apagar mensagens enviadas de maneira irreversível. (24 horas) + + + Can't call member + Não foi possível ligar para este membro + + + Can't message member + Não foi possível enviar mensagem para este membro + + + Cancel migration + Cancelar migração + + + Abort + Abortar + + + Abort changing address + Abortar troca de endereço + + + Abort changing address? + Abortar troca de endereço? + + + - optionally notify deleted contacts. +- profile names with spaces. +- and more! + - notificar contatos apagados de maneira opcional. +- nome de perfil com espaços. +- e muito mais! + + + Allow sharing + Permitir compartilhamento + + + Block + Bloquear + + + Additional accent 2 + Esquema adicional 2 + + + Address change will be aborted. Old receiving address will be used. + Alteração de endereço será abortada. O endereço antigo será utilizado. + + + Advanced settings + Configurações avançadas + + + All data is kept private on your device. + Toda informação é privada em seu dispositivo. + + + All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays. + Todos os seus contatos, conversas e arquivos serão encriptados e enviados em pedaços para nós XFTP. + + + Allow irreversible message deletion only if your contact allows it to you. (24 hours) + Permitir deletar mensagens de maneira irreversível apenas se seu contato permitir para você. (24 horas) + + + Already connecting! + Já está conectando! + + + Already joining the group! + Já está entrando no grupo! + + + Always use private routing. + Sempre use rotas privadas. + + + Apply to + Aplicar em + + + Archiving database + Arquivando banco de dados + + + Black + Preto + + + Cannot forward message + Não é possível encaminhar mensagem + + + (new) + (novo) + + + (this device v%@) + este dispositivo + + + **Create 1-time link**: to create and share a new invitation link. + **Adicionar contato**: criar um novo link de convite ou conectar via um link que você recebeu. + + + **Create group**: to create a new group. + **Criar grupo**: criar um novo grupo. + + + **Warning**: the archive will be removed. + **Aviso**: o arquivo será removido. + + + A few more things + E mais algumas coisas + + + Archived contacts + Contatos arquivados + + + Cellular + Rede móvel + + + %d file(s) failed to download. + %d arquivo(s) falharam ao ser baixados. + + + %d file(s) were deleted. + %d arquivo(s) foram apagados. + + + %d messages not forwarded + %d mensagens não encaminhadas + + + Bad desktop address + Endereço de desktop incorreto + + + Blur for better privacy. + Borrar para melhor privacidade. + + + %d file(s) are still being downloaded. + %d arquivo(s) ainda estão sendo baixados. + + + %d file(s) were not downloaded. + %d arquivo(s) não foram baixados. + + + Chat colors + Cores do chat + + + %lld group events + %lld eventos do grupo + + + %lld messages moderated by %@ + %lld mensagens moderadas por %@ + + + %1$@, %2$@ + %1$@, %2$@ + + + %lld new interface languages + %lld novos idiomas de interface + + + Better networking + Melhores redes + + + Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + Búlgaro, Finlandês, Tailandês e Ucraniano - obrigado aos usuários e [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! + + + Better groups + Melhores grupos + + + Capacity exceeded - recipient did not receive previously sent messages. + Capacidade excedida - o destinatário não recebeu as mensagens enviadas anteriormente. + + + Chat migrated! + Conversa migrada! + + + Auto-accept settings + Aceitar automaticamente configurações + + + App encrypts new local files (except videos). + O aplicativo criptografa novos arquivos locais (exceto videos). + + + App session + Sessão do aplicativo + + + Acknowledged + Reconhecido + + + Acknowledgement errors + Erros conhecidos + + + Chat list + Lista de conversas + + + Chat database exported + Banco de dados da conversa exportado + + + Chat preferences were changed. + As preferências de bate-papo foram alteradas. + + + Chat theme + Tema da conversa + + + Better calls + Chamadas melhores + + + Better user experience + Melhor experiência do usuário + + + Allow downgrade + Permitir redução + + + Additional secondary + Secundária adicional + + + App data migration + Migração de dados do aplicativo + + + Archive and upload + Arquivar e enviar + + + Background + Fundo + + + Better message dates. + Datas de mensagens melhores. + + + Better notifications + Notificações melhores + + + Better security ✅ + Melhor segurança ✅ + + + Chat profile + Perfil da conversa + diff --git a/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff b/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff index a9bf86e778..de1787bdad 100644 --- a/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff +++ b/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff @@ -214,22 +214,17 @@ Available in v5.1 ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **Adicionar novo contato**: para criar seu QR Code único ou link para seu contato. - No comment provided by engineer. - **Create link / QR code** for your contact to use. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Mais privado**: verifique novas mensagens a cada 20 minutos. O token do dispositivo é compartilhado com o servidor SimpleX Chat, mas não com quantos contatos ou mensagens você possui. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Totalmente privado**: não use o servidor de notificações do SimpleX Chat, verifique as mensagens periodicamente em segundo plano (depende da frequência com que você usa o aplicativo). No comment provided by engineer. @@ -242,8 +237,8 @@ Available in v5.1 **Atenção**: Você NÃO poderá recuperar ou alterar a senha caso a perca. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Recomendado**: O token do dispositivo e as notificações são enviados ao servidor de notificação do SimpleX Chat, mas não o conteúdo, o tamanho da mensagem ou de quem ela é. No comment provided by engineer. @@ -1232,8 +1227,8 @@ Available in v5.1 Direct messages chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. No comment provided by engineer. @@ -1248,8 +1243,8 @@ Available in v5.1 Disappearing messages are prohibited in this chat. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. No comment provided by engineer. @@ -1684,16 +1679,16 @@ Available in v5.1 Group members can irreversibly delete sent messages. No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. No comment provided by engineer. @@ -1812,8 +1807,8 @@ Available in v5.1 Immediately No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam No comment provided by engineer. @@ -1925,8 +1920,8 @@ Available in v5.1 Irreversible message deletion is prohibited in this chat. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. No comment provided by engineer. @@ -2120,8 +2115,8 @@ Available in v5.1 Migration is completed No comment provided by engineer. - - Migrations: %@ + + Migrations: No comment provided by engineer. @@ -2278,8 +2273,8 @@ Available in v5.1 Onion hosts will not be used. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. No comment provided by engineer. @@ -2338,8 +2333,8 @@ Available in v5.1 Open user profiles authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. No comment provided by engineer. @@ -2394,8 +2389,8 @@ Available in v5.1 Paste the link you received into the box below to connect with your contact. No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. No comment provided by engineer. @@ -3098,8 +3093,8 @@ Available in v5.1 Thanks to the users – contribute via Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. No comment provided by engineer. @@ -3143,8 +3138,8 @@ It can happen because of some bug or when the connection is compromised.The message will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging No comment provided by engineer. @@ -3215,8 +3210,8 @@ It can happen because of some bug or when the connection is compromised.To make a new connection 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. No comment provided by engineer. @@ -3441,8 +3436,8 @@ To connect, please ask your contact to create another connection link and check Voice messages are prohibited in this chat. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. No comment provided by engineer. @@ -3582,10 +3577,6 @@ SimpleX Lock must be enabled. You can't send messages! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - No comment provided by engineer. - You could not be verified; please try again. No comment provided by engineer. @@ -4302,8 +4293,8 @@ SimpleX servers cannot see your profile. %lld novas interface de idiomas No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **Adicionar contato**: para criar um novo link de convite ou conectar-se por meio de um link que você recebeu. No comment provided by engineer. 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 8bbf054868..5809c65216 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ подтверждён No comment provided by engineer. + + %@ server + %@ сервер + No comment provided by engineer. + + + %@ servers + %@ серверы + No comment provided by engineer. + %@ uploaded %@ загружено @@ -137,6 +132,11 @@ %@ хочет соединиться! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ и %lld членов группы @@ -157,11 +157,36 @@ %d дней time interval + + %d file(s) are still being downloaded. + %d файл(ов) загружаются. + forward confirmation reason + + + %d file(s) failed to download. + %d файл(ов) не удалось загрузить. + forward confirmation reason + + + %d file(s) were deleted. + %d файлов было удалено. + forward confirmation reason + + + %d file(s) were not downloaded. + %d файлов не было загружено. + forward confirmation reason + %d hours %d ч. time interval + + %d messages not forwarded + %d сообщений не переслано + alert title + %d min %d мин @@ -322,14 +347,9 @@ ) 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 or link for your contact. - **Добавить новый контакт**: чтобы создать одноразовый QR код или ссылку для Вашего контакта. + + **Create 1-time link**: to create and share a new invitation link. + **Добавить контакт**: создать и поделиться новой ссылкой-приглашением. No comment provided by engineer. @@ -337,14 +357,14 @@ **Создать группу**: создать новую группу. 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, но у сервера не будет информации о количестве контактов и сообщений. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. + **Более конфиденциально**: проверять новые сообщения каждые 20 минут. Только токен устройства будет отправлен на сервер уведомлений SimpleX Chat, но у сервера не будет информации о количестве контактов и какой либо информации о сообщениях. 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, проверять сообщения периодически в фоновом режиме (зависит от того насколько часто Вы используете приложение). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. + **Самый конфиденциальный**: не использовать сервер уведомлений SimpleX Chat. Сообщения проверяются в фоновом режиме, когда система позволяет, в зависимости от того, как часто Вы используете приложение. No comment provided by engineer. @@ -357,11 +377,16 @@ **Внимание**: Вы не сможете восстановить или поменять пароль, если Вы его потеряете. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Рекомендовано**: токен устройства и уведомления отправляются на сервер SimpleX Chat, но сервер не получает сами сообщения, их размер или от кого они. No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + **Сканировать / Вставить ссылку**: чтобы соединиться через полученную ссылку. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **Внимание**: для работы мгновенных уведомлений пароль должен быть сохранен в Keychain. @@ -468,6 +493,16 @@ 1 неделю time interval + + 1-time link + Одноразовая ссылка + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Одноразовая ссылка может быть использована *только с одним контактом* - поделитесь при встрече или через любой мессенджер. + No comment provided by engineer. + 5 minutes 5 минут @@ -537,19 +572,14 @@ Прекратить изменение адреса? No comment provided by engineer. - - About SimpleX - О SimpleX - No comment provided by engineer. - About SimpleX Chat Информация о SimpleX Chat No comment provided by engineer. - - About SimpleX address - Об адресе SimpleX + + About operators + Об операторах No comment provided by engineer. @@ -564,6 +594,11 @@ accept incoming call via notification swipe action + + Accept conditions + Принять условия + No comment provided by engineer. + Accept connection request? Принять запрос? @@ -580,6 +615,11 @@ accept contact request via notification swipe action + + Accepted conditions + Принятые условия + No comment provided by engineer. + Acknowledged Подтверждено @@ -600,14 +640,9 @@ Добавьте адрес в свой профиль, чтобы Ваши контакты могли поделиться им. Профиль будет отправлен Вашим контактам. No comment provided by engineer. - - Add contact - Добавить контакт - No comment provided by engineer. - - - Add preset servers - Добавить серверы по умолчанию + + Add friends + Добавить друзей No comment provided by engineer. @@ -625,6 +660,11 @@ Добавить серверы через QR код. No comment provided by engineer. + + Add team members + Добавить сотрудников + No comment provided by engineer. + Add to another device Добавить на другое устройство @@ -635,6 +675,21 @@ Добавить приветственное сообщение No comment provided by engineer. + + Add your team members to the conversations. + Добавьте сотрудников в разговор. + No comment provided by engineer. + + + Added media & file servers + Дополнительные серверы файлов и медиа + No comment provided by engineer. + + + Added message servers + Дополнительные серверы сообщений + No comment provided by engineer. + Additional accent Дополнительный акцент @@ -660,6 +715,16 @@ Изменение адреса будет прекращено. Будет использоваться старый адрес. No comment provided by engineer. + + Address or 1-time link? + Адрес или одноразовая ссылка? + No comment provided by engineer. + + + Address settings + Настройки адреса + No comment provided by engineer. + Admins can block a member for all. Админы могут заблокировать члена группы. @@ -695,8 +760,8 @@ Все данные удаляются при его вводе. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. Все данные хранятся только на вашем устройстве. No comment provided by engineer. @@ -705,6 +770,11 @@ Все члены группы, которые соединились через эту ссылку, останутся в группе. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Все сообщения и файлы отправляются с **end-to-end шифрованием**, с постквантовой безопасностью в прямых разговорах. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Все сообщения будут удалены - это нельзя отменить! @@ -723,7 +793,7 @@ All profiles Все профили - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -885,6 +955,11 @@ Принять звонок No comment provided by engineer. + + Anybody can host servers. + Кто угодно может запустить сервер. + No comment provided by engineer. + App build: %@ Сборка приложения: %@ @@ -915,6 +990,11 @@ Код доступа в приложение будет заменен кодом самоуничтожения. No comment provided by engineer. + + App session + Сессия приложения + No comment provided by engineer. + App version Версия приложения @@ -1020,6 +1100,11 @@ Автоприем изображений No comment provided by engineer. + + Auto-accept settings + Настройки автоприема + alert title + Back Назад @@ -1045,11 +1130,21 @@ Ошибка хэш сообщения No comment provided by engineer. + + Better calls + Улучшенные звонки + No comment provided by engineer. + Better groups Улучшенные группы No comment provided by engineer. + + Better message dates. + Улучшенные даты сообщений. + No comment provided by engineer. + Better messages Улучшенные сообщения @@ -1060,6 +1155,21 @@ Улучшенные сетевые функции No comment provided by engineer. + + Better notifications + Улучшенные уведомления + No comment provided by engineer. + + + Better security ✅ + Улучшенная безопасность ✅ + No comment provided by engineer. + + + Better user experience + Улучшенный интерфейс + No comment provided by engineer. + Black Черная @@ -1140,6 +1250,16 @@ Болгарский, финский, тайский и украинский - благодаря пользователям и [Weblate] (https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + Бизнес адрес + No comment provided by engineer. + + + Business chats + Бизнес разговоры + 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) (БЕТА). @@ -1193,7 +1313,8 @@ Cancel Отменить - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1213,7 +1334,7 @@ Cannot receive file Невозможно получить файл - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1230,6 +1351,11 @@ Поменять No comment provided by engineer. + + Change chat profiles + Поменять профили + authentication reason + Change database passphrase? Поменять пароль базы данных? @@ -1276,9 +1402,19 @@ authentication reason set passcode view - - Chat archive - Архив чата + + Chat + Разговор + No comment provided by engineer. + + + Chat already exists + Разговор уже существует + No comment provided by engineer. + + + Chat already exists! + Разговор уже существует! No comment provided by engineer. @@ -1341,20 +1477,50 @@ Предпочтения No comment provided by engineer. + + Chat preferences were changed. + Настройки чата были изменены. + alert message + + + Chat profile + Профиль чата + No comment provided by engineer. + Chat theme Тема чата No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + Разговор будет удален для всех участников - это действие нельзя отменить! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + Разговор будет удален для Вас - это действие нельзя отменить! + No comment provided by engineer. + Chats Чаты No comment provided by engineer. + + Check messages every 20 min. + Проверять сообщения каждые 20 минут. + No comment provided by engineer. + + + Check messages when allowed. + Проверять сообщения по возможности. + No comment provided by engineer. + Check server address and try again. Проверьте адрес сервера и попробуйте снова. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1418,7 +1584,7 @@ Color chats with the new themes. - Добавьте цвета к чатам в настройках тем. + Добавьте цвета к чатам в настройках. No comment provided by engineer. @@ -1441,16 +1607,56 @@ Готово No comment provided by engineer. + + Conditions accepted on: %@. + Условия приняты: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Условия приняты для оператора(ов): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Условия уже приняты для следующих оператора(ов): **%@**. + No comment provided by engineer. + + + Conditions of use + Условия использования + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Условия будут приняты для включенных операторов через 30 дней. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Условия будут приняты для оператора(ов): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Условия будут приняты для оператора(ов): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Условия будут приняты: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Условия будут автоматически приняты для включенных операторов: %@. + No comment provided by engineer. + Configure ICE servers Настройка ICE серверов No comment provided by engineer. - - Configured %@ servers - Настроенные %@ серверы - No comment provided by engineer. - Confirm Подтвердить @@ -1640,6 +1846,11 @@ This is your own one-time link! Запрос на соединение отправлен! No comment provided by engineer. + + Connection security + Безопасность соединения + No comment provided by engineer. + Connection terminated Подключение прервано @@ -1740,6 +1951,11 @@ This is your own one-time link! Версия ядра: v%@ No comment provided by engineer. + + Corner + Угол + No comment provided by engineer. + Correct name to %@? Исправить имя на %@? @@ -1750,6 +1966,11 @@ This is your own one-time link! Создать No comment provided by engineer. + + Create 1-time link + Создать одноразовую ссылку + No comment provided by engineer. + Create SimpleX address Создать адрес SimpleX @@ -1760,11 +1981,6 @@ This is your own one-time link! Создайте группу, используя случайный профиль. No comment provided by engineer. - - Create an address to let people connect with you. - Создайте адрес, чтобы можно было соединиться с вами. - No comment provided by engineer. - Create file Создание файла @@ -1825,11 +2041,6 @@ This is your own one-time link! Создано: %@ copied message info - - Created on %@ - Дата создания %@ - No comment provided by engineer. - Creating archive link Создание ссылки на архив @@ -1845,6 +2056,11 @@ This is your own one-time link! Текущий Код No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + Текст условий использования не может быть показан, вы можете посмотреть их через ссылку: + No comment provided by engineer. + Current passphrase… Текущий пароль… @@ -1865,6 +2081,11 @@ This is your own one-time link! Пользовательское время No comment provided by engineer. + + Customizable message shape. + Настраиваемая форма сообщений. + No comment provided by engineer. + Customize theme Настроить тему @@ -1996,7 +2217,8 @@ This is your own one-time link! Delete Удалить - chat item action + alert action + chat item action swipe action @@ -2034,14 +2256,9 @@ This is your own one-time link! Удалить и уведомить контакт No comment provided by engineer. - - Delete archive - Удалить архив - No comment provided by engineer. - - - Delete chat archive? - Удалить архив чата? + + Delete chat + Удалить разговор No comment provided by engineer. @@ -2054,6 +2271,11 @@ This is your own one-time link! Удалить профиль? No comment provided by engineer. + + Delete chat? + Удалить разговор? + No comment provided by engineer. + Delete connection Удалить соединение @@ -2159,6 +2381,11 @@ This is your own one-time link! Удалить предыдущую версию данных? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Удаляйте или модерируйте до 200 сообщений. + No comment provided by engineer. + Delete pending connection? Удалить ожидаемое соединение? @@ -2176,7 +2403,7 @@ This is your own one-time link! Delete up to 20 messages at once. - Удаляйте до 20 сообщений одновременно. + Удаляйте до 20 сообщений за раз. No comment provided by engineer. @@ -2209,6 +2436,11 @@ This is your own one-time link! Ошибки удаления No comment provided by engineer. + + Delivered even when Apple drops them. + Доставляются даже тогда, когда Apple их теряет. + No comment provided by engineer. + Delivery Доставка @@ -2309,8 +2541,13 @@ This is your own one-time link! Прямые сообщения chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + Прямые сообщения между членами запрещены в этом разговоре. + No comment provided by engineer. + + + Direct messages between members are prohibited. Прямые сообщения между членами группы запрещены. No comment provided by engineer. @@ -2349,8 +2586,8 @@ This is your own one-time link! Исчезающие сообщения запрещены в этом чате. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Исчезающие сообщения запрещены в этой группе. No comment provided by engineer. @@ -2409,6 +2646,11 @@ This is your own one-time link! Не отправлять историю новым членам. No comment provided by engineer. + + Do not use credentials with proxy. + Не использовать учетные данные с прокси. + No comment provided by engineer. + Don't create address Не создавать адрес @@ -2432,7 +2674,8 @@ This is your own one-time link! Download Загрузить - chat item action + alert button + chat item action Download errors @@ -2449,6 +2692,11 @@ This is your own one-time link! Загрузка файла server test step + + Download files + Загрузить файлы + alert action + Downloaded Принято @@ -2479,6 +2727,11 @@ This is your own one-time link! Длительность No comment provided by engineer. + + E2E encrypted notifications. + E2E зашифрованные нотификации. + No comment provided by engineer. + Edit Редактировать @@ -2499,6 +2752,11 @@ This is your own one-time link! Включить (кроме исключений) No comment provided by engineer. + + Enable Flux + Включить Flux + No comment provided by engineer. + Enable SimpleX Lock Включить блокировку SimpleX @@ -2704,26 +2962,36 @@ This is your own one-time link! Ошибка при прекращении изменения адреса No comment provided by engineer. + + Error accepting conditions + Ошибка приема условий + alert title + Error accepting contact request Ошибка при принятии запроса на соединение No comment provided by engineer. - - Error accessing database file - Ошибка при доступе к данным чата - No comment provided by engineer. - Error adding member(s) Ошибка при добавлении членов группы No comment provided by engineer. + + Error adding server + Ошибка добавления сервера + alert title + Error changing address Ошибка при изменении адреса No comment provided by engineer. + + Error changing connection profile + Ошибка при изменении профиля соединения + No comment provided by engineer. + Error changing role Ошибка при изменении роли @@ -2734,6 +3002,11 @@ This is your own one-time link! Ошибка при изменении настройки No comment provided by engineer. + + Error changing to incognito! + Ошибка при смене на Инкогнито! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. Ошибка подключения к пересылающему серверу %@. Попробуйте позже. @@ -2849,9 +3122,14 @@ This is your own one-time link! Ошибка при вступлении в группу No comment provided by engineer. - - Error loading %@ servers - Ошибка загрузки %@ серверов + + Error loading servers + Ошибка загрузки серверов + alert title + + + Error migrating settings + Ошибка миграции настроек No comment provided by engineer. @@ -2862,7 +3140,7 @@ This is your own one-time link! Error receiving file Ошибка при получении файла - No comment provided by engineer. + alert title Error reconnecting server @@ -2884,11 +3162,6 @@ This is your own one-time link! Ошибка сброса статистики No comment provided by engineer. - - Error saving %@ servers - Ошибка при сохранении %@ серверов - No comment provided by engineer. - Error saving ICE servers Ошибка при сохранении ICE серверов @@ -2909,6 +3182,11 @@ This is your own one-time link! Ошибка сохранения пароля в Keychain No comment provided by engineer. + + Error saving servers + Ошибка сохранения серверов + alert title + Error saving settings Ошибка сохранения настроек @@ -2954,10 +3232,15 @@ This is your own one-time link! Ошибка при остановке чата No comment provided by engineer. + + Error switching profile + Ошибка переключения профиля + No comment provided by engineer. + Error switching profile! Ошибка выбора профиля! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2974,6 +3257,11 @@ This is your own one-time link! Ошибка при обновлении сообщения No comment provided by engineer. + + Error updating server + Ошибка сохранения сервера + alert title + Error updating settings Ошибка при сохранении настроек сети @@ -3002,8 +3290,7 @@ This is your own one-time link! Error: %@ Ошибка: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -3020,6 +3307,11 @@ This is your own one-time link! Ошибки No comment provided by engineer. + + Errors in servers configuration. + Ошибки в настройках серверов. + servers error + Even when disabled in the conversation. Даже когда они выключены в разговоре. @@ -3090,6 +3382,13 @@ This is your own one-time link! Ошибка файла No comment provided by engineer. + + File errors: +%@ + Ошибки файлов: +%@ + alert message + File not found - most likely file was deleted or cancelled. Файл не найден - скорее всего, файл был удален или отменен. @@ -3145,8 +3444,8 @@ This is your own one-time link! Файлы и медиа chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Файлы и медиа запрещены в этой группе. No comment provided by engineer. @@ -3215,21 +3514,61 @@ This is your own one-time link! Починка не поддерживается членом группы No comment provided by engineer. + + For chat profile %@: + Для профиля чата %@: + servers error + For console Для консоли No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Например, если Ваш контакт получает сообщения через сервер SimpleX Chat, Ваше приложение доставит их через сервер Flux. + No comment provided by engineer. + + + For private routing + Для доставки сообщений + No comment provided by engineer. + + + For social media + Для социальных сетей + No comment provided by engineer. + Forward Переслать chat item action + + Forward %d message(s)? + Переслать %d сообщение(й)? + alert title + Forward and save messages Переслать и сохранить сообщение No comment provided by engineer. + + Forward messages + Переслать сообщения + alert action + + + Forward messages without files? + Переслать сообщения без файлов? + alert message + + + Forward up to 20 messages at once. + Пересылайте до 20 сообщений за раз. + No comment provided by engineer. + Forwarded Переслано @@ -3240,6 +3579,11 @@ This is your own one-time link! Переслано из No comment provided by engineer. + + Forwarding %lld messages + Пересылка %lld сообщений + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. Пересылающий сервер %@ не смог подключиться к серверу назначения %@. Попробуйте позже. @@ -3289,11 +3633,6 @@ Error: %2$@ Полное имя (не обязательно) No comment provided by engineer. - - Full name: - Полное имя: - No comment provided by engineer. - Fully decentralized – visible only to members. Группа полностью децентрализована – она видна только членам. @@ -3379,41 +3718,6 @@ Error: %2$@ Ссылки групп No comment provided by engineer. - - Group members can add message reactions. - Члены группы могут добавлять реакции на сообщения. - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - Члены группы могут необратимо удалять отправленные сообщения. (24 часа) - No comment provided by engineer. - - - Group members can send SimpleX links. - Члены группы могут отправлять ссылки SimpleX. - No comment provided by engineer. - - - Group members can send direct messages. - Члены группы могут посылать прямые сообщения. - No comment provided by engineer. - - - Group members can send disappearing messages. - Члены группы могут посылать исчезающие сообщения. - No comment provided by engineer. - - - Group members can send files and media. - Члены группы могут слать файлы и медиа. - No comment provided by engineer. - - - Group members can send voice messages. - Члены группы могут отправлять голосовые сообщения. - No comment provided by engineer. - Group message: Групповое сообщение: @@ -3509,9 +3813,14 @@ Error: %2$@ Как SimpleX работает No comment provided by engineer. - - How it works - Как это работает + + How it affects privacy + Как это влияет на конфиденциальность + No comment provided by engineer. + + + How it helps privacy + Как это улучшает конфиденциальность No comment provided by engineer. @@ -3521,7 +3830,7 @@ Error: %2$@ How to use it - Как использовать + Про адрес No comment provided by engineer. @@ -3539,6 +3848,11 @@ Error: %2$@ ICE серверы (один на строке) No comment provided by engineer. + + IP address + IP адрес + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. Если Вы не можете встретиться лично, покажите QR-код во время видеозвонка или поделитесь ссылкой. @@ -3579,8 +3893,8 @@ Error: %2$@ Сразу No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Защищен от спама No comment provided by engineer. @@ -3614,6 +3928,12 @@ Error: %2$@ Импорт архива No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Улучшенная доставка, меньше трафик. + No comment provided by engineer. + Improved message delivery Улучшенная доставка сообщений @@ -3714,6 +4034,11 @@ Error: %2$@ [SimpleX Chat для терминала](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Мгновенно + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3721,11 +4046,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Мгновенно - No comment provided by engineer. - Interface Интерфейс @@ -3774,7 +4094,7 @@ Error: %2$@ Invalid server address! Ошибка в адресе сервера! - No comment provided by engineer. + alert title Invalid status @@ -3796,6 +4116,11 @@ Error: %2$@ Пригласить членов группы No comment provided by engineer. + + Invite to chat + Пригласить в разговор + No comment provided by engineer. + Invite to group Пригласить в группу @@ -3811,8 +4136,8 @@ Error: %2$@ Необратимое удаление сообщений запрещено в этом чате. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Необратимое удаление сообщений запрещено в этой группе. No comment provided by engineer. @@ -3902,7 +4227,7 @@ This is your link for group %@! Keep Оставить - No comment provided by engineer. + alert action Keep conversation @@ -3917,7 +4242,7 @@ This is your link for group %@! Keep unused invitation? Оставить неиспользованное приглашение? - No comment provided by engineer. + alert title Keep your connections @@ -3954,6 +4279,16 @@ This is your link for group %@! Выйти swipe action + + Leave chat + Покинуть разговор + No comment provided by engineer. + + + Leave chat? + Покинуть разговор? + No comment provided by engineer. + Leave group Выйти из группы @@ -4004,11 +4339,6 @@ This is your link for group %@! "Живые" сообщения No comment provided by engineer. - - Local - Локальные - No comment provided by engineer. - Local name Локальное имя @@ -4029,11 +4359,6 @@ This is your link for group %@! Режим блокировки No comment provided by engineer. - - Make a private connection - Добавьте контакт - No comment provided by engineer. - Make one message disappear Одно исчезающее сообщение @@ -4044,21 +4369,11 @@ This is your link for group %@! Сделайте профиль скрытым! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Пожалуйста, проверьте, что адреса %@ серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Пожалуйста, проверьте, что адреса WebRTC ICE серверов имеют правильный формат, каждый адрес на отдельной строке и не повторяется. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Много пользователей спросили: *как SimpleX доставляет сообщения без идентификаторов пользователей?* - No comment provided by engineer. - Mark deleted for everyone Пометить как удаленное для всех @@ -4104,6 +4419,11 @@ This is your link for group %@! Член неактивен item status text + + Member role will be changed to "%@". All chat members will be notified. + Роль участника будет изменена на "%@". Все участники разговора получат уведомление. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Роль члена группы будет изменена на "%@". Все члены группы получат сообщение. @@ -4114,11 +4434,51 @@ This is your link for group %@! Роль члена группы будет изменена на "%@". Будет отправлено новое приглашение. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + Член будет удален из разговора - это действие нельзя отменить! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Член группы будет удален - это действие нельзя отменить! No comment provided by engineer. + + Members can add message reactions. + Члены группы могут добавлять реакции на сообщения. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Члены группы могут необратимо удалять отправленные сообщения. (24 часа) + No comment provided by engineer. + + + Members can send SimpleX links. + Члены группы могут отправлять ссылки SimpleX. + No comment provided by engineer. + + + Members can send direct messages. + Члены группы могут посылать прямые сообщения. + No comment provided by engineer. + + + Members can send disappearing messages. + Члены группы могут посылать исчезающие сообщения. + No comment provided by engineer. + + + Members can send files and media. + Члены группы могут слать файлы и медиа. + No comment provided by engineer. + + + Members can send voice messages. + Члены группы могут отправлять голосовые сообщения. + No comment provided by engineer. + Menus Меню @@ -4169,8 +4529,8 @@ This is your link for group %@! Реакции на сообщения в этом чате запрещены. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Реакции на сообщения запрещены в этой группе. No comment provided by engineer. @@ -4184,6 +4544,11 @@ This is your link for group %@! Серверы сообщений No comment provided by engineer. + + Message shape + Форма сообщений + No comment provided by engineer. + Message source remains private. Источник сообщения остаётся конфиденциальным. @@ -4234,6 +4599,11 @@ This is your link for group %@! Сообщений отправлено No comment provided by engineer. + + Messages were deleted after you selected them. + Сообщения были удалены после того, как вы их выбрали. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Сообщения, файлы и звонки защищены **end-to-end шифрованием** с прямой секретностью (PFS), правдоподобным отрицанием и восстановлением от взлома. @@ -4299,9 +4669,9 @@ This is your link for group %@! Перемещение данных завершено No comment provided by engineer. - - Migrations: %@ - Миграции: %@ + + Migrations: + Миграции: No comment provided by engineer. @@ -4329,6 +4699,11 @@ This is your link for group %@! Более надежное соединение с сетью. No comment provided by engineer. + + More reliable notifications + Более надежные уведомления + No comment provided by engineer. + Most likely this connection is deleted. Скорее всего, соединение удалено. @@ -4364,6 +4739,11 @@ This is your link for group %@! Интернет-соединение No comment provided by engineer. + + Network decentralization + Децентрализация сети + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Ошибка сети - сообщение не было отправлено после многократных попыток. @@ -4374,6 +4754,11 @@ This is your link for group %@! Статус сети No comment provided by engineer. + + Network operator + Оператор сети + No comment provided by engineer. + Network settings Настройки сети @@ -4389,6 +4774,16 @@ This is your link for group %@! Новый Код No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Новые учетные данные SOCKS будут использоваться при каждом запуске приложения. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Новые учетные данные SOCKS будут использоваться для каждого сервера. + No comment provided by engineer. + New chat Новый чат @@ -4409,11 +4804,6 @@ This is your link for group %@! Новый контакт: notification - - New database archive - Новый архив чата - No comment provided by engineer. - New desktop app! Приложение для компьютера! @@ -4424,6 +4814,11 @@ This is your link for group %@! Новое имя No comment provided by engineer. + + New events + Новые события + notification + New in %@ Новое в %@ @@ -4449,6 +4844,11 @@ This is your link for group %@! Новый пароль… No comment provided by engineer. + + New server + Новый сервер + No comment provided by engineer. + No Нет @@ -4504,21 +4904,71 @@ This is your link for group %@! Нет информации, попробуйте перезагрузить No comment provided by engineer. + + No media & file servers. + Нет серверов файлов и медиа. + servers error + + + No message servers. + Нет серверов сообщений. + servers error + No network connection Нет интернет-соединения No comment provided by engineer. + + No permission to record speech + Нет разрешения на запись речи + No comment provided by engineer. + + + No permission to record video + Нет разрешения на запись видео + No comment provided by engineer. + No permission to record voice message Нет разрешения для записи голосового сообщения No comment provided by engineer. + + No push server + Без сервера нотификаций + No comment provided by engineer. + No received or sent files Нет полученных или отправленных файлов No comment provided by engineer. + + No servers for private message routing. + Нет серверов для доставки сообщений. + servers error + + + No servers to receive files. + Нет серверов для приема файлов. + servers error + + + No servers to receive messages. + Нет серверов для приема сообщений. + servers error + + + No servers to send files. + Нет серверов для отправки файлов. + servers error + + + No user identifiers. + Без идентификаторов пользователей. + No comment provided by engineer. + Not compatible! Несовместимая версия! @@ -4529,6 +4979,11 @@ This is your link for group %@! Ничего не выбрано No comment provided by engineer. + + Nothing to forward! + Нет сообщений, которые можно переслать! + alert title + Notifications Уведомления @@ -4539,6 +4994,11 @@ This is your link for group %@! Уведомления выключены No comment provided by engineer. + + Notifications privacy + Конфиденциальность уведомлений + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4561,18 +5021,13 @@ This is your link for group %@! Ok Ок - No comment provided by engineer. + alert button Old database Предыдущая версия данных чата No comment provided by engineer. - - Old database archive - Старый архив чата - No comment provided by engineer. - One-time invitation link Одноразовая ссылка @@ -4597,9 +5052,14 @@ Requires compatible VPN. Onion хосты не используются. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. - Только пользовательские устройства хранят контакты, группы и сообщения, которые отправляются **с двухуровневым end-to-end шифрованием**. + + Only chat owners can change preferences. + Только владельцы разговора могут поменять предпочтения. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. + Только пользовательские устройства хранят контакты, группы и сообщения. No comment provided by engineer. @@ -4682,6 +5142,11 @@ Requires compatible VPN. Открыть Настройки No comment provided by engineer. + + Open changes + Открыть изменения + No comment provided by engineer. + Open chat Открыть чат @@ -4692,6 +5157,11 @@ Requires compatible VPN. Открыть консоль authentication reason + + Open conditions + Открыть условия + No comment provided by engineer. + Open group Открыть группу @@ -4702,26 +5172,26 @@ Requires compatible VPN. Открытие миграции на другое устройство authentication reason - - Open server settings - Открыть настройки серверов - No comment provided by engineer. - - - Open user profiles - Открыть профили пользователя - authentication reason - - - Open-source protocol and code – anybody can run the servers. - Открытый протокол и код - кто угодно может запустить сервер. - No comment provided by engineer. - Opening app… Приложение отрывается… No comment provided by engineer. + + Operator + Оператор + No comment provided by engineer. + + + Operator server + Сервер оператора + alert title + + + Or import archive file + Или импортировать файл архива + No comment provided by engineer. + Or paste archive link Или вставьте ссылку архива @@ -4742,15 +5212,22 @@ Requires compatible VPN. Или покажите этот код No comment provided by engineer. + + Or to share privately + Или поделиться конфиденциально + No comment provided by engineer. + Other Другaя сеть No comment provided by engineer. - - Other %@ servers - Другие %@ серверы - No comment provided by engineer. + + Other file errors: +%@ + Другие ошибки файлов: +%@ + alert message PING count @@ -4787,6 +5264,11 @@ Requires compatible VPN. Код доступа установлен! No comment provided by engineer. + + Password + Пароль + No comment provided by engineer. + Password to show Пароль чтобы раскрыть @@ -4822,13 +5304,8 @@ Requires compatible VPN. В ожидании No comment provided by engineer. - - People can connect to you only via the links you share. - С Вами можно соединиться только через созданные Вами ссылки. - No comment provided by engineer. - - - Periodically + + Periodic Периодически No comment provided by engineer. @@ -4936,6 +5413,11 @@ Error: %@ Польский интерфейс No comment provided by engineer. + + Port + Порт + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Возможно, хэш сертификата в адресе сервера неверный @@ -4946,16 +5428,16 @@ Error: %@ Сохранить последний черновик, вместе с вложениями. No comment provided by engineer. - - Preset server - Сервер по умолчанию - No comment provided by engineer. - Preset server address Адрес сервера по умолчанию No comment provided by engineer. + + Preset servers + Серверы по умолчанию + No comment provided by engineer. + Preview Просмотр @@ -4971,6 +5453,11 @@ Error: %@ Конфиденциальность No comment provided by engineer. + + Privacy for your customers. + Конфиденциальность для ваших покупателей. + No comment provided by engineer. + Privacy redefined Более конфиденциальный @@ -4988,7 +5475,7 @@ Error: %@ Private message routing 🚀 - Конфиденциальная доставка сообщений 🚀 + Конфиденциальная доставка 🚀 No comment provided by engineer. @@ -5021,16 +5508,6 @@ Error: %@ Картинки профилей No comment provided by engineer. - - Profile name - Имя профиля - No comment provided by engineer. - - - Profile name: - Имя профиля: - No comment provided by engineer. - Profile password Пароль профиля @@ -5044,7 +5521,7 @@ Error: %@ Profile update will be sent to your contacts. Обновлённый профиль будет отправлен Вашим контактам. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5105,7 +5582,7 @@ Error: %@ Protect your IP address from the messaging relays chosen by your contacts. Enable in *Network & servers* settings. Защитите ваш IP адрес от серверов сообщений, выбранных Вашими контактами. -Включите в настройках *Сеть и серверы*. +Включите в настройках *Сети и серверов*. No comment provided by engineer. @@ -5133,6 +5610,11 @@ Enable in *Network & servers* settings. Проксированные серверы No comment provided by engineer. + + Proxy requires password + Прокси требует пароль + No comment provided by engineer. + Push notifications Доставка уведомлений @@ -5173,26 +5655,21 @@ Enable in *Network & servers* settings. Узнать больше 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Узнать больше в [Руководстве пользователя](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Узнайте больше из нашего GitHub репозитория. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Узнайте больше из нашего [GitHub репозитория](https://github.com/simplex-chat/simplex-chat#readme). @@ -5354,6 +5831,11 @@ Enable in *Network & servers* settings. Удалить No comment provided by engineer. + + Remove archive? + Удалить архив? + No comment provided by engineer. + Remove image Удалить изображение @@ -5504,6 +5986,16 @@ Enable in *Network & servers* settings. Показать chat item action + + Review conditions + Посмотреть условия + No comment provided by engineer. + + + Review later + Посмотреть позже + No comment provided by engineer. + Revoke Отозвать @@ -5534,6 +6026,11 @@ Enable in *Network & servers* settings. SMP сервер No comment provided by engineer. + + SOCKS proxy + SOCKS прокси + No comment provided by engineer. + Safely receive files Получайте файлы безопасно @@ -5547,17 +6044,18 @@ Enable in *Network & servers* settings. Save Сохранить - chat item action + alert button + chat item action Save (and notify contacts) Сохранить (и уведомить контакты) - No comment provided by engineer. + alert button Save and notify contact Сохранить и уведомить контакт - No comment provided by engineer. + alert button Save and notify group members @@ -5574,16 +6072,6 @@ Enable in *Network & servers* settings. Сохранить сообщение и обновить группу No comment provided by engineer. - - Save archive - Сохранить архив - No comment provided by engineer. - - - Save auto-accept settings - Сохранить настройки автоприема - No comment provided by engineer. - Save group profile Сохранить профиль группы @@ -5602,7 +6090,7 @@ Enable in *Network & servers* settings. Save preferences? Сохранить предпочтения? - No comment provided by engineer. + alert title Save profile password @@ -5617,18 +6105,18 @@ Enable in *Network & servers* settings. Save servers? Сохранить серверы? - No comment provided by engineer. - - - Save settings? - Сохранить настройки? - No comment provided by engineer. + alert title Save welcome message? Сохранить приветственное сообщение? No comment provided by engineer. + + Save your profile? + Сохранить ваш профиль? + alert title + Saved Сохранено @@ -5649,6 +6137,11 @@ Enable in *Network & servers* settings. Сохраненное сообщение message info title + + Saving %lld messages + Сохранение %lld сообщений + No comment provided by engineer. + Scale Масштаб @@ -5729,6 +6222,11 @@ Enable in *Network & servers* settings. Выбрать chat item action + + Select chat profile + Выберите профиль чата + No comment provided by engineer. + Selected %lld Выбрано %lld @@ -5819,11 +6317,6 @@ Enable in *Network & servers* settings. Отправлять уведомления No comment provided by engineer. - - Send notifications: - Отправлять уведомления: - No comment provided by engineer. - Send questions and ideas Отправьте вопросы и идеи @@ -5847,7 +6340,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Отправитель отменил передачу файла. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5944,6 +6437,16 @@ Enable in *Network & servers* settings. Отправлено через прокси No comment provided by engineer. + + Server + Сервер + No comment provided by engineer. + + + Server added to operator %@. + Сервер добавлен к оператору %@. + alert message + Server address Адрес сервера @@ -5959,6 +6462,21 @@ Enable in *Network & servers* settings. Адрес сервера несовместим с сетевыми настройками: %@. No comment provided by engineer. + + Server operator changed. + Оператор серверов изменен. + alert title + + + Server operators + Операторы серверов + No comment provided by engineer. + + + Server protocol changed. + Протокол сервера изменен. + alert title + Server requires authorization to create queues, check password Сервер требует авторизации для создания очередей, проверьте пароль @@ -6064,6 +6582,11 @@ Enable in *Network & servers* settings. Настройки No comment provided by engineer. + + Settings were changed. + Настройки были изменены. + alert message + Shape profile images Форма картинок профилей @@ -6072,22 +6595,38 @@ Enable in *Network & servers* settings. Share Поделиться - chat item action + alert action + chat item action Share 1-time link Поделиться одноразовой ссылкой No comment provided by engineer. + + Share 1-time link with a friend + Поделитесь одноразовой ссылкой с другом + No comment provided by engineer. + + + Share SimpleX address on social media. + Поделитесь SimpleX адресом в социальных сетях. + No comment provided by engineer. + Share address Поделиться адресом No comment provided by engineer. + + Share address publicly + Поделитесь адресом + No comment provided by engineer. + Share address with contacts? Поделиться адресом с контактами? - No comment provided by engineer. + alert title Share from other apps. @@ -6099,6 +6638,11 @@ Enable in *Network & servers* settings. Поделиться ссылкой No comment provided by engineer. + + Share profile + Поделиться профилем + No comment provided by engineer. + Share this 1-time invite link Поделиться одноразовой ссылкой-приглашением @@ -6169,6 +6713,11 @@ Enable in *Network & servers* settings. Адрес SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + SimpleX Chat и Flux заключили соглашение добавить серверы под управлением Flux в приложение. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Безопасность SimpleX Chat была проверена Trail of Bits. @@ -6199,6 +6748,16 @@ Enable in *Network & servers* settings. Адрес SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + Адрес SimpleX и одноразовые ссылки безопасно отправлять через любой мессенджер. + No comment provided by engineer. + + + SimpleX address or 1-time link? + Адрес SimpleX или одноразовая ссылка? + No comment provided by engineer. + SimpleX contact address SimpleX ссылка-контакт @@ -6219,8 +6778,8 @@ Enable in *Network & servers* settings. SimpleX ссылки chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. Ссылки SimpleX запрещены в этой группе. No comment provided by engineer. @@ -6234,6 +6793,11 @@ Enable in *Network & servers* settings. SimpleX одноразовая ссылка simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Аудит SimpleX протоколов от Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Упрощенный режим Инкогнито @@ -6264,6 +6828,11 @@ Enable in *Network & servers* settings. Слабое blur media + + Some app settings were not migrated. + Некоторые настройки приложения не были перенесены. + No comment provided by engineer. + Some file(s) were not exported: Некоторые файл(ы) не были экспортированы: @@ -6279,6 +6848,13 @@ Enable in *Network & servers* settings. Во время импорта произошли некоторые ошибки: No comment provided by engineer. + + Some servers failed the test: +%@ + Серверы не прошли тест: +%@ + alert message + Somebody Контакт @@ -6329,11 +6905,6 @@ Enable in *Network & servers* settings. Остановить чат No comment provided by engineer. - - Stop chat to enable database actions - Остановите чат, чтобы разблокировать операции с архивом чата - 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. Остановите чат, чтобы экспортировать или импортировать архив чата или удалить данные чата. Вы не сможете получать и отправлять сообщения, пока чат остановлен. @@ -6362,12 +6933,12 @@ Enable in *Network & servers* settings. Stop sharing Прекратить делиться - No comment provided by engineer. + alert action Stop sharing address? Прекратить делиться адресом? - No comment provided by engineer. + alert title Stopping chat @@ -6404,6 +6975,16 @@ Enable in *Network & servers* settings. Поддержать SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + Переключайте звук и видео во время звонка. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Переключайте профиль чата для одноразовых приглашений. + No comment provided by engineer. + System Системная @@ -6439,11 +7020,21 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Хвост + No comment provided by engineer. + Take picture Сделать фото No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + Нажмите Создать адрес SimpleX в меню, чтобы создать его позже. + No comment provided by engineer. + Tap button Нажмите кнопку @@ -6502,7 +7093,7 @@ Enable in *Network & servers* settings. Tests failed! Ошибка тестов! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6519,11 +7110,6 @@ Enable in *Network & servers* settings. Благодаря пользователям – добавьте переводы через Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Первая в мире платформа без идентификаторов пользователей. - No comment provided by engineer. - 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. @@ -6536,6 +7122,11 @@ It can happen because of some bug or when the connection is compromised.Приложение может посылать Вам уведомления о сообщениях и запросах на соединение - уведомления можно включить в Настройках. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + Приложение улучшает конфиденциальность используя разных операторов в каждом разговоре. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). Приложение будет запрашивать подтверждение загрузки с неизвестных серверов (за исключением .onion адресов). @@ -6551,6 +7142,11 @@ It can happen because of some bug or when the connection is compromised.Этот QR код не является SimpleX-ccылкой. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + Соединение достигло предела недоставленных сообщений. Возможно, Ваш контакт не в сети. + No comment provided by engineer. + The connection you accepted will be cancelled! Подтвержденное соединение будет отменено! @@ -6571,6 +7167,11 @@ It can happen because of some bug or when the connection is compromised.Шифрование работает, и новое соглашение не требуется. Это может привести к ошибкам соединения! No comment provided by engineer. + + The future of messaging + Будущее коммуникаций + No comment provided by engineer. + The hash of the previous message is different. Хэш предыдущего сообщения отличается. @@ -6596,11 +7197,6 @@ It can happen because of some bug or when the connection is compromised.Сообщения будут помечены как удаленные для всех членов группы. No comment provided by engineer. - - The next generation of private messaging - Новое поколение приватных сообщений - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. Предыдущая версия данных чата не удалена при перемещении, её можно удалить. @@ -6611,6 +7207,21 @@ It can happen because of some bug or when the connection is compromised.Профиль отправляется только Вашим контактам. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Те же самые условия будут приняты для оператора **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Те же самые условия будут приняты для оператора(ов): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + Второй оператор серверов в приложении! + No comment provided by engineer. + The second tick we missed! ✅ Вторая галочка - знать, что доставлено! ✅ @@ -6626,16 +7237,31 @@ It can happen because of some bug or when the connection is compromised.Серверы для новых соединений Вашего текущего профиля чата **%@**. No comment provided by engineer. + + The servers for new files 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. + + The uploaded database archive will be permanently removed from the servers. + Загруженный архив базы данных будет навсегда удален с серверов. + No comment provided by engineer. + Themes Темы No comment provided by engineer. + + These conditions will also apply for: **%@**. + Эти условия также будут применены к: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. Установки для Вашего активного профиля **%@**. @@ -6736,9 +7362,9 @@ It can happen because of some bug or when the connection is compromised.Чтобы соединиться 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. - Чтобы защитить Вашу конфиденциальность, вместо ID пользователей, которые есть в других платформах, SimpleX использует ID для очередей сообщений, разные для каждого контакта. + + To protect against your link being replaced, you can compare contact security codes. + Чтобы защитить Вашу ссылку от замены, Вы можете сравнить код безопасности. No comment provided by engineer. @@ -6758,6 +7384,26 @@ You will be prompted to complete authentication before this feature is enabled.< Вам будет нужно пройти аутентификацию для включения блокировки. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Чтобы защитить Вашу конфиденциальность, SimpleX использует разные идентификаторы для каждого Вашeго контакта. + No comment provided by engineer. + + + To receive + Для получения + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Для записи речи, пожалуйста, дайте разрешение на использование микрофона. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Для записи видео, пожалуйста, дайте разрешение на использование камеры. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Для записи голосового сообщения, пожалуйста разрешите доступ к микрофону. @@ -6768,11 +7414,21 @@ You will be prompted to complete authentication before this feature is enabled.< Чтобы показать Ваш скрытый профиль, введите его пароль в поле поиска на странице **Ваши профили чата**. No comment provided by engineer. + + To send + Для оправки + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Для поддержки мгновенный доставки уведомлений данные чата должны быть перемещены. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + Чтобы использовать серверы оператора **%@**, примите условия использования. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Чтобы подтвердить end-to-end шифрование с Вашим контактом сравните (или сканируйте) код безопасности на Ваших устройствах. @@ -6863,6 +7519,11 @@ You will be prompted to complete authentication before this feature is enabled.< Разблокировать члена группы? No comment provided by engineer. + + Undelivered messages + Недоставленные сообщения + No comment provided by engineer. + Unexpected migration state Неожиданная ошибка при перемещении данных чата @@ -6911,7 +7572,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! Неизвестные серверы! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -7020,11 +7681,21 @@ To connect, please ask your contact to create another connection link and check Загрузка архива No comment provided by engineer. + + Use %@ + Использовать %@ + No comment provided by engineer. + Use .onion hosts Использовать .onion хосты No comment provided by engineer. + + Use SOCKS proxy + Использовать SOCKS прокси + No comment provided by engineer. + Use SimpleX Chat servers? Использовать серверы предосталенные SimpleX Chat? @@ -7040,6 +7711,16 @@ To connect, please ask your contact to create another connection link and check Использовать активный профиль No comment provided by engineer. + + Use for files + Использовать для файлов + No comment provided by engineer. + + + Use for messages + Использовать для сообщений + No comment provided by engineer. + Use for new connections Использовать для новых соединений @@ -7080,6 +7761,11 @@ To connect, please ask your contact to create another connection link and check Использовать сервер No comment provided by engineer. + + Use servers + Использовать серверы + No comment provided by engineer. + Use the app while in the call. Используйте приложение во время звонка. @@ -7090,16 +7776,16 @@ To connect, please ask your contact to create another connection link and check Используйте приложение одной рукой. No comment provided by engineer. - - User profile - Профиль чата - No comment provided by engineer. - User selection Выбор пользователя No comment provided by engineer. + + Username + Имя пользователя + No comment provided by engineer. + Using SimpleX Chat servers. Используются серверы, предоставленные SimpleX Chat. @@ -7170,11 +7856,21 @@ To connect, please ask your contact to create another connection link and check Видео и файлы до 1гб No comment provided by engineer. + + View conditions + Посмотреть условия + No comment provided by engineer. + View security code Показать код безопасности No comment provided by engineer. + + View updated conditions + Посмотреть измененные условия + No comment provided by engineer. + Visible history Доступ к истории @@ -7190,8 +7886,8 @@ To connect, please ask your contact to create another connection link and check Голосовые сообщения запрещены в этом чате. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Голосовые сообщения запрещены в этой группе. No comment provided by engineer. @@ -7285,9 +7981,9 @@ To connect, please ask your contact to create another connection link and check Во время соединения аудио и видео звонков. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Когда Вы получите запрос на соединение, Вы можете принять или отклонить его. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Когда больше чем один оператор включен, ни один из них не видит метаданные, чтобы определить, кто соединен с кем. No comment provided by engineer. @@ -7333,7 +8029,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Без Тора или ВПН, Ваш IP адрес будет доступен этим серверам файлов: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7360,11 +8056,6 @@ To connect, please ask your contact to create another connection link and check XFTP сервер No comment provided by engineer. - - You - Вы - No comment provided by engineer. - You **must not** use the same database on two devices. Вы **не должны** использовать одну и ту же базу данных на двух устройствах. @@ -7390,6 +8081,11 @@ To connect, please ask your contact to create another connection link and check Вы уже соединены с контактом %@. No comment provided by engineer. + + You are already connected with %@. + Вы уже соединены с %@. + No comment provided by engineer. + You are already connecting to %@. Вы уже соединяетесь с %@. @@ -7452,6 +8148,16 @@ Repeat join request? Вы можете изменить это в настройках Интерфейса. No comment provided by engineer. + + You can configure operators in Network & servers settings. + Вы можете настроить операторов в настройках Сети и серверов. + No comment provided by engineer. + + + You can configure servers via settings. + Вы можете настроить серверы позже. + No comment provided by engineer. + You can create it later Вы можете создать его позже @@ -7492,6 +8198,11 @@ Repeat join request? Вы можете отправлять сообщения %@ из Архивированных контактов. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + Вы можете установить имя соединения, чтобы запомнить кому Вы отправили ссылку. + No comment provided by engineer. + You can set lock screen notification preview via settings. Вы можете установить просмотр уведомлений на экране блокировки в настройках. @@ -7507,11 +8218,6 @@ Repeat join request? Вы можете поделиться этим адресом с Вашими контактами, чтобы они могли соединиться с **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Вы можете использовать Ваш адрес как ссылку или как QR код - кто угодно сможет соединиться с Вами. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Вы можете запустить чат через Настройки приложения или перезапустив приложение. @@ -7535,23 +8241,23 @@ Repeat join request? You can view invitation link again in connection details. Вы можете увидеть ссылку-приглашение снова открыв соединение. - No comment provided by engineer. + alert message You can't send messages! Вы не можете отправлять сообщения! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Вы определяете через какие серверы Вы **получаете сообщения**, Ваши контакты - серверы, которые Вы используете для отправки. - No comment provided by engineer. - You could not be verified; please try again. Верификация не удалась; пожалуйста, попробуйте ещё раз. No comment provided by engineer. + + You decide who can connect. + Вы определяете, кто может соединиться. + No comment provided by engineer. + You have already requested connection via this address! Вы уже запросили соединение через этот адрес! @@ -7654,6 +8360,11 @@ Repeat connection request? Вы все равно получите звонки и уведомления в профилях без звука, когда они активные. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + Вы прекратите получать сообщения в этом разговоре. История будет сохранена. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Вы перестанете получать сообщения от этой группы. История чата будет сохранена. @@ -7674,11 +8385,6 @@ Repeat connection request? Вы используете инкогнито профиль для этой группы - чтобы предотвратить раскрытие Вашего основного профиля, приглашать контакты не разрешено No comment provided by engineer. - - Your %@ servers - Ваши %@ серверы - No comment provided by engineer. - Your ICE servers Ваши ICE серверы @@ -7694,11 +8400,6 @@ Repeat connection request? Ваш адрес SimpleX No comment provided by engineer. - - Your XFTP servers - Ваши XFTP серверы - No comment provided by engineer. - Your calls Ваши звонки @@ -7714,11 +8415,21 @@ Repeat connection request? База данных НЕ зашифрована. Установите пароль, чтобы защитить Ваши данные. No comment provided by engineer. + + Your chat preferences + Ваши настройки чата + alert title + Your chat profiles Ваши профили чата No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Соединение было перемещено на %@, но при смене профиля произошла неожиданная ошибка. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Ваш контакт отправил файл, размер которого превышает максимальный размер (%@). @@ -7734,6 +8445,11 @@ Repeat connection request? Ваши контакты сохранятся. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Ваши учетные данные могут быть отправлены в незашифрованном виде. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Текущие данные Вашего чата будет УДАЛЕНЫ и ЗАМЕНЕНЫ импортированными. @@ -7764,13 +8480,16 @@ Repeat connection request? Будет отправлен Ваш профиль **%@**. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. -SimpleX серверы не могут получить доступ к Вашему профилю. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам. SimpleX серверы не могут получить доступ к Вашему профилю. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Ваш профиль был изменен. Если вы сохраните его, обновленный профиль будет отправлен всем вашим контактам. + alert message + Your profile, contacts and delivered messages are stored on your device. Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве. @@ -7781,16 +8500,16 @@ SimpleX серверы не могут получить доступ к Ваше Случайный профиль No comment provided by engineer. - - Your server - Ваш сервер - No comment provided by engineer. - Your server address Адрес Вашего сервера No comment provided by engineer. + + Your servers + Ваши серверы + No comment provided by engineer. + Your settings Настройки @@ -7831,6 +8550,11 @@ SimpleX серверы не могут получить доступ к Ваше принятый звонок call status + + accepted invitation + принятое приглашение + chat list item title + admin админ @@ -8019,7 +8743,7 @@ SimpleX серверы не могут получить доступ к Ваше connecting… соединяется… - chat list item title + No comment provided by engineer. connection established @@ -8211,6 +8935,11 @@ SimpleX серверы не могут получить доступ к Ваше истекло No comment provided by engineer. + + for better metadata privacy. + для лучшей конфиденциальности метаданных. + No comment provided by engineer. + forwarded переслано @@ -8508,6 +9237,11 @@ SimpleX серверы не могут получить доступ к Ваше удалил(а) Вас из группы rcv group event chat item + + requested to connect + запрошено соединение + chat list item title + saved сохранено @@ -8833,6 +9567,38 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + %d новых сообщений + notification body + + + From: %@ + От: %@ + notification body + + + New events + Новые события + notification + + + New messages + Новые сообщения + notification + + + New messages in %d chats + Новые сообщения в %d разговоре(ах) + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/ru.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 646a94a337..4317787f67 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff +++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -120,6 +105,14 @@ %@ ได้รับการตรวจสอบแล้ว No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded No comment provided by engineer. @@ -129,6 +122,10 @@ %@ อยากเชื่อมต่อ! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members No comment provided by engineer. @@ -147,11 +144,31 @@ %d วัน time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d ชั่วโมง time interval + + %d messages not forwarded + alert title + %d min %d นาที @@ -304,26 +321,21 @@ ) 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 or link for your contact. - **เพิ่มผู้ติดต่อใหม่**: เพื่อสร้างคิวอาร์โค้ดแบบใช้ครั้งเดียวหรือลิงก์สำหรับผู้ติดต่อของคุณ + + **Create 1-time link**: to create and share a new invitation link. No comment provided by engineer. **Create group**: to create a new group. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **เป็นส่วนตัวมากขึ้น**: ตรวจสอบข้อความใหม่ทุกๆ 20 นาที โทเค็นอุปกรณ์แชร์กับเซิร์ฟเวอร์ SimpleX Chat แต่ไม่ระบุจำนวนผู้ติดต่อหรือข้อความที่คุณมี 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **ส่วนตัวที่สุด**: ไม่ใช้เซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat ตรวจสอบข้อความเป็นระยะในพื้นหลัง (ขึ้นอยู่กับความถี่ที่คุณใช้แอป) No comment provided by engineer. @@ -336,11 +348,15 @@ **โปรดทราบ**: คุณจะไม่สามารถกู้คืนหรือเปลี่ยนรหัสผ่านได้หากคุณทำรหัสผ่านหาย 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **แนะนำ**: โทเค็นอุปกรณ์และการแจ้งเตือนจะถูกส่งไปยังเซิร์ฟเวอร์การแจ้งเตือนของ SimpleX Chat แต่ไม่ใช่เนื้อหาข้อความ ขนาด หรือผู้ที่ส่ง No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **คำเตือน**: การแจ้งเตือนแบบพุชทันทีจำเป็นต้องบันทึกรหัสผ่านไว้ใน Keychain @@ -439,6 +455,14 @@ 1 สัปดาห์ time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 นาที @@ -507,19 +531,13 @@ ยกเลิกการเปลี่ยนที่อยู่? No comment provided by engineer. - - About SimpleX - เกี่ยวกับ SimpleX - No comment provided by engineer. - About SimpleX Chat เกี่ยวกับ SimpleX Chat No comment provided by engineer. - - About SimpleX address - เกี่ยวกับที่อยู่ SimpleX + + About operators No comment provided by engineer. @@ -533,6 +551,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? No comment provided by engineer. @@ -548,6 +570,10 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged No comment provided by engineer. @@ -565,13 +591,8 @@ เพิ่มที่อยู่ลงในโปรไฟล์ของคุณ เพื่อให้ผู้ติดต่อของคุณสามารถแชร์กับผู้อื่นได้ การอัปเดตโปรไฟล์จะถูกส่งไปยังผู้ติดต่อของคุณ No comment provided by engineer. - - Add contact - No comment provided by engineer. - - - Add preset servers - เพิ่มเซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า + + Add friends No comment provided by engineer. @@ -589,6 +610,10 @@ เพิ่มเซิร์ฟเวอร์โดยการสแกนรหัสคิวอาร์โค้ด No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device เพิ่มเข้าไปในอุปกรณ์อื่น @@ -599,6 +624,18 @@ เพิ่มข้อความต้อนรับ No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent No comment provided by engineer. @@ -621,6 +658,14 @@ การเปลี่ยนแปลงที่อยู่จะถูกยกเลิก จะใช้ที่อยู่เก่าของผู้รับ No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. No comment provided by engineer. @@ -654,8 +699,8 @@ ข้อมูลทั้งหมดจะถูกลบเมื่อถูกป้อน No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. No comment provided by engineer. @@ -663,6 +708,10 @@ สมาชิกในกลุ่มทุกคนจะยังคงเชื่อมต่ออยู่. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! No comment provided by engineer. @@ -678,7 +727,7 @@ All profiles - No comment provided by engineer. + profile dropdown All your contacts will remain connected. @@ -832,6 +881,11 @@ รับสาย No comment provided by engineer. + + Anybody can host servers. + โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้ + No comment provided by engineer. + App build: %@ รุ่นแอป: %@ @@ -860,6 +914,10 @@ รหัสผ่านแอปจะถูกแทนที่ด้วยรหัสผ่านที่ทำลายตัวเอง No comment provided by engineer. + + App session + No comment provided by engineer. + App version เวอร์ชันแอป @@ -959,6 +1017,10 @@ ยอมรับภาพอัตโนมัติ No comment provided by engineer. + + Auto-accept settings + alert title + Back กลับ @@ -982,10 +1044,18 @@ แฮชข้อความไม่ดี No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages ข้อความที่ดีขึ้น @@ -995,6 +1065,18 @@ Better networking No comment provided by engineer. + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience + No comment provided by engineer. + Black No comment provided by engineer. @@ -1064,6 +1146,14 @@ Bulgarian, Finnish, Thai and Ukrainian - thanks to the users and [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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) (เบต้า) @@ -1112,7 +1202,8 @@ Cancel ยกเลิก - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1130,7 +1221,7 @@ Cannot receive file ไม่สามารถรับไฟล์ได้ - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1145,6 +1236,10 @@ เปลี่ยน No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? เปลี่ยนรหัสผ่านฐานข้อมูล? @@ -1191,9 +1286,16 @@ authentication reason set passcode view - - Chat archive - ที่เก็บแชทถาวร + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. @@ -1251,19 +1353,44 @@ ค่ากําหนดในการแชท No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + โปรไฟล์ผู้ใช้ + No comment provided by engineer. + Chat theme No comment provided by engineer. + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! + No comment provided by engineer. + Chats แชท No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. ตรวจสอบที่อยู่เซิร์ฟเวอร์แล้วลองอีกครั้ง - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1342,15 +1469,47 @@ Completed No comment provided by engineer. + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + No comment provided by engineer. + Configure ICE servers กำหนดค่าเซิร์ฟเวอร์ ICE No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm ยืนยัน @@ -1514,6 +1673,10 @@ This is your own one-time link! ส่งคําขอเชื่อมต่อแล้ว! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated No comment provided by engineer. @@ -1606,6 +1769,10 @@ This is your own one-time link! รุ่นหลัก: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? No comment provided by engineer. @@ -1615,6 +1782,10 @@ This is your own one-time link! สร้าง No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address สร้างที่อยู่ SimpleX @@ -1624,11 +1795,6 @@ This is your own one-time link! Create a group using a random profile. No comment provided by engineer. - - Create an address to let people connect with you. - สร้างที่อยู่เพื่อให้ผู้อื่นเชื่อมต่อกับคุณ - No comment provided by engineer. - Create file สร้างไฟล์ @@ -1683,11 +1849,6 @@ This is your own one-time link! Created at: %@ copied message info - - Created on %@ - สร้างเมื่อ %@ - No comment provided by engineer. - Creating archive link No comment provided by engineer. @@ -1701,6 +1862,10 @@ This is your own one-time link! รหัสผ่านปัจจุบัน No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… รหัสผ่านปัจจุบัน… @@ -1720,6 +1885,10 @@ This is your own one-time link! เวลาที่กําหนดเอง No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme No comment provided by engineer. @@ -1848,7 +2017,8 @@ This is your own one-time link! Delete ลบ - chat item action + alert action + chat item action swipe action @@ -1883,14 +2053,8 @@ This is your own one-time link! Delete and notify contact No comment provided by engineer. - - Delete archive - ลบที่เก็บถาวร - No comment provided by engineer. - - - Delete chat archive? - ลบที่เก็บแชทถาวร? + + Delete chat No comment provided by engineer. @@ -1903,6 +2067,10 @@ This is your own one-time link! ลบโปรไฟล์แชทไหม? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection ลบการเชื่อมต่อ @@ -2006,6 +2174,10 @@ This is your own one-time link! ลบฐานข้อมูลเก่า? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? ลบการเชื่อมต่อที่รอดำเนินการหรือไม่? @@ -2052,6 +2224,10 @@ This is your own one-time link! Deletion errors No comment provided by engineer. + + Delivered even when Apple drops them. + No comment provided by engineer. + Delivery No comment provided by engineer. @@ -2142,8 +2318,12 @@ This is your own one-time link! ข้อความโดยตรง chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. ข้อความโดยตรงระหว่างสมาชิกเป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. @@ -2181,8 +2361,8 @@ This is your own one-time link! ข้อความที่จะหายไปหลังเวลาที่กําหนด (disappearing message) เป็นสิ่งต้องห้ามในแชทนี้ No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. ข้อความที่จะหายไปหลังเวลาที่กําหนด (disappearing message) เป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. @@ -2235,6 +2415,10 @@ This is your own one-time link! Do not send history to new members. No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address อย่าสร้างที่อยู่ @@ -2257,7 +2441,8 @@ This is your own one-time link! Download - chat item action + alert button + chat item action Download errors @@ -2272,6 +2457,10 @@ This is your own one-time link! ดาวน์โหลดไฟล์ server test step + + Download files + alert action + Downloaded No comment provided by engineer. @@ -2298,6 +2487,10 @@ This is your own one-time link! ระยะเวลา No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit แก้ไข @@ -2318,6 +2511,10 @@ This is your own one-time link! เปิดใช้งาน (เก็บการแทนที่) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock เปิดใช้งาน SimpleX Lock @@ -2510,26 +2707,33 @@ This is your own one-time link! เกิดข้อผิดพลาดในการยกเลิกการเปลี่ยนที่อยู่ No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request เกิดข้อผิดพลาดในการรับคำขอติดต่อ No comment provided by engineer. - - Error accessing database file - เกิดข้อผิดพลาดในการเข้าถึงไฟล์ฐานข้อมูล - No comment provided by engineer. - Error adding member(s) เกิดข้อผิดพลาดในการเพิ่มสมาชิก No comment provided by engineer. + + Error adding server + alert title + Error changing address เกิดข้อผิดพลาดในการเปลี่ยนที่อยู่ No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role เกิดข้อผิดพลาดในการเปลี่ยนบทบาท @@ -2540,6 +2744,10 @@ This is your own one-time link! เกิดข้อผิดพลาดในการเปลี่ยนการตั้งค่า No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. No comment provided by engineer. @@ -2649,9 +2857,12 @@ This is your own one-time link! เกิดข้อผิดพลาดในการเข้าร่วมกลุ่ม No comment provided by engineer. - - Error loading %@ servers - โหลดเซิร์ฟเวอร์ %@ ผิดพลาด + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. @@ -2661,7 +2872,7 @@ This is your own one-time link! Error receiving file เกิดข้อผิดพลาดในการรับไฟล์ - No comment provided by engineer. + alert title Error reconnecting server @@ -2680,11 +2891,6 @@ This is your own one-time link! Error resetting statistics No comment provided by engineer. - - Error saving %@ servers - เกิดข้อผิดพลาดในการบันทึกเซิร์ฟเวอร์ %@ - No comment provided by engineer. - Error saving ICE servers เกิดข้อผิดพลาดในการบันทึกเซิร์ฟเวอร์ ICE @@ -2705,6 +2911,10 @@ This is your own one-time link! เกิดข้อผิดพลาดในการบันทึกรหัสผ่านไปยัง keychain No comment provided by engineer. + + Error saving servers + alert title + Error saving settings when migrating @@ -2747,10 +2957,14 @@ This is your own one-time link! เกิดข้อผิดพลาดในการหยุดแชท No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! เกิดข้อผิดพลาดในการเปลี่ยนโปรไฟล์! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2767,6 +2981,10 @@ This is your own one-time link! เกิดข้อผิดพลาดในการอัปเดตข้อความ No comment provided by engineer. + + Error updating server + alert title + Error updating settings เกิดข้อผิดพลาดในการอัปเดตการตั้งค่า @@ -2793,8 +3011,7 @@ This is your own one-time link! Error: %@ ข้อผิดพลาด: % @ - file error text - snd error text + alert message Error: URL is invalid @@ -2810,6 +3027,10 @@ This is your own one-time link! Errors No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. แม้ในขณะที่ปิดใช้งานในการสนทนา @@ -2875,6 +3096,11 @@ This is your own one-time link! File error No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. file error text @@ -2925,8 +3151,8 @@ This is your own one-time link! ไฟล์และสื่อ chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. ไฟล์และสื่อเป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. @@ -2992,19 +3218,51 @@ This is your own one-time link! การแก้ไขไม่สนับสนุนโดยสมาชิกกลุ่ม No comment provided by engineer. + + For chat profile %@: + servers error + For console สำหรับคอนโซล No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward chat item action + + Forward %d message(s)? + alert title + Forward and save messages No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded No comment provided by engineer. @@ -3013,6 +3271,10 @@ This is your own one-time link! Forwarded from No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. No comment provided by engineer. @@ -3054,11 +3316,6 @@ Error: %2$@ ชื่อเต็ม (ไม่บังคับ) No comment provided by engineer. - - Full name: - ชื่อเต็ม: - No comment provided by engineer. - Fully decentralized – visible only to members. No comment provided by engineer. @@ -3139,40 +3396,6 @@ Error: %2$@ ลิงค์กลุ่ม No comment provided by engineer. - - Group members can add message reactions. - สมาชิกกลุ่มสามารถเพิ่มการแสดงปฏิกิริยาต่อข้อความได้ - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร - No comment provided by engineer. - - - Group members can send SimpleX links. - No comment provided by engineer. - - - Group members can send direct messages. - สมาชิกกลุ่มสามารถส่งข้อความโดยตรงได้ - No comment provided by engineer. - - - Group members can send disappearing messages. - สมาชิกกลุ่มสามารถส่งข้อความที่จะหายไปหลังจากเวลาที่กำหนดหลังการอ่าน (disappearing messages) ได้ - No comment provided by engineer. - - - Group members can send files and media. - สมาชิกกลุ่มสามารถส่งไฟล์และสื่อ - No comment provided by engineer. - - - Group members can send voice messages. - สมาชิกกลุ่มสามารถส่งข้อความเสียง - No comment provided by engineer. - Group message: ข้อความกลุ่ม: @@ -3267,9 +3490,12 @@ Error: %2$@ วิธีการ SimpleX ทํางานอย่างไร No comment provided by engineer. - - How it works - มันทำงานอย่างไร + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3296,6 +3522,10 @@ Error: %2$@ เซิร์ฟเวอร์ ICE (หนึ่งเครื่องต่อสาย) No comment provided by engineer. + + IP address + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. หากคุณไม่สามารถพบกันในชีวิตจริงได้ ให้แสดงคิวอาร์โค้ดในวิดีโอคอล หรือแชร์ลิงก์ @@ -3336,8 +3566,8 @@ Error: %2$@ โดยทันที No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam มีภูมิคุ้มกันต่อสแปมและการละเมิด No comment provided by engineer. @@ -3368,6 +3598,11 @@ Error: %2$@ Importing archive No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery No comment provided by engineer. @@ -3462,6 +3697,11 @@ Error: %2$@ ติดตั้ง [SimpleX Chat สำหรับเทอร์มินัล](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + ทันที + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3469,11 +3709,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - ทันที - No comment provided by engineer. - Interface อินเตอร์เฟซ @@ -3515,7 +3750,7 @@ Error: %2$@ Invalid server address! ที่อยู่เซิร์ฟเวอร์ไม่ถูกต้อง! - No comment provided by engineer. + alert title Invalid status @@ -3536,6 +3771,10 @@ Error: %2$@ เชิญสมาชิก No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group เชิญเข้าร่วมกลุ่ม @@ -3551,8 +3790,8 @@ Error: %2$@ ไม่สามารถลบข้อความแบบแก้ไขไม่ได้ในแชทนี้ No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. การลบข้อความแบบแก้ไขไม่ได้เป็นสิ่งที่ห้ามในกลุ่มนี้ No comment provided by engineer. @@ -3635,7 +3874,7 @@ This is your link for group %@! Keep - No comment provided by engineer. + alert action Keep conversation @@ -3647,7 +3886,7 @@ This is your link for group %@! Keep unused invitation? - No comment provided by engineer. + alert title Keep your connections @@ -3684,6 +3923,14 @@ This is your link for group %@! ออกจาก swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group ออกจากกลุ่ม @@ -3731,11 +3978,6 @@ This is your link for group %@! ข้อความสด No comment provided by engineer. - - Local - ในเครื่อง - No comment provided by engineer. - Local name ชื่อภายในเครื่องเท่านั้น @@ -3756,11 +3998,6 @@ This is your link for group %@! โหมดล็อค No comment provided by engineer. - - Make a private connection - สร้างการเชื่อมต่อแบบส่วนตัว - No comment provided by engineer. - Make one message disappear ทำให้ข้อความหายไปหนึ่งข้อความ @@ -3771,21 +4008,11 @@ This is your link for group %@! ทำให้โปรไฟล์เป็นส่วนตัว! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - ตรวจสอบให้แน่ใจว่าที่อยู่เซิร์ฟเวอร์ %@ อยู่ในรูปแบบที่ถูกต้อง แยกบรรทัดและไม่ซ้ำกัน (%@) - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. ตรวจสอบให้แน่ใจว่าที่อยู่เซิร์ฟเวอร์ WebRTC ICE อยู่ในรูปแบบที่ถูกต้อง แยกบรรทัดและไม่ซ้ำกัน No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - หลายคนถามว่า: *หาก SimpleX ไม่มีตัวระบุผู้ใช้ จะส่งข้อความได้อย่างไร?* - No comment provided by engineer. - Mark deleted for everyone ทำเครื่องหมายว่าลบแล้วสำหรับทุกคน @@ -3828,6 +4055,10 @@ This is your link for group %@! Member inactive item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. บทบาทของสมาชิกจะถูกเปลี่ยนเป็น "%@" สมาชิกกลุ่มทั้งหมดจะได้รับแจ้ง @@ -3838,11 +4069,49 @@ This is your link for group %@! บทบาทของสมาชิกจะถูกเปลี่ยนเป็น "%@" สมาชิกจะได้รับคำเชิญใหม่ No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! สมาชิกจะถูกลบออกจากกลุ่ม - ไม่สามารถยกเลิกได้! No comment provided by engineer. + + Members can add message reactions. + สมาชิกกลุ่มสามารถเพิ่มการแสดงปฏิกิริยาต่อข้อความได้ + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + สมาชิกกลุ่มสามารถลบข้อความที่ส่งแล้วอย่างถาวร + No comment provided by engineer. + + + Members can send SimpleX links. + No comment provided by engineer. + + + Members can send direct messages. + สมาชิกกลุ่มสามารถส่งข้อความโดยตรงได้ + No comment provided by engineer. + + + Members can send disappearing messages. + สมาชิกกลุ่มสามารถส่งข้อความที่จะหายไปหลังจากเวลาที่กำหนดหลังการอ่าน (disappearing messages) ได้ + No comment provided by engineer. + + + Members can send files and media. + สมาชิกกลุ่มสามารถส่งไฟล์และสื่อ + No comment provided by engineer. + + + Members can send voice messages. + สมาชิกกลุ่มสามารถส่งข้อความเสียง + No comment provided by engineer. + Menus No comment provided by engineer. @@ -3888,8 +4157,8 @@ This is your link for group %@! ห้ามแสดงปฏิกิริยาบนข้อความในแชทนี้ No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. ปฏิกิริยาบนข้อความเป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. @@ -3901,6 +4170,10 @@ This is your link for group %@! Message servers No comment provided by engineer. + + Message shape + No comment provided by engineer. + Message source remains private. No comment provided by engineer. @@ -3944,6 +4217,10 @@ This is your link for group %@! Messages sent No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. No comment provided by engineer. @@ -4000,9 +4277,9 @@ This is your link for group %@! การโยกย้ายเสร็จสมบูรณ์ No comment provided by engineer. - - Migrations: %@ - การย้ายข้อมูล: %@ + + Migrations: + การย้ายข้อมูล No comment provided by engineer. @@ -4029,6 +4306,10 @@ This is your link for group %@! More reliable network connection. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. item status description @@ -4062,6 +4343,10 @@ This is your link for group %@! Network connection No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. snd error text @@ -4070,6 +4355,10 @@ This is your link for group %@! Network management No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings การตั้งค่าเครือข่าย @@ -4085,6 +4374,14 @@ This is your link for group %@! รหัสผ่านใหม่ No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat No comment provided by engineer. @@ -4103,11 +4400,6 @@ This is your link for group %@! คำขอติดต่อใหม่: notification - - New database archive - ฐานข้อมูลใหม่สำหรับการเก็บถาวร - No comment provided by engineer. - New desktop app! No comment provided by engineer. @@ -4117,6 +4409,10 @@ This is your link for group %@! ชื่อที่แสดงใหม่ No comment provided by engineer. + + New events + notification + New in %@ ใหม่ใน %@ @@ -4141,6 +4437,10 @@ This is your link for group %@! รหัสผ่านใหม่… No comment provided by engineer. + + New server + No comment provided by engineer. + No เลขที่ @@ -4193,20 +4493,62 @@ This is your link for group %@! No info, try to reload No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message ไม่อนุญาตให้บันทึกข้อความเสียง No comment provided by engineer. + + No push server + ในเครื่อง + No comment provided by engineer. + No received or sent files ไม่มีไฟล์ที่ได้รับหรือส่ง No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + แพลตฟอร์มแรกที่ไม่มีตัวระบุผู้ใช้ - ถูกออกแบบให้เป็นส่วนตัว + No comment provided by engineer. + Not compatible! No comment provided by engineer. @@ -4215,6 +4557,10 @@ This is your link for group %@! Nothing selected No comment provided by engineer. + + Nothing to forward! + alert title + Notifications การแจ้งเตือน @@ -4225,6 +4571,10 @@ This is your link for group %@! ปิดการแจ้งเตือน! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4246,18 +4596,13 @@ This is your link for group %@! Ok ตกลง - No comment provided by engineer. + alert button Old database ฐานข้อมูลเก่า No comment provided by engineer. - - Old database archive - คลังฐานข้อมูลเก่า - No comment provided by engineer. - One-time invitation link ลิงก์คำเชิญแบบใช้ครั้งเดียว @@ -4280,8 +4625,12 @@ Requires compatible VPN. โฮสต์หัวหอมจะไม่ถูกใช้ No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. เฉพาะอุปกรณ์ไคลเอนต์เท่านั้นที่จัดเก็บโปรไฟล์ผู้ใช้ ผู้ติดต่อ กลุ่ม และข้อความที่ส่งด้วย **การเข้ารหัส encrypt แบบ 2 ชั้น** No comment provided by engineer. @@ -4363,6 +4712,10 @@ Requires compatible VPN. เปิดการตั้งค่า No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat เปิดแชท @@ -4373,6 +4726,10 @@ Requires compatible VPN. เปิดคอนโซลการแชท authentication reason + + Open conditions + No comment provided by engineer. + Open group No comment provided by engineer. @@ -4381,24 +4738,22 @@ Requires compatible VPN. Open migration to another device authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - เปิดโปรไฟล์ผู้ใช้ - authentication reason - - - Open-source protocol and code – anybody can run the servers. - โปรโตคอลและโค้ดโอเพ่นซอร์ส – ใคร ๆ ก็สามารถเปิดใช้เซิร์ฟเวอร์ได้ - No comment provided by engineer. - Opening app… No comment provided by engineer. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link No comment provided by engineer. @@ -4415,13 +4770,18 @@ Requires compatible VPN. Or show this code No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4458,6 +4818,10 @@ Requires compatible VPN. ตั้งรหัสผ่านเรียบร้อยแล้ว! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show รหัสผ่านที่จะแสดง @@ -4488,13 +4852,8 @@ Requires compatible VPN. Pending No comment provided by engineer. - - People can connect to you only via the links you share. - ผู้คนสามารถเชื่อมต่อกับคุณผ่านลิงก์ที่คุณแบ่งปันเท่านั้น - No comment provided by engineer. - - - Periodically + + Periodic เป็นระยะๆ No comment provided by engineer. @@ -4594,6 +4953,10 @@ Error: %@ อินเตอร์เฟซภาษาโปแลนด์ No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect อาจเป็นไปได้ว่าลายนิ้วมือของ certificate ในที่อยู่เซิร์ฟเวอร์ไม่ถูกต้อง @@ -4604,16 +4967,15 @@ Error: %@ เก็บข้อความที่ร่างไว้ล่าสุดพร้อมไฟล์แนบ No comment provided by engineer. - - Preset server - เซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า - No comment provided by engineer. - Preset server address ที่อยู่เซิร์ฟเวอร์ที่ตั้งไว้ล่วงหน้า No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview ดูตัวอย่าง @@ -4628,6 +4990,10 @@ Error: %@ ความเป็นส่วนตัวและความปลอดภัย No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined นิยามความเป็นส่วนตัวใหม่ @@ -4672,14 +5038,6 @@ Error: %@ Profile images No comment provided by engineer. - - Profile name - No comment provided by engineer. - - - Profile name: - No comment provided by engineer. - Profile password รหัสผ่านโปรไฟล์ @@ -4692,7 +5050,7 @@ Error: %@ Profile update will be sent to your contacts. การอัปเดตโปรไฟล์จะถูกส่งไปยังผู้ติดต่อของคุณ - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4775,6 +5133,10 @@ Enable in *Network & servers* settings. Proxied servers No comment provided by engineer. + + Proxy requires password + No comment provided by engineer. + Push notifications การแจ้งเตือนแบบทันที @@ -4812,25 +5174,20 @@ Enable in *Network & servers* settings. อ่านเพิ่มเติม 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). No comment provided by engineer. + + Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + อ่านเพิ่มเติมใน[คู่มือผู้ใช้](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses) + 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) No comment provided by engineer. - - Read more in our GitHub repository. - อ่านเพิ่มเติมในที่เก็บ GitHub ของเรา - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). อ่านเพิ่มเติมใน[พื้นที่เก็บข้อมูล GitHub](https://github.com/simplex-chat/simplex-chat#readme) @@ -4979,6 +5336,10 @@ Enable in *Network & servers* settings. ลบ No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image No comment provided by engineer. @@ -5117,6 +5478,14 @@ Enable in *Network & servers* settings. เปิดเผย chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke ถอน @@ -5146,6 +5515,10 @@ Enable in *Network & servers* settings. SMP server No comment provided by engineer. + + SOCKS proxy + No comment provided by engineer. + Safely receive files No comment provided by engineer. @@ -5157,17 +5530,18 @@ Enable in *Network & servers* settings. Save บันทึก - chat item action + alert button + chat item action Save (and notify contacts) บันทึก (และแจ้งผู้ติดต่อ) - No comment provided by engineer. + alert button Save and notify contact บันทึกและแจ้งผู้ติดต่อ - No comment provided by engineer. + alert button Save and notify group members @@ -5183,16 +5557,6 @@ Enable in *Network & servers* settings. บันทึกและอัปเดตโปรไฟล์กลุ่ม No comment provided by engineer. - - Save archive - บันทึกไฟล์เก็บถาวร - No comment provided by engineer. - - - Save auto-accept settings - บันทึกการตั้งค่าการยอมรับอัตโนมัติ - No comment provided by engineer. - Save group profile บันทึกโปรไฟล์กลุ่ม @@ -5211,7 +5575,7 @@ Enable in *Network & servers* settings. Save preferences? บันทึกการตั้งค่า? - No comment provided by engineer. + alert title Save profile password @@ -5226,18 +5590,17 @@ Enable in *Network & servers* settings. Save servers? บันทึกเซิร์ฟเวอร์? - No comment provided by engineer. - - - Save settings? - บันทึกการตั้งค่า? - No comment provided by engineer. + alert title Save welcome message? บันทึกข้อความต้อนรับ? No comment provided by engineer. + + Save your profile? + alert title + Saved No comment provided by engineer. @@ -5255,6 +5618,10 @@ Enable in *Network & servers* settings. Saved message message info title + + Saving %lld messages + No comment provided by engineer. + Scale No comment provided by engineer. @@ -5328,6 +5695,10 @@ Enable in *Network & servers* settings. เลือก chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld No comment provided by engineer. @@ -5411,11 +5782,6 @@ Enable in *Network & servers* settings. ส่งการแจ้งเตือน No comment provided by engineer. - - Send notifications: - ส่งการแจ้งเตือน: - No comment provided by engineer. - Send questions and ideas ส่งคําถามและความคิด @@ -5438,7 +5804,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. ผู้ส่งยกเลิกการโอนไฟล์ - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5528,6 +5894,14 @@ Enable in *Network & servers* settings. Sent via proxy No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address No comment provided by engineer. @@ -5540,6 +5914,18 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password เซิร์ฟเวอร์ต้องการการอนุญาตในการสร้างคิว โปรดตรวจสอบรหัสผ่าน @@ -5637,6 +6023,10 @@ Enable in *Network & servers* settings. การตั้งค่า No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images No comment provided by engineer. @@ -5644,22 +6034,35 @@ Enable in *Network & servers* settings. Share แชร์ - chat item action + alert action + chat item action Share 1-time link แชร์ลิงก์แบบใช้ครั้งเดียว No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address แชร์ที่อยู่ No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? แชร์ที่อยู่กับผู้ติดต่อ? - No comment provided by engineer. + alert title Share from other apps. @@ -5670,6 +6073,10 @@ Enable in *Network & servers* settings. แชร์ลิงก์ No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link No comment provided by engineer. @@ -5732,6 +6139,10 @@ Enable in *Network & servers* settings. ที่อยู่ SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. ความปลอดภัยของ SimpleX Chat ได้รับการตรวจสอบโดย Trail of Bits @@ -5762,6 +6173,14 @@ Enable in *Network & servers* settings. ที่อยู่ SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address ที่อยู่ติดต่อ SimpleX @@ -5782,8 +6201,8 @@ Enable in *Network & servers* settings. ลิงก์ SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. No comment provided by engineer. @@ -5795,6 +6214,10 @@ Enable in *Network & servers* settings. คำเชิญ SimpleX แบบครั้งเดียว simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode No comment provided by engineer. @@ -5821,6 +6244,10 @@ Enable in *Network & servers* settings. Soft blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: No comment provided by engineer. @@ -5834,6 +6261,11 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody ใครบางคน @@ -5879,11 +6311,6 @@ Enable in *Network & servers* settings. Stop chat No comment provided by engineer. - - Stop chat to enable database actions - หยุดการแชทเพื่อเปิดใช้งานการดำเนินการกับฐานข้อมูล - 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. หยุดแชทเพื่อส่งออก นำเข้า หรือลบฐานข้อมูลแชท คุณจะไม่สามารถรับและส่งข้อความได้ในขณะที่การแชทหยุดลง @@ -5912,12 +6339,12 @@ Enable in *Network & servers* settings. Stop sharing หยุดแชร์ - No comment provided by engineer. + alert action Stop sharing address? หยุดแชร์ที่อยู่ไหม? - No comment provided by engineer. + alert title Stopping chat @@ -5949,6 +6376,14 @@ Enable in *Network & servers* settings. สนับสนุน SimpleX แชท No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System ระบบ @@ -5983,11 +6418,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture ถ่ายภาพ No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button แตะปุ่ม @@ -6042,7 +6485,7 @@ Enable in *Network & servers* settings. Tests failed! การทดสอบล้มเหลว! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6059,11 +6502,6 @@ Enable in *Network & servers* settings. ขอบคุณผู้ใช้ – มีส่วนร่วมผ่าน Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - แพลตฟอร์มแรกที่ไม่มีตัวระบุผู้ใช้ - ถูกออกแบบให้เป็นส่วนตัว - No comment provided by engineer. - 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. @@ -6077,6 +6515,10 @@ It can happen because of some bug or when the connection is compromised.แอปสามารถแจ้งให้คุณทราบเมื่อคุณได้รับข้อความหรือคำขอติดต่อ - โปรดเปิดการตั้งค่าเพื่อเปิดใช้งาน No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). No comment provided by engineer. @@ -6090,6 +6532,10 @@ It can happen because of some bug or when the connection is compromised.The code you scanned is not a SimpleX link QR code. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! การเชื่อมต่อที่คุณยอมรับจะถูกยกเลิก! @@ -6110,6 +6556,11 @@ It can happen because of some bug or when the connection is compromised.encryption กำลังทำงานและไม่จำเป็นต้องใช้ข้อตกลง encryption ใหม่ อาจทำให้การเชื่อมต่อผิดพลาดได้! No comment provided by engineer. + + The future of messaging + การส่งข้อความส่วนตัวรุ่นต่อไป + No comment provided by engineer. + The hash of the previous message is different. แฮชของข้อความก่อนหน้านี้แตกต่างกัน @@ -6133,11 +6584,6 @@ It can happen because of some bug or when the connection is compromised.The messages will be marked as moderated for all members. No comment provided by engineer. - - The next generation of private messaging - การส่งข้อความส่วนตัวรุ่นต่อไป - No comment provided by engineer. - The old database was not removed during the migration, it can be deleted. ฐานข้อมูลเก่าไม่ได้ถูกลบในระหว่างการย้ายข้อมูล แต่สามารถลบได้ @@ -6148,6 +6594,18 @@ It can happen because of some bug or when the connection is compromised.โปรไฟล์นี้แชร์กับผู้ติดต่อของคุณเท่านั้น No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ ขีดที่สองที่เราพลาด! ✅ @@ -6163,14 +6621,26 @@ It can happen because of some bug or when the connection is compromised.เซิร์ฟเวอร์สำหรับการเชื่อมต่อใหม่ของโปรไฟล์การแชทปัจจุบันของคุณ **%@** No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + No comment provided by engineer. + The text you pasted is not a SimpleX link. No comment provided by engineer. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes No comment provided by engineer. + + These conditions will also apply for: **%@**. + No comment provided by engineer. + These settings are for your current profile **%@**. การตั้งค่าเหล่านี้ใช้สำหรับโปรไฟล์ปัจจุบันของคุณ **%@** @@ -6260,9 +6730,8 @@ It can happen because of some bug or when the connection is compromised.เพื่อสร้างการเชื่อมต่อใหม่ 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. - เพื่อปกป้องความเป็นส่วนตัว แทนที่จะใช้ ID ผู้ใช้เหมือนที่แพลตฟอร์มอื่นๆใช้ SimpleX มีตัวระบุสำหรับคิวข้อความ โดยแยกจากกันสำหรับผู้ติดต่อแต่ละราย + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6281,6 +6750,23 @@ You will be prompted to complete authentication before this feature is enabled.< คุณจะได้รับแจ้งให้ยืนยันตัวตนให้เสร็จสมบูรณ์ก่อนที่จะเปิดใช้งานคุณลักษณะนี้ No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + เพื่อปกป้องความเป็นส่วนตัว แทนที่จะใช้ ID ผู้ใช้เหมือนที่แพลตฟอร์มอื่นๆใช้ SimpleX มีตัวระบุสำหรับคิวข้อความ โดยแยกจากกันสำหรับผู้ติดต่อแต่ละราย + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. ในการบันทึกข้อความเสียง โปรดให้สิทธิ์ในการใช้ไมโครโฟน @@ -6291,11 +6777,19 @@ You will be prompted to complete authentication before this feature is enabled.< หากต้องการเปิดเผยโปรไฟล์ที่ซ่อนอยู่ของคุณ ให้ป้อนรหัสผ่านแบบเต็มในช่องค้นหาในหน้า **โปรไฟล์แชทของคุณ** No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. เพื่อรองรับการแจ้งเตือนแบบทันที ฐานข้อมูลการแชทจะต้องได้รับการโยกย้าย No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. ในการตรวจสอบการเข้ารหัสแบบ encrypt จากต้นจนจบ กับผู้ติดต่อของคุณ ให้เปรียบเทียบ (หรือสแกน) รหัสบนอุปกรณ์ของคุณ @@ -6375,6 +6869,10 @@ You will be prompted to complete authentication before this feature is enabled.< Unblock member? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state สถานะการย้ายข้อมูลที่ไม่คาดคิด @@ -6422,7 +6920,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6522,11 +7020,19 @@ To connect, please ask your contact to create another connection link and check Uploading archive No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts ใช้โฮสต์ .onion No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? ใช้เซิร์ฟเวอร์ SimpleX Chat ไหม? @@ -6541,6 +7047,14 @@ To connect, please ask your contact to create another connection link and check Use current profile No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections ใช้สำหรับการเชื่อมต่อใหม่ @@ -6576,6 +7090,10 @@ To connect, please ask your contact to create another connection link and check ใช้เซิร์ฟเวอร์ No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. No comment provided by engineer. @@ -6584,15 +7102,14 @@ To connect, please ask your contact to create another connection link and check Use the app with one hand. No comment provided by engineer. - - User profile - โปรไฟล์ผู้ใช้ - No comment provided by engineer. - User selection No comment provided by engineer. + + Username + No comment provided by engineer. + Using SimpleX Chat servers. กำลังใช้เซิร์ฟเวอร์ SimpleX Chat อยู่ @@ -6657,11 +7174,19 @@ To connect, please ask your contact to create another connection link and check วิดีโอและไฟล์สูงสุด 1gb No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code ดูรหัสความปลอดภัย No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history chat feature @@ -6676,8 +7201,8 @@ To connect, please ask your contact to create another connection link and check ห้ามส่งข้อความเสียงในแชทนี้ No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. ข้อความเสียงเป็นสิ่งต้องห้ามในกลุ่มนี้ No comment provided by engineer. @@ -6764,9 +7289,8 @@ To connect, please ask your contact to create another connection link and check When connecting audio and video calls. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - เมื่อมีคนขอเชื่อมต่อ คุณสามารถยอมรับหรือปฏิเสธได้ + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -6805,7 +7329,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -6829,11 +7353,6 @@ To connect, please ask your contact to create another connection link and check XFTP server No comment provided by engineer. - - You - คุณ - No comment provided by engineer. - You **must not** use the same database on two devices. No comment provided by engineer. @@ -6858,6 +7377,10 @@ To connect, please ask your contact to create another connection link and check คุณได้เชื่อมต่อกับ %@ แล้ว No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. No comment provided by engineer. @@ -6910,6 +7433,14 @@ Repeat join request? You can change it in Appearance settings. No comment provided by engineer. + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. + No comment provided by engineer. + You can create it later คุณสามารถสร้างได้ในภายหลัง @@ -6947,6 +7478,10 @@ Repeat join request? You can send messages to %@ from Archived contacts. No comment provided by engineer. + + You can set connection name, to remember who the link was shared with. + No comment provided by engineer. + You can set lock screen notification preview via settings. คุณสามารถตั้งค่าแสดงตัวอย่างการแจ้งเตือนบนหน้าจอล็อคผ่านการตั้งค่า @@ -6962,11 +7497,6 @@ Repeat join request? คุณสามารถแบ่งปันที่อยู่นี้กับผู้ติดต่อของคุณเพื่อให้พวกเขาเชื่อมต่อกับ **%@** No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - คุณสามารถแชร์ที่อยู่ของคุณเป็นลิงก์หรือรหัสคิวอาร์ - ใคร ๆ ก็สามารถเชื่อมต่อกับคุณได้ - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app คุณสามารถเริ่มแชทผ่านการตั้งค่าแอป / ฐานข้อมูล หรือโดยการรีสตาร์ทแอป @@ -6988,23 +7518,23 @@ Repeat join request? You can view invitation link again in connection details. - No comment provided by engineer. + alert message You can't send messages! คุณไม่สามารถส่งข้อความได้! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - คุณควบคุมผ่านเซิร์ฟเวอร์ **เพื่อรับ** ข้อความผู้ติดต่อของคุณ - เซิร์ฟเวอร์ที่คุณใช้เพื่อส่งข้อความถึงพวกเขา - No comment provided by engineer. - You could not be verified; please try again. เราไม่สามารถตรวจสอบคุณได้ กรุณาลองอีกครั้ง. No comment provided by engineer. + + You decide who can connect. + ผู้คนสามารถเชื่อมต่อกับคุณผ่านลิงก์ที่คุณแบ่งปันเท่านั้น + No comment provided by engineer. + You have already requested connection via this address! No comment provided by engineer. @@ -7098,6 +7628,10 @@ Repeat connection request? คุณจะยังได้รับสายเรียกเข้าและการแจ้งเตือนจากโปรไฟล์ที่ปิดเสียงเมื่อโปรไฟล์ของเขามีการใช้งาน No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. คุณจะหยุดได้รับข้อความจากกลุ่มนี้ ประวัติการแชทจะถูกรักษาไว้ @@ -7118,11 +7652,6 @@ Repeat connection request? คุณกำลังใช้โปรไฟล์ที่ไม่ระบุตัวตนสำหรับกลุ่มนี้ - ไม่อนุญาตให้เชิญผู้ติดต่อเพื่อป้องกันการแชร์โปรไฟล์หลักของคุณ No comment provided by engineer. - - Your %@ servers - เซิร์ฟเวอร์ %@ ของคุณ - No comment provided by engineer. - Your ICE servers เซิร์ฟเวอร์ ICE ของคุณ @@ -7138,11 +7667,6 @@ Repeat connection request? ที่อยู่ SimpleX ของคุณ No comment provided by engineer. - - Your XFTP servers - เซิร์ฟเวอร์ XFTP ของคุณ - No comment provided by engineer. - Your calls การโทรของคุณ @@ -7158,11 +7682,19 @@ Repeat connection request? ฐานข้อมูลการแชทของคุณไม่ได้ถูก encrypt - ตั้งรหัสผ่านเพื่อ encrypt No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles โปรไฟล์แชทของคุณ No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). ผู้ติดต่อของคุณส่งไฟล์ที่ใหญ่กว่าขนาดสูงสุดที่รองรับในปัจจุบัน (%@) @@ -7178,6 +7710,10 @@ Repeat connection request? ผู้ติดต่อของคุณจะยังคงเชื่อมต่ออยู่ No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. ฐานข้อมูลแชทปัจจุบันของคุณจะถูกลบและแทนที่ด้วยฐานข้อมูลที่นำเข้า @@ -7206,13 +7742,15 @@ Repeat connection request? Your profile **%@** will be shared. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น -เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้ + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + โปรไฟล์ของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณและแชร์กับผู้ติดต่อของคุณเท่านั้น เซิร์ฟเวอร์ SimpleX ไม่สามารถดูโปรไฟล์ของคุณได้ No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. โปรไฟล์ รายชื่อผู้ติดต่อ และข้อความที่ส่งของคุณจะถูกจัดเก็บไว้ในอุปกรณ์ของคุณ @@ -7223,16 +7761,15 @@ SimpleX servers cannot see your profile. โปรไฟล์แบบสุ่มของคุณ No comment provided by engineer. - - Your server - เซิร์ฟเวอร์ของคุณ - No comment provided by engineer. - Your server address ที่อยู่เซิร์ฟเวอร์ของคุณ No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings การตั้งค่าของคุณ @@ -7273,6 +7810,10 @@ SimpleX servers cannot see your profile. รับสายแล้ว call status + + accepted invitation + chat list item title + admin ผู้ดูแลระบบ @@ -7451,7 +7992,7 @@ SimpleX servers cannot see your profile. connecting… กำลังเชื่อมต่อ… - chat list item title + No comment provided by engineer. connection established @@ -7636,6 +8177,10 @@ SimpleX servers cannot see your profile. expired No comment provided by engineer. + + for better metadata privacy. + No comment provided by engineer. + forwarded No comment provided by engineer. @@ -7921,6 +8466,10 @@ SimpleX servers cannot see your profile. ลบคุณออกแล้ว rcv group event chat item + + requested to connect + chat list item title + saved No comment provided by engineer. @@ -8223,6 +8772,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/th.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/th.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 054f65110f..261752aefc 100644 --- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,14 @@ %@ onaylandı No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded %@ yüklendi @@ -137,6 +130,11 @@ %@ bağlanmak istiyor! notification title + + %1$@, %2$@ + %1$@,%2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ ve %lld üyeleri @@ -157,11 +155,36 @@ %d gün time interval + + %d file(s) are still being downloaded. + %d dosyası(ları) hala indiriliyor. + forward confirmation reason + + + %d file(s) failed to download. + %d dosyası(ları) indirilemedi. + forward confirmation reason + + + %d file(s) were deleted. + %d dosyası(ları) silindi. + forward confirmation reason + + + %d file(s) were not downloaded. + %d dosyası(ları) indirilmedi. + forward confirmation reason + %d hours %d saat time interval + + %d messages not forwarded + %d mesajı iletilmeyedi + alert title + %d min %d dakika @@ -322,28 +345,23 @@ ) No comment provided by engineer. - - **Add contact**: to create a new invitation link, or connect via a link you received. + + **Create 1-time link**: to create and share a new invitation link. **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 or link 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. - - **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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. @@ -357,11 +375,15 @@ **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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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. + + **Scan / Paste link**: to connect via a link you received. + 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. @@ -468,6 +490,14 @@ 1 hafta time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5 dakika @@ -537,23 +567,18 @@ Adres değişimi iptal edilsin mi? No comment provided by engineer. - - About SimpleX - SimpleX Hakkında - No comment provided by engineer. - About SimpleX Chat SimpleX Chat hakkında No comment provided by engineer. - - About SimpleX address - SimpleX Chat adresi hakkında + + About operators No comment provided by engineer. Accent + Ana renk No comment provided by engineer. @@ -563,6 +588,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? Bağlantı isteği kabul edilsin mi? @@ -579,16 +608,23 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged + Onaylandı No comment provided by engineer. Acknowledgement errors + Onay hataları No comment provided by engineer. Active connections + Aktif bağlantılar No comment provided by engineer. @@ -596,14 +632,8 @@ 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 + + Add friends No comment provided by engineer. @@ -621,6 +651,10 @@ Karekod taratarak sunucuları ekleyin. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Başka bir cihaza ekle @@ -631,16 +665,31 @@ Karşılama mesajı ekleyin No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent + Ek ana renk No comment provided by engineer. Additional accent 2 + Ek vurgu 2 No comment provided by engineer. Additional secondary + Ek ikincil renk No comment provided by engineer. @@ -653,6 +702,14 @@ Adres değişikliği iptal edilecek. Eski alıcı adresi kullanılacaktır. No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. Yöneticiler bir üyeyi tamamen engelleyebilirler. @@ -670,6 +727,7 @@ Advanced settings + Gelişmiş ayarlar No comment provided by engineer. @@ -687,8 +745,9 @@ Kullanıldığında bütün veriler silinir. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. + Tüm veriler cihazınıza özeldir. No comment provided by engineer. @@ -696,6 +755,10 @@ Tüm grup üyeleri bağlı kalacaktır. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Tüm mesajlar silinecektir - bu geri alınamaz! @@ -713,7 +776,8 @@ All profiles - No comment provided by engineer. + Tüm Profiller + profile dropdown All your contacts will remain connected. @@ -742,6 +806,7 @@ Allow calls? + Aramalara izin verilsin mi ? No comment provided by engineer. @@ -781,6 +846,7 @@ Allow sharing + Paylaşıma izin ver No comment provided by engineer. @@ -873,6 +939,11 @@ Aramayı cevapla No comment provided by engineer. + + Anybody can host servers. + Açık kaynak protokolü ve kodu - herhangi biri sunucuları çalıştırabilir. + No comment provided by engineer. + App build: %@ Uygulama sürümü: %@ @@ -903,6 +974,11 @@ Uygulama parolası kendi kendini imha eden parolayla değiştirildi. No comment provided by engineer. + + App session + Uygulama oturumu + No comment provided by engineer. + App version Uygulama sürümü @@ -925,6 +1001,7 @@ Apply to + Şuna uygula No comment provided by engineer. @@ -934,10 +1011,12 @@ Archive contacts to chat later. + Daha sonra görüşmek için kişileri arşivleyin. No comment provided by engineer. Archived contacts + Arşivli kişiler No comment provided by engineer. @@ -1005,6 +1084,11 @@ Fotoğrafları otomatik kabul et No comment provided by engineer. + + Auto-accept settings + Ayarları otomatik olarak kabul et + alert title + Back Geri @@ -1012,6 +1096,7 @@ Background + Arka plan No comment provided by engineer. @@ -1029,11 +1114,21 @@ Kötü mesaj karması No comment provided by engineer. + + Better calls + Daha iyi aramalar + No comment provided by engineer. + Better groups Daha iyi gruplar No comment provided by engineer. + + Better message dates. + Daha iyi mesaj tarihleri. + No comment provided by engineer. + Better messages Daha iyi mesajlar @@ -1041,10 +1136,27 @@ Better networking + Daha iyi ağ oluşturma + No comment provided by engineer. + + + Better notifications + Daha iyi bildirimler + No comment provided by engineer. + + + Better security ✅ + Daha iyi güvenlik ✅ + No comment provided by engineer. + + + Better user experience + Daha iyi kullanıcı deneyimi No comment provided by engineer. Black + Siyah No comment provided by engineer. @@ -1084,10 +1196,12 @@ Blur for better privacy. + Daha iyi gizlilik için bulanıklaştır. No comment provided by engineer. Blur media + Medyayı bulanıklaştır No comment provided by engineer. @@ -1120,6 +1234,14 @@ 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. + + Business address + No comment provided by engineer. + + + Business chats + 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). @@ -1137,6 +1259,7 @@ Calls prohibited! + Aramalara izin verilmiyor! No comment provided by engineer. @@ -1146,10 +1269,12 @@ Can't call contact + Kişi aranamıyor No comment provided by engineer. Can't call member + Üye aranamaz No comment provided by engineer. @@ -1164,12 +1289,14 @@ Can't message member + Üyeye mesaj gönderilemiyor No comment provided by engineer. Cancel İptal et - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1183,12 +1310,13 @@ Cannot forward message + Mesaj iletilemiyor No comment provided by engineer. Cannot receive file Dosya alınamıyor - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1205,6 +1333,10 @@ Değiştir No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? Veritabanı parolasını değiştir? @@ -1251,13 +1383,21 @@ authentication reason set passcode view - - Chat archive - Sohbet arşivi + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. Chat colors + Sohbet renkleri No comment provided by engineer. @@ -1277,6 +1417,7 @@ Chat database exported + Veritabanı dışa aktarıldı No comment provided by engineer. @@ -1301,6 +1442,7 @@ Chat list + Sohbet listesi No comment provided by engineer. @@ -1313,8 +1455,27 @@ Sohbet tercihleri No comment provided by engineer. + + Chat preferences were changed. + Sohbet tercihleri değiştirildi. + alert message + + + Chat profile + Kullanıcı profili + No comment provided by engineer. + Chat theme + Sohbet teması + No comment provided by engineer. + + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! No comment provided by engineer. @@ -1322,10 +1483,18 @@ Sohbetler No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. Sunucu adresini kontrol edip tekrar deneyin. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1349,14 +1518,17 @@ Chunks deleted + Parçalar silindi No comment provided by engineer. Chunks downloaded + Parçalar indirildi No comment provided by engineer. Chunks uploaded + Parçalar yüklendi No comment provided by engineer. @@ -1386,10 +1558,12 @@ Color chats with the new themes. + Yeni temalarla renkli sohbetler. No comment provided by engineer. Color mode + Renk modu No comment provided by engineer. @@ -1404,6 +1578,43 @@ Completed + Tamamlandı + No comment provided by engineer. + + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. No comment provided by engineer. @@ -1411,10 +1622,6 @@ ICE sunucularını ayarla No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm Onayla @@ -1427,6 +1634,7 @@ Confirm contact deletion? + Kişiyi silmek istediğinizden emin misiniz ? No comment provided by engineer. @@ -1486,6 +1694,7 @@ Connect to your friends faster. + Arkadaşlarınıza daha hızlı bağlanın. No comment provided by engineer. @@ -1529,6 +1738,7 @@ Bu senin kendi tek kullanımlık bağlantın! Connected + Bağlandı No comment provided by engineer. @@ -1538,15 +1748,17 @@ Bu senin kendi tek kullanımlık bağlantın! Connected servers + Bağlı sunucular No comment provided by engineer. Connected to desktop - Bilgisayara bağlanıldı + Masaüstüne bağlandı No comment provided by engineer. Connecting + Bağlanıyor No comment provided by engineer. @@ -1561,6 +1773,7 @@ Bu senin kendi tek kullanımlık bağlantın! Connecting to contact, please wait or check later! + Kişiye bağlanılıyor, lütfen bekleyin ya da daha sonra kontrol edin! No comment provided by engineer. @@ -1575,6 +1788,7 @@ Bu senin kendi tek kullanımlık bağlantın! Connection and servers status. + Bağlantı ve sunucuların durumu. No comment provided by engineer. @@ -1589,6 +1803,7 @@ Bu senin kendi tek kullanımlık bağlantın! Connection notifications + Bağlantı bildirimleri No comment provided by engineer. @@ -1596,6 +1811,10 @@ Bu senin kendi tek kullanımlık bağlantın! Bağlantı daveti gönderildi! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated Bağlantı sonlandırılmış @@ -1608,10 +1827,12 @@ Bu senin kendi tek kullanımlık bağlantın! Connection with desktop stopped + Masaüstü ile bağlantı durduruldu No comment provided by engineer. Connections + Bağlantılar No comment provided by engineer. @@ -1626,6 +1847,7 @@ Bu senin kendi tek kullanımlık bağlantın! Contact deleted! + Kişiler silindi! No comment provided by engineer. @@ -1640,6 +1862,7 @@ Bu senin kendi tek kullanımlık bağlantın! Contact is deleted. + Kişi silindi. No comment provided by engineer. @@ -1654,6 +1877,7 @@ Bu senin kendi tek kullanımlık bağlantın! Contact will be deleted - this cannot be undone! + Kişiler silinecek - bu geri alınamaz ! No comment provided by engineer. @@ -1673,6 +1897,7 @@ Bu senin kendi tek kullanımlık bağlantın! Conversation deleted! + Sohbet silindi! No comment provided by engineer. @@ -1682,6 +1907,7 @@ Bu senin kendi tek kullanımlık bağlantın! Copy error + Kopyalama hatası No comment provided by engineer. @@ -1689,6 +1915,11 @@ Bu senin kendi tek kullanımlık bağlantın! Çekirdek sürümü: v%@ No comment provided by engineer. + + Corner + Köşeleri yuvarlama + No comment provided by engineer. + Correct name to %@? İsim %@ olarak düzeltilsin mi? @@ -1699,6 +1930,10 @@ Bu senin kendi tek kullanımlık bağlantın! Oluştur No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address SimpleX adresi oluştur @@ -1709,11 +1944,6 @@ Bu senin kendi tek kullanımlık bağlantın! 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. - No comment provided by engineer. - Create file Dosya oluştur @@ -1761,6 +1991,7 @@ Bu senin kendi tek kullanımlık bağlantın! Created + Yaratıldı No comment provided by engineer. @@ -1773,11 +2004,6 @@ Bu senin kendi tek kullanımlık bağlantın! Şurada oluşturuldu: %@ copied message info - - Created on %@ - %@ de oluşturuldu - No comment provided by engineer. - Creating archive link Arşiv bağlantısı oluşturuluyor @@ -1793,6 +2019,10 @@ Bu senin kendi tek kullanımlık bağlantın! Şu anki şifre No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… Şu anki parola… @@ -1800,6 +2030,7 @@ Bu senin kendi tek kullanımlık bağlantın! Current profile + Aktif profil No comment provided by engineer. @@ -1812,8 +2043,14 @@ Bu senin kendi tek kullanımlık bağlantın! Özel saat No comment provided by engineer. + + Customizable message shape. + Özelleştirilebilir mesaj şekli. + No comment provided by engineer. + Customize theme + Renk temalarını kişiselleştir No comment provided by engineer. @@ -1823,6 +2060,7 @@ Bu senin kendi tek kullanımlık bağlantın! Dark mode colors + Karanlık mod renkleri No comment provided by engineer. @@ -1941,11 +2179,13 @@ Bu senin kendi tek kullanımlık bağlantın! Delete Sil - chat item action + alert action + chat item action swipe action Delete %lld messages of members? + Üyelerin %lld mesajları silinsin mi? No comment provided by engineer. @@ -1978,14 +2218,8 @@ Bu senin kendi tek kullanımlık bağlantın! 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? + + Delete chat No comment provided by engineer. @@ -1998,6 +2232,10 @@ Bu senin kendi tek kullanımlık bağlantın! Sohbet profili silinsin mi? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Bağlantıyı sil @@ -2010,6 +2248,7 @@ Bu senin kendi tek kullanımlık bağlantın! Delete contact? + Kişiyi sil? No comment provided by engineer. @@ -2102,6 +2341,11 @@ Bu senin kendi tek kullanımlık bağlantın! Eski veritabanı silinsin mi? No comment provided by engineer. + + Delete or moderate up to 200 messages. + 200'e kadar mesajı silin veya düzenleyin. + No comment provided by engineer. + Delete pending connection? Bekleyen bağlantı silinsin mi? @@ -2119,6 +2363,7 @@ Bu senin kendi tek kullanımlık bağlantın! Delete up to 20 messages at once. + Tek seferde en fazla 20 mesaj silin. No comment provided by engineer. @@ -2128,10 +2373,12 @@ Bu senin kendi tek kullanımlık bağlantın! Delete without notification + Bildirim göndermeden sil No comment provided by engineer. Deleted + Silindi No comment provided by engineer. @@ -2146,6 +2393,11 @@ Bu senin kendi tek kullanımlık bağlantın! Deletion errors + Silme hatası + No comment provided by engineer. + + + Delivered even when Apple drops them. No comment provided by engineer. @@ -2185,6 +2437,7 @@ Bu senin kendi tek kullanımlık bağlantın! Destination server address of %@ is incompatible with forwarding server %@ settings. + Hedef sunucu adresi %@, yönlendirme sunucusu %@ ayarlarıyla uyumlu değil. No comment provided by engineer. @@ -2194,14 +2447,17 @@ Bu senin kendi tek kullanımlık bağlantın! Destination server version of %@ is incompatible with forwarding server %@. + Hedef sunucu %@ sürümü, yönlendirme sunucusu %@ ile uyumlu değil. No comment provided by engineer. Detailed statistics + Detaylı istatistikler No comment provided by engineer. Details + Detaylar No comment provided by engineer. @@ -2211,6 +2467,7 @@ Bu senin kendi tek kullanımlık bağlantın! Developer options + Geliştirici seçenekleri No comment provided by engineer. @@ -2243,8 +2500,12 @@ Bu senin kendi tek kullanımlık bağlantın! Doğrudan mesajlar chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. Bu grupta üyeler arasında direkt mesajlaşma yasaktır. No comment provided by engineer. @@ -2265,6 +2526,7 @@ Bu senin kendi tek kullanımlık bağlantın! Disabled + Devre dışı No comment provided by engineer. @@ -2282,8 +2544,8 @@ Bu senin kendi tek kullanımlık bağlantın! Kaybolan mesajlar bu sohbette yasaklanmış. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. Kaybolan mesajlar bu grupta yasaklanmış. No comment provided by engineer. @@ -2342,6 +2604,11 @@ Bu senin kendi tek kullanımlık bağlantın! Yeni üyelere geçmişi gönderme. No comment provided by engineer. + + Do not use credentials with proxy. + Kimlik bilgilerini proxy ile kullanmayın. + No comment provided by engineer. + Don't create address Adres oluşturma @@ -2365,10 +2632,12 @@ Bu senin kendi tek kullanımlık bağlantın! Download İndir - chat item action + alert button + chat item action Download errors + İndirme hataları No comment provided by engineer. @@ -2381,12 +2650,19 @@ Bu senin kendi tek kullanımlık bağlantın! Dosya indir server test step + + Download files + Dosyaları indirin + alert action + Downloaded + İndirildi No comment provided by engineer. Downloaded files + Dosyalar İndirildi No comment provided by engineer. @@ -2409,6 +2685,10 @@ Bu senin kendi tek kullanımlık bağlantın! Süre No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit Düzenle @@ -2429,6 +2709,10 @@ Bu senin kendi tek kullanımlık bağlantın! Etkinleştir (geçersiz kılmaları koru) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock SimpleX Kilidini etkinleştir @@ -2491,6 +2775,7 @@ Bu senin kendi tek kullanımlık bağlantın! Enabled + Etkin No comment provided by engineer. @@ -2633,26 +2918,34 @@ Bu senin kendi tek kullanımlık bağlantın! Adres değişikliği iptal edilirken hata oluştu No comment provided by engineer. + + Error accepting conditions + alert title + 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 adding server + alert title + Error changing address Adres değiştirilirken hata oluştu No comment provided by engineer. + + Error changing connection profile + Bağlantı profili değiştirilirken hata oluştu + No comment provided by engineer. + Error changing role Rol değiştirilirken hata oluştu @@ -2663,8 +2956,14 @@ Bu senin kendi tek kullanımlık bağlantın! Ayar değiştirilirken hata oluştu No comment provided by engineer. + + Error changing to incognito! + Gizli moduna geçerken hata oluştu! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. + Yönlendirme sunucusu %@'ya bağlanırken hata oluştu. Lütfen daha sonra deneyin. No comment provided by engineer. @@ -2764,6 +3063,7 @@ Bu senin kendi tek kullanımlık bağlantın! Error exporting theme: %@ + Tema dışa aktarılırken hata oluştu: %@ No comment provided by engineer. @@ -2776,9 +3076,13 @@ Bu senin kendi tek kullanımlık bağlantın! Gruba katılırken hata oluştu No comment provided by engineer. - - Error loading %@ servers - %@ sunucuları yüklenirken hata oluştu + + Error loading servers + alert title + + + Error migrating settings + Ayarlar taşınırken hata oluştu No comment provided by engineer. @@ -2789,14 +3093,16 @@ Bu senin kendi tek kullanımlık bağlantın! Error receiving file Dosya alınırken sorun oluştu - No comment provided by engineer. + alert title Error reconnecting server + Hata, sunucuya yeniden bağlanılıyor No comment provided by engineer. Error reconnecting servers + Hata sunuculara yeniden bağlanılıyor No comment provided by engineer. @@ -2806,11 +3112,7 @@ Bu senin kendi tek kullanımlık bağlantın! Error resetting statistics - No comment provided by engineer. - - - Error saving %@ servers - %@ sunucuları kaydedilirken sorun oluştu + Hata istatistikler sıfırlanıyor No comment provided by engineer. @@ -2833,6 +3135,10 @@ Bu senin kendi tek kullanımlık bağlantın! Parolayı Anahtar Zincirine kaydederken hata oluştu No comment provided by engineer. + + Error saving servers + alert title + Error saving settings Ayarlar kaydedilirken hata oluştu @@ -2878,10 +3184,15 @@ Bu senin kendi tek kullanımlık bağlantın! Sohbet durdurulurken hata oluştu No comment provided by engineer. + + Error switching profile + Profil değiştirme sırasında hata oluştu + No comment provided by engineer. + Error switching profile! Profil değiştirilirken hata oluştu! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2898,6 +3209,10 @@ Bu senin kendi tek kullanımlık bağlantın! Mesaj güncellenirken hata oluştu No comment provided by engineer. + + Error updating server + alert title + Error updating settings Ayarları güncellerken hata oluştu @@ -2926,8 +3241,7 @@ Bu senin kendi tek kullanımlık bağlantın! Error: %@ Hata: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2941,8 +3255,13 @@ Bu senin kendi tek kullanımlık bağlantın! Errors + Hatalar No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. Konuşma sırasında devre dışı bırakılsa bile. @@ -2970,6 +3289,7 @@ Bu senin kendi tek kullanımlık bağlantın! Export theme + Temayı dışa aktar No comment provided by engineer. @@ -3009,22 +3329,34 @@ Bu senin kendi tek kullanımlık bağlantın! File error + Dosya hatası No comment provided by engineer. + + File errors: +%@ + Dosya hataları: +%@ + alert message + File not found - most likely file was deleted or cancelled. + Dosya bulunamadı - muhtemelen dosya silindi veya göderim iptal edildi. file error text File server error: %@ + Dosya sunucusu hatası: %@ file error text File status + Dosya durumu No comment provided by engineer. File status: %@ + Dosya durumu: %@ copied message info @@ -3062,8 +3394,8 @@ Bu senin kendi tek kullanımlık bağlantın! Dosyalar ve medya chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Dosyalar ve medya bu grupta yasaklandı. No comment provided by engineer. @@ -3132,21 +3464,57 @@ Bu senin kendi tek kullanımlık bağlantın! Düzeltme grup üyesi tarafından desteklenmiyor No comment provided by engineer. + + For chat profile %@: + servers error + For console Konsol için No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward İlet chat item action + + Forward %d message(s)? + %d mesaj(lar)ı iletilsin mi? + alert title + Forward and save messages Mesajları ilet ve kaydet No comment provided by engineer. + + Forward messages + İletileri ilet + alert action + + + Forward messages without files? + Mesajlar dosyalar olmadan iletilsin mi ? + alert message + + + Forward up to 20 messages at once. + Aynı anda en fazla 20 mesaj iletin. + No comment provided by engineer. + Forwarded İletildi @@ -3157,16 +3525,24 @@ Bu senin kendi tek kullanımlık bağlantın! Şuradan iletildi No comment provided by engineer. + + Forwarding %lld messages + %lld mesajlarını ilet + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. + Yönlendirme sunucusu %@, hedef sunucu %@'ya bağlanamadı. Lütfen daha sonra deneyin. No comment provided by engineer. Forwarding server address is incompatible with network settings: %@. + Yönlendirme sunucusu adresi ağ ayarlarıyla uyumsuz: %@. No comment provided by engineer. Forwarding server version is incompatible with network settings: %@. + Yönlendirme sunucusu sürümü ağ ayarlarıyla uyumsuz: %@. No comment provided by engineer. @@ -3203,11 +3579,6 @@ Hata: %2$@ 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. @@ -3230,10 +3601,12 @@ Hata: %2$@ Good afternoon! + İyi öğlenler! message preview Good morning! + Günaydın! message preview @@ -3291,41 +3664,6 @@ Hata: %2$@ 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 irreversibly delete sent messages. (24 hours) - Grup üyeleri, gönderilen mesajları kalıcı olarak silebilir. (24 saat içinde) - No comment provided by engineer. - - - Group members can send SimpleX links. - Grup üyeleri SimpleX bağlantıları gönderebilir. - 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. - No comment provided by engineer. - Group message: Grup mesajı: @@ -3421,9 +3759,12 @@ Hata: %2$@ SimpleX nasıl çalışır No comment provided by engineer. - - How it works - Nasıl çalışıyor + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3451,6 +3792,11 @@ Hata: %2$@ ICE sunucuları (her satıra bir tane) No comment provided by engineer. + + IP address + IP adresi + 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ş. @@ -3491,8 +3837,8 @@ Hata: %2$@ Hemen No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Spam ve kötüye kullanıma karşı bağışıklı No comment provided by engineer. @@ -3518,6 +3864,7 @@ Hata: %2$@ Import theme + Temayı içe aktar No comment provided by engineer. @@ -3525,6 +3872,13 @@ Hata: %2$@ Arşiv içe aktarılıyor No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + İyileştirilmiş teslimat, azaltılmış trafik kullanımı. +Daha fazla iyileştirme yakında geliyor! + No comment provided by engineer. + Improved message delivery İyileştirilmiş mesaj iletimi @@ -3625,6 +3979,11 @@ Hata: %2$@ [Terminal için SimpleX Chat]i indir(https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Anında + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3632,11 +3991,6 @@ Hata: %2$@ No comment provided by engineer. - - Instantly - Anında - No comment provided by engineer. - Interface Arayüz @@ -3644,6 +3998,7 @@ Hata: %2$@ Interface colors + Arayüz renkleri No comment provided by engineer. @@ -3684,7 +4039,7 @@ Hata: %2$@ Invalid server address! Geçersiz sunucu adresi! - No comment provided by engineer. + alert title Invalid status @@ -3706,6 +4061,10 @@ Hata: %2$@ Üyeleri davet et No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Gruba davet et @@ -3721,8 +4080,8 @@ Hata: %2$@ Bu sohbette geri döndürülemez mesaj silme yasaktır. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. Bu grupta geri döndürülemez mesaj silme yasaktır. No comment provided by engineer. @@ -3749,6 +4108,7 @@ Hata: %2$@ It protects your IP address and connections. + IP adresinizi ve bağlantılarınızı korur. No comment provided by engineer. @@ -3811,10 +4171,11 @@ Bu senin grup için bağlantın %@! Keep Tut - No comment provided by engineer. + alert action Keep conversation + Sohbeti sakla No comment provided by engineer. @@ -3825,7 +4186,7 @@ Bu senin grup için bağlantın %@! Keep unused invitation? Kullanılmamış davet tutulsun mu? - No comment provided by engineer. + alert title Keep your connections @@ -3862,6 +4223,14 @@ Bu senin grup için bağlantın %@! Ayrıl swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Gruptan ayrıl @@ -3912,11 +4281,6 @@ Bu senin grup için bağlantın %@! Canlı mesajlar No comment provided by engineer. - - Local - Yerel - No comment provided by engineer. - Local name Yerel isim @@ -3937,11 +4301,6 @@ Bu senin grup için bağlantın %@! 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 @@ -3952,21 +4311,11 @@ Bu senin grup için bağlantın %@! 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 @@ -3994,10 +4343,12 @@ Bu senin grup için bağlantın %@! Media & file servers + Medya ve dosya sunucuları No comment provided by engineer. Medium + Orta blur media @@ -4007,8 +4358,13 @@ Bu senin grup için bağlantın %@! Member inactive + Üye inaktif item status text + + Member role will be changed to "%@". All chat members will be notified. + 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. @@ -4019,13 +4375,53 @@ Bu senin grup için bağlantın %@! Üye rolü "%@" olarak değiştirilecektir. Ve üye yeni bir davetiye alacaktır. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Üye gruptan çıkarılacaktır - bu geri alınamaz! No comment provided by engineer. + + Members can add message reactions. + Grup üyeleri mesaj tepkileri ekleyebilir. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Grup üyeleri, gönderilen mesajları kalıcı olarak silebilir. (24 saat içinde) + No comment provided by engineer. + + + Members can send SimpleX links. + Grup üyeleri SimpleX bağlantıları gönderebilir. + No comment provided by engineer. + + + Members can send direct messages. + Grup üyeleri doğrudan mesajlar gönderebilir. + No comment provided by engineer. + + + Members can send disappearing messages. + Grup üyeleri kaybolan mesajlar gönderebilir. + No comment provided by engineer. + + + Members can send files and media. + Grup üyeleri dosyalar ve medya gönderebilir. + No comment provided by engineer. + + + Members can send voice messages. + Grup üyeleri sesli mesajlar gönderebilir. + No comment provided by engineer. + Menus + Menüler No comment provided by engineer. @@ -4050,10 +4446,12 @@ Bu senin grup için bağlantın %@! Message forwarded + Mesaj iletildi item status text Message may be delivered later if member becomes active. + Kullanıcı aktif olursa mesaj iletilebilir. item status description @@ -4071,17 +4469,24 @@ Bu senin grup için bağlantın %@! Mesaj tepkileri bu sohbette yasaklandı. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Mesaj tepkileri bu grupta yasaklandı. No comment provided by engineer. Message reception + Mesaj alındısı No comment provided by engineer. Message servers + Mesaj sunucuları + No comment provided by engineer. + + + Message shape + Mesaj şekli No comment provided by engineer. @@ -4091,10 +4496,12 @@ Bu senin grup için bağlantın %@! Message status + Mesaj durumu No comment provided by engineer. Message status: %@ + Mesaj durumu: %@ copied message info @@ -4124,12 +4531,19 @@ Bu senin grup için bağlantın %@! Messages received + Mesajlar alındı No comment provided by engineer. Messages sent + Mesajlar gönderildi No comment provided by engineer. + + Messages were deleted after you selected them. + Mesajlar siz seçtikten sonra silindi. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Mesajlar, dosyalar ve aramalar **uçtan uca şifreleme** ile mükemmel ileri gizlilik, inkar ve izinsiz giriş kurtarma ile korunur. @@ -4195,9 +4609,9 @@ Bu senin grup için bağlantın %@! Geçiş tamamlandı No comment provided by engineer. - - Migrations: %@ - Geçişler: %@ + + Migrations: + Geçişler: No comment provided by engineer. @@ -4225,6 +4639,10 @@ Bu senin grup için bağlantın %@! Daha güvenilir ağ bağlantısı. No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. Büyük ihtimalle bu bağlantı silinmiş. @@ -4260,6 +4678,10 @@ Bu senin grup için bağlantın %@! Ağ bağlantısı No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Ağ sorunları - birçok gönderme denemesinden sonra mesajın süresi doldu. @@ -4270,6 +4692,10 @@ Bu senin grup için bağlantın %@! Ağ yönetimi No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings Ağ ayarları @@ -4285,6 +4711,16 @@ Bu senin grup için bağlantın %@! Yeni şifre No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Uygulamayı her başlattığınızda yeni SOCKS kimlik bilgileri kullanılacaktır. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Her sunucu için yeni SOCKS kimlik bilgileri kullanılacaktır. + No comment provided by engineer. + New chat Yeni sohbet @@ -4292,6 +4728,7 @@ Bu senin grup için bağlantın %@! New chat experience 🎉 + Yeni bir sohbet deneyimi 🎉 No comment provided by engineer. @@ -4304,11 +4741,6 @@ Bu senin grup için bağlantın %@! Yeni kişi: notification - - New database archive - Yeni veritabanı arşivi - No comment provided by engineer. - New desktop app! Yeni bilgisayar uygulaması! @@ -4319,6 +4751,10 @@ Bu senin grup için bağlantın %@! Yeni görünen ad No comment provided by engineer. + + New events + notification + New in %@ %@ da yeni @@ -4326,6 +4762,7 @@ Bu senin grup için bağlantın %@! New media options + Yeni medya seçenekleri No comment provided by engineer. @@ -4343,6 +4780,10 @@ Bu senin grup için bağlantın %@! Yeni parola… No comment provided by engineer. + + New server + No comment provided by engineer. + No Hayır @@ -4375,6 +4816,7 @@ Bu senin grup için bağlantın %@! No direct connection yet, message is forwarded by admin. + Henüz direkt bağlantı yok mesaj admin tarafından yönlendirildi. item status description @@ -4394,23 +4836,68 @@ Bu senin grup için bağlantın %@! No info, try to reload + Bilgi yok, yenilemeyi deneyin No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection Ağ bağlantısı yok No comment provided by engineer. + + No permission to record speech + Konuşma kaydetme izni yok + No comment provided by engineer. + + + No permission to record video + Video kaydı için izin 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 push server + Yerel + No comment provided by engineer. + No received or sent files Hiç alınmış veya gönderilmiş dosya yok No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + Herhangi bir kullanıcı tanımlayıcısı yok. + No comment provided by engineer. + Not compatible! Uyumlu değil! @@ -4418,8 +4905,14 @@ Bu senin grup için bağlantın %@! Nothing selected + Hiçbir şey seçilmedi No comment provided by engineer. + + Nothing to forward! + Yönlendirilecek bir şey yok! + alert title + Notifications Bildirimler @@ -4430,6 +4923,10 @@ Bu senin grup için bağlantın %@! Bildirimler devre dışı! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4452,18 +4949,13 @@ Bu senin grup için bağlantın %@! Ok Tamam - No comment provided by engineer. + alert button Old database Eski veritabanı No comment provided by engineer. - - Old database archive - Eski veritabanı arşivi - No comment provided by engineer. - One-time invitation link Tek zamanlı bağlantı daveti @@ -4488,13 +4980,18 @@ VPN'nin etkinleştirilmesi gerekir. 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**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. 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 delete conversation + Sadece sohbeti sil No comment provided by engineer. @@ -4572,6 +5069,10 @@ VPN'nin etkinleştirilmesi gerekir. Ayarları aç No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat Sohbeti aç @@ -4582,6 +5083,10 @@ VPN'nin etkinleştirilmesi gerekir. Sohbet konsolunu aç authentication reason + + Open conditions + No comment provided by engineer. + Open group Grubu aç @@ -4592,25 +5097,23 @@ VPN'nin etkinleştirilmesi gerekir. Başka bir cihaza açık geçiş authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - Kullanıcı profillerini aç - authentication reason - - - 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. + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link Veya arşiv bağlantısını yapıştırın @@ -4631,14 +5134,21 @@ VPN'nin etkinleştirilmesi gerekir. Veya bu kodu göster No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other Diğer No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + Diğer dosya hataları: +%@ + alert message PING count @@ -4675,6 +5185,11 @@ VPN'nin etkinleştirilmesi gerekir. Şifre ayarlandı! No comment provided by engineer. + + Password + Şifre + No comment provided by engineer. + Password to show Gösterilecek şifre @@ -4707,15 +5222,11 @@ VPN'nin etkinleştirilmesi gerekir. Pending + Bekleniyor 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 + + Periodic Periyodik olarak No comment provided by engineer. @@ -4731,10 +5242,12 @@ VPN'nin etkinleştirilmesi gerekir. Play from the chat list. + Sohbet listesinden oynat. No comment provided by engineer. Please ask your contact to enable calls. + Lütfen kişinizden çağrılara izin vermesini isteyin. No comment provided by engineer. @@ -4745,6 +5258,8 @@ VPN'nin etkinleştirilmesi gerekir. Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection. Please share any other issues with the developers. + Lütfen telefonun ve bilgisayarın aynı lokal ağa bağlı olduğundan ve bilgisayar güvenlik duvarının bağlantıya izin verdiğinden emin olun. +Lütfen diğer herhangi bir sorunu geliştiricilerle paylaşın. No comment provided by engineer. @@ -4819,6 +5334,11 @@ Hata: %@ Lehçe arayüz No comment provided by engineer. + + Port + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Muhtemelen, sunucu adresindeki parmakizi sertifikası doğru değil @@ -4829,16 +5349,15 @@ Hata: %@ 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. + + Preset servers + No comment provided by engineer. + Preview Ön izleme @@ -4846,6 +5365,7 @@ Hata: %@ Previously connected servers + Önceden bağlanılmış sunucular No comment provided by engineer. @@ -4853,6 +5373,10 @@ Hata: %@ Gizlilik & güvenlik No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Gizlilik yeniden tanımlandı @@ -4885,6 +5409,7 @@ Hata: %@ Private routing error + Gizli yönlendirme hatası No comment provided by engineer. @@ -4902,16 +5427,6 @@ Hata: %@ Profil resimleri 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ı @@ -4919,12 +5434,13 @@ Hata: %@ Profile theme + Profil teması 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. + alert message Prohibit audio/video calls. @@ -5005,10 +5521,17 @@ Enable in *Network & servers* settings. Proxied + Proxyli No comment provided by engineer. Proxied servers + Proxy sunucuları + No comment provided by engineer. + + + Proxy requires password + Proxy şifre gerektirir No comment provided by engineer. @@ -5033,6 +5556,7 @@ Enable in *Network & servers* settings. Reachable chat toolbar + Erişilebilir sohbet araç çubuğu No comment provided by engineer. @@ -5050,26 +5574,21 @@ Enable in *Network & servers* settings. 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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + [Kullanıcı Rehberi]nde daha fazlasını okuyun(https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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. - Daha fazlasını GitHub depomuzdan oku. - 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). @@ -5077,11 +5596,12 @@ Enable in *Network & servers* settings. Receipts are disabled - Gönderildi bilgisi devre dışı bırakıldı + Alıcılar devre dışı bırakıldı No comment provided by engineer. Receive errors + Alım sırasında hata No comment provided by engineer. @@ -5106,14 +5626,17 @@ Enable in *Network & servers* settings. Received messages + Alınan mesajlar No comment provided by engineer. Received reply + Alınan cevap No comment provided by engineer. Received total + Toplam alınan No comment provided by engineer. @@ -5148,6 +5671,7 @@ Enable in *Network & servers* settings. Reconnect + Yeniden bağlan No comment provided by engineer. @@ -5157,18 +5681,22 @@ Enable in *Network & servers* settings. Reconnect all servers + Tüm sunuculara yeniden bağlan No comment provided by engineer. Reconnect all servers? + Tüm sunuculara yeniden bağlansın mı? No comment provided by engineer. Reconnect server to force message delivery. It uses additional traffic. + Mesajı göndermeye zorlamak için sunucuya yeniden bağlan. Bu ekstra internet kullanır. No comment provided by engineer. Reconnect server? + Sunucuya yeniden bağlansın mı ? No comment provided by engineer. @@ -5222,8 +5750,14 @@ Enable in *Network & servers* settings. Sil No comment provided by engineer. + + Remove archive? + Arşiv kaldırılsın mı ? + No comment provided by engineer. + Remove image + Resmi kaldır No comment provided by engineer. @@ -5298,14 +5832,17 @@ Enable in *Network & servers* settings. Reset all hints + Tüm ip uçlarını sıfırla No comment provided by engineer. Reset all statistics + Tüm istatistikleri sıfırla No comment provided by engineer. Reset all statistics? + Tüm istatistikler sıfırlansın mı ? No comment provided by engineer. @@ -5315,6 +5852,7 @@ Enable in *Network & servers* settings. Reset to app theme + Uygulama temasına sıfırla No comment provided by engineer. @@ -5324,6 +5862,7 @@ Enable in *Network & servers* settings. Reset to user theme + Kullanıcı temasına sıfırla No comment provided by engineer. @@ -5366,6 +5905,14 @@ Enable in *Network & servers* settings. Göster chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke İptal et @@ -5393,6 +5940,12 @@ Enable in *Network & servers* settings. SMP server + SMP sunucusu + No comment provided by engineer. + + + SOCKS proxy + SOCKS vekili No comment provided by engineer. @@ -5408,17 +5961,18 @@ Enable in *Network & servers* settings. Save Kaydet - chat item action + alert button + chat item action Save (and notify contacts) Kaydet (ve kişilere bildir) - No comment provided by engineer. + alert button Save and notify contact Kaydet ve kişilere bildir - No comment provided by engineer. + alert button Save and notify group members @@ -5427,6 +5981,7 @@ Enable in *Network & servers* settings. Save and reconnect + Kayıt et ve yeniden bağlan No comment provided by engineer. @@ -5434,16 +5989,6 @@ Enable in *Network & servers* settings. 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 @@ -5462,7 +6007,7 @@ Enable in *Network & servers* settings. Save preferences? Tercihler kaydedilsin mi? - No comment provided by engineer. + alert title Save profile password @@ -5477,18 +6022,18 @@ Enable in *Network & servers* settings. Save servers? Sunucular kaydedilsin mi? - No comment provided by engineer. - - - Save settings? - Ayarlar kaydedilsin mi? - No comment provided by engineer. + alert title Save welcome message? Hoşgeldin mesajı kaydedilsin mi? No comment provided by engineer. + + Save your profile? + Profiliniz kaydedilsin mi? + alert title + Saved Kaydedildi @@ -5509,12 +6054,19 @@ Enable in *Network & servers* settings. Kaydedilmiş mesaj message info title + + Saving %lld messages + %lld mesajlarını kaydet + No comment provided by engineer. + Scale + Ölçeklendir No comment provided by engineer. Scan / Paste link + Tara / Bağlantı yapıştır No comment provided by engineer. @@ -5559,6 +6111,7 @@ Enable in *Network & servers* settings. Secondary + İkincil renk No comment provided by engineer. @@ -5568,6 +6121,7 @@ Enable in *Network & servers* settings. Secured + Güvenli No comment provided by engineer. @@ -5585,12 +6139,19 @@ Enable in *Network & servers* settings. Seç chat item action + + Select chat profile + Sohbet profili seç + No comment provided by engineer. + Selected %lld + Seçilen %lld No comment provided by engineer. Selected chat preferences prohibit this message. + Seçilen sohbet tercihleri bu mesajı yasakladı. No comment provided by engineer. @@ -5640,6 +6201,7 @@ Enable in *Network & servers* settings. Send errors + Gönderme hataları No comment provided by engineer. @@ -5654,6 +6216,7 @@ Enable in *Network & servers* settings. Send message to enable calls. + Çağrıları aktif etmek için mesaj gönder. No comment provided by engineer. @@ -5671,11 +6234,6 @@ Enable in *Network & servers* settings. 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 @@ -5699,7 +6257,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Gönderici dosya gönderimini iptal etti. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5713,7 +6271,7 @@ Enable in *Network & servers* settings. Sending delivery receipts will be enabled for all contacts. - Gönderildi bilgisi tüm kişiler için etkinleştirilecektir. + Tüm kişiler için iletim bilgisi gönderme özelliği etkinleştirilecek. No comment provided by engineer. @@ -5758,6 +6316,7 @@ Enable in *Network & servers* settings. Sent directly + Direkt gönderildi No comment provided by engineer. @@ -5772,6 +6331,7 @@ Enable in *Network & servers* settings. Sent messages + Gönderilen mesajlar No comment provided by engineer. @@ -5781,18 +6341,31 @@ Enable in *Network & servers* settings. Sent reply + Gönderilen cevap No comment provided by engineer. Sent total + Gönderilen tüm mesajların toplamı No comment provided by engineer. Sent via proxy + Bir proxy aracılığıyla gönderildi No comment provided by engineer. + + Server + Sunucu + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address + Sunucu adresi No comment provided by engineer. @@ -5802,8 +6375,21 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. + Sunucu adresi ağ ayarlarıyla uyumsuz: %@. No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password Sunucunun sıra oluşturması için yetki gereklidir, şifreyi kontrol edin @@ -5821,6 +6407,7 @@ Enable in *Network & servers* settings. Server type + Sunucu tipi No comment provided by engineer. @@ -5830,6 +6417,7 @@ Enable in *Network & servers* settings. Server version is incompatible with your app: %@. + Sunucu sürümü uygulamanızla uyumlu değil: %@. No comment provided by engineer. @@ -5839,10 +6427,12 @@ Enable in *Network & servers* settings. Servers info + Sunucu bilgileri No comment provided by engineer. Servers statistics will be reset - this cannot be undone! + Sunucu istatistikleri sıfırlanacaktır - bu geri alınamaz! No comment provided by engineer. @@ -5862,6 +6452,7 @@ Enable in *Network & servers* settings. Set default theme + Varsayılan temaya ayarla No comment provided by engineer. @@ -5904,6 +6495,11 @@ Enable in *Network & servers* settings. Ayarlar No comment provided by engineer. + + Settings were changed. + Ayarlar değiştirildi. + alert message + Shape profile images Profil resimlerini şekillendir @@ -5912,25 +6508,39 @@ Enable in *Network & servers* settings. Share Paylaş - chat item action + alert action + chat item action Share 1-time link Tek kullanımlık bağlantıyı paylaş No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address Adresi paylaş No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? Kişilerle adres paylaşılsın mı? - No comment provided by engineer. + alert title Share from other apps. + Diğer uygulamalardan paylaşın. No comment provided by engineer. @@ -5938,6 +6548,11 @@ Enable in *Network & servers* settings. Bağlantıyı paylaş No comment provided by engineer. + + Share profile + Profil paylaş + No comment provided by engineer. + Share this 1-time invite link Bu tek kullanımlık bağlantı davetini paylaş @@ -5945,6 +6560,7 @@ Enable in *Network & servers* settings. Share to SimpleX + SimpleX ile paylaş No comment provided by engineer. @@ -5979,6 +6595,7 @@ Enable in *Network & servers* settings. Show percentage + Yüzdeyi göster No comment provided by engineer. @@ -5998,6 +6615,7 @@ Enable in *Network & servers* settings. SimpleX + SimpleX No comment provided by engineer. @@ -6005,6 +6623,10 @@ Enable in *Network & servers* settings. SimpleX Adresi No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + 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. @@ -6035,6 +6657,14 @@ Enable in *Network & servers* settings. SimpleX adresi No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX kişi adresi @@ -6055,8 +6685,8 @@ Enable in *Network & servers* settings. SimpleX bağlantıları chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. SimpleX bağlantıları bu grupta yasaklandı. No comment provided by engineer. @@ -6070,6 +6700,11 @@ Enable in *Network & servers* settings. SimpleX tek kullanımlık davet simplex link type + + SimpleX protocols reviewed by Trail of Bits. + SimpleX protokolleri Trail of Bits tarafından incelenmiştir. + No comment provided by engineer. + Simplified incognito mode Basitleştirilmiş gizli mod @@ -6077,6 +6712,7 @@ Enable in *Network & servers* settings. Size + Boyut No comment provided by engineer. @@ -6096,10 +6732,17 @@ Enable in *Network & servers* settings. Soft + Yumuşak blur media + + Some app settings were not migrated. + Bazı uygulama ayarları taşınamadı. + No comment provided by engineer. + Some file(s) were not exported: + Bazı dosya(lar) dışa aktarılmadı: No comment provided by engineer. @@ -6109,8 +6752,14 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: + İçe aktarma sırasında bazı önemli olmayan hatalar oluştu: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody Biri @@ -6138,10 +6787,12 @@ Enable in *Network & servers* settings. Starting from %@. + %@'dan başlayarak. No comment provided by engineer. Statistics + İstatistikler No comment provided by engineer. @@ -6159,11 +6810,6 @@ Enable in *Network & servers* settings. Sohbeti kes 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. @@ -6192,12 +6838,12 @@ Enable in *Network & servers* settings. Stop sharing Paylaşmayı durdur - No comment provided by engineer. + alert action Stop sharing address? Adresi paylaşmak durdurulsun mu? - No comment provided by engineer. + alert title Stopping chat @@ -6206,6 +6852,7 @@ Enable in *Network & servers* settings. Strong + Güçlü blur media @@ -6215,14 +6862,17 @@ Enable in *Network & servers* settings. Subscribed + Abone olundu No comment provided by engineer. Subscription errors + Abone olurken hata No comment provided by engineer. Subscriptions ignored + Abonelikler göz ardı edildi No comment provided by engineer. @@ -6230,6 +6880,16 @@ Enable in *Network & servers* settings. SimpleX Chat'e destek ol No comment provided by engineer. + + Switch audio and video during the call. + Görüşme sırasında ses ve görüntüyü değiştirin. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Sohbet profilini 1 kerelik davetler için değiştirin. + No comment provided by engineer. + System Sistem @@ -6242,6 +6902,7 @@ Enable in *Network & servers* settings. TCP connection + TCP bağlantısı No comment provided by engineer. @@ -6264,11 +6925,20 @@ Enable in *Network & servers* settings. TCP_TVLDEKAL No comment provided by engineer. + + Tail + Konuşma balonu + No comment provided by engineer. + Take picture Fotoğraf çek No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Tuşa bas @@ -6306,6 +6976,7 @@ Enable in *Network & servers* settings. Temporary file error + Geçici dosya hatası No comment provided by engineer. @@ -6326,7 +6997,7 @@ Enable in *Network & servers* settings. Tests failed! Testler başarısız oldu! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6343,11 +7014,6 @@ Enable in *Network & servers* settings. 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 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. @@ -6360,6 +7026,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. 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 app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). Uygulama bilinmeyen dosya sunucularından indirmeleri onaylamanızı isteyecektir (.onion hariç). @@ -6375,6 +7045,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Taradığınız kod bir SimpleX bağlantı QR kodu değildir. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! Bağlantı kabulünüz iptal edilecektir! @@ -6395,6 +7069,11 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Şifreleme çalışıyor ve yeni şifreleme anlaşması gerekli değil. Bağlantı hatalarına neden olabilir! No comment provided by engineer. + + The future of messaging + Gizli mesajlaşmanın yeni nesli + No comment provided by engineer. + The hash of the previous message is different. Önceki mesajın hash'i farklı. @@ -6412,15 +7091,12 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. The messages will be deleted for all members. + Mesajlar tüm üyeler için silinecektir. No comment provided by engineer. The messages will be marked as moderated for all members. - No comment provided by engineer. - - - The next generation of private messaging - Gizli mesajlaşmanın yeni nesli + Mesajlar tüm üyeler için moderasyonlu olarak işaretlenecektir. No comment provided by engineer. @@ -6433,6 +7109,18 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Profil sadece kişilerinle paylaşılacak. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ Özlediğimiz ikinci tik! ✅ @@ -6448,13 +7136,27 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Mevcut sohbet profilinizin yeni bağlantıları için sunucular **%@**. No comment provided by engineer. + + The servers for new files of your current chat profile **%@**. + 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. + + The uploaded database archive will be permanently removed from the servers. + Yüklenen veritabanı arşivi sunuculardan kalıcı olarak kaldırılacaktır. + No comment provided by engineer. + Themes + Temalar + No comment provided by engineer. + + + These conditions will also apply for: **%@**. No comment provided by engineer. @@ -6524,6 +7226,7 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. This link was used with another mobile device, please create a new link on the desktop. + Bu bağlantı başka bir mobil cihazda kullanıldı, lütfen masaüstünde yeni bir bağlantı oluşturun. No comment provided by engineer. @@ -6533,6 +7236,7 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. Title + Başlık No comment provided by engineer. @@ -6555,9 +7259,8 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir. 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. + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6577,6 +7280,25 @@ You will be prompted to complete authentication before this feature is enabled.< Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenecektir. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs 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 receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Konuşmayı kaydetmek için lütfen Mikrofon kullanma izni verin. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Video kaydetmek için lütfen Kamera kullanım izni verin. + 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. @@ -6587,11 +7309,19 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Gizli profilinizi ortaya çıkarmak için **Sohbet profilleriniz** sayfasındaki arama alanına tam bir şifre girin. No comment provided by engineer. + + To send + 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 use the servers of **%@**, accept conditions of use. + 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). @@ -6599,6 +7329,7 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Toggle chat list: + Sohbet listesini değiştir: No comment provided by engineer. @@ -6608,10 +7339,12 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Toolbar opacity + Araç çubuğu opaklığı No comment provided by engineer. Total + Toplam No comment provided by engineer. @@ -6621,6 +7354,7 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Transport sessions + Taşıma oturumları No comment provided by engineer. @@ -6678,6 +7412,10 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Üyenin engeli kaldırılsın mı? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state Beklenmeyen geçiş durumu @@ -6726,7 +7464,7 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec Unknown servers! Bilinmeyen sunucular! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6792,6 +7530,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Update settings? + Ayarları güncelleyelim mi? No comment provided by engineer. @@ -6806,6 +7545,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Upload errors + Yükleme hataları No comment provided by engineer. @@ -6820,10 +7560,12 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Uploaded + Yüklendi No comment provided by engineer. Uploaded files + Yüklenen dosyalar No comment provided by engineer. @@ -6831,11 +7573,20 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Arşiv yükleme No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts .onion ana bilgisayarlarını kullan No comment provided by engineer. + + Use SOCKS proxy + SOCKS vekili kullan + No comment provided by engineer. + Use SimpleX Chat servers? SimpleX Chat sunucuları kullanılsın mı? @@ -6851,6 +7602,14 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Şu anki profili kullan No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections Yeni bağlantılar için kullan @@ -6891,6 +7650,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Sunucu kullan No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. Görüşme sırasında uygulamayı kullanın. @@ -6898,15 +7661,17 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Use the app with one hand. - No comment provided by engineer. - - - User profile - Kullanıcı profili + Uygulamayı tek elle kullan. No comment provided by engineer. User selection + Kullanıcı seçimi + No comment provided by engineer. + + + Username + Kullanıcı Adı No comment provided by engineer. @@ -6979,11 +7744,19 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste 1gb'a kadar videolar ve dosyalar No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code Güvenlik kodunu görüntüle No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history Görünür geçmiş @@ -6999,8 +7772,8 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Bu sohbette sesli mesajlar yasaktır. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Bu grupta sesli mesajlar yasaktır. No comment provided by engineer. @@ -7041,10 +7814,12 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Wallpaper accent + Duvar kağıdı vurgusu No comment provided by engineer. Wallpaper background + Duvar kağıdı arkaplanı No comment provided by engineer. @@ -7092,9 +7867,8 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Sesli ve görüntülü aramalara bağlanırken. 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. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7140,7 +7914,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Tor veya VPN olmadan, IP adresiniz bu XFTP aktarıcıları tarafından görülebilir: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7154,6 +7928,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Wrong key or unknown file chunk address - most likely file is deleted. + Yanlış anahtar veya bilinmeyen dosya yığın adresi - büyük olasılıkla dosya silinmiştir. file error text @@ -7163,11 +7938,7 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste XFTP server - No comment provided by engineer. - - - You - Sen + XFTP sunucusu No comment provided by engineer. @@ -7195,6 +7966,10 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste Zaten %@'a bağlısınız. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. Zaten %@'a bağlanıyorsunuz. @@ -7244,6 +8019,7 @@ Katılma isteği tekrarlansın mı? You are not connected to these servers. Private routing is used to deliver messages to them. + Bu sunuculara bağlı değilsiniz. Mesajları onlara iletmek için özel yönlendirme kullanılır. No comment provided by engineer. @@ -7253,6 +8029,15 @@ Katılma isteği tekrarlansın mı? You can change it in Appearance settings. + Görünüm ayarlarından değiştirebilirsiniz. + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. No comment provided by engineer. @@ -7292,6 +8077,11 @@ Katılma isteği tekrarlansın mı? You can send messages to %@ from Archived contacts. + Arşivlenen kişilerden %@'ya mesaj gönderebilirsiniz. + No comment provided by engineer. + + + You can set connection name, to remember who the link was shared with. No comment provided by engineer. @@ -7309,11 +8099,6 @@ Katılma isteği tekrarlansın mı? 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 @@ -7321,6 +8106,7 @@ Katılma isteği tekrarlansın mı? You can still view conversation with %@ in the list of chats. + Sohbet listesinde %@ ile konuşmayı görüntülemeye devam edebilirsiniz. No comment provided by engineer. @@ -7336,23 +8122,23 @@ Katılma isteği tekrarlansın mı? 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. + alert message You can't send messages! Mesajlar gönderemezsiniz! 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 decide who can connect. + Kimin bağlanabileceğine siz karar verirsiniz. + No comment provided by engineer. + You have already requested connection via this address! Bu adres üzerinden zaten bağlantı talebinde bulundunuz! @@ -7387,10 +8173,12 @@ Bağlantı isteği tekrarlansın mı? You may migrate the exported database. + Dışa aktarılan veritabanını taşıyabilirsiniz. No comment provided by engineer. You may save the exported archive. + Dışa aktarılan arşivi kaydedebilirsiniz. No comment provided by engineer. @@ -7400,6 +8188,7 @@ Bağlantı isteği tekrarlansın mı? You need to allow your contact to call to be able to call them. + Kendiniz arayabilmeniz için önce irtibat kişinizin sizi aramasına izin vermelisiniz. No comment provided by engineer. @@ -7452,6 +8241,10 @@ Bağlantı isteği tekrarlansın mı? 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 chat. Chat history will be preserved. + 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. @@ -7472,11 +8265,6 @@ Bağlantı isteği tekrarlansın mı? 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 ICE servers ICE sunucularınız @@ -7492,11 +8280,6 @@ Bağlantı isteği tekrarlansın mı? SimpleX adresin No comment provided by engineer. - - Your XFTP servers - XFTP sunucularınız - No comment provided by engineer. - Your calls Aramaların @@ -7512,11 +8295,21 @@ Bağlantı isteği tekrarlansın mı? Sohbet veritabanınız şifrelenmemiş - şifrelemek için parola ayarlayın. No comment provided by engineer. + + Your chat preferences + Sohbet tercihleriniz + alert title + Your chat profiles Sohbet profillerin No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Bağlantınız %@ adresine taşındı ancak sizi profile yönlendirirken beklenmedik bir hata oluştu. + 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. @@ -7532,6 +8325,11 @@ Bağlantı isteği tekrarlansın mı? Kişileriniz bağlı kalacaktır. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Kimlik bilgileriniz şifrelenmeden gönderilebilir. + 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. @@ -7562,13 +8360,16 @@ Bağlantı isteği tekrarlansın mı? Profiliniz **%@** paylaşılacaktır. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. -SimpleX sunucuları profilinizi göremez. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Profiliniz cihazınızda saklanır ve sadece kişilerinizle paylaşılır. SimpleX sunucuları profilinizi göremez. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Profiliniz değiştirildi. Kaydederseniz, güncellenmiş profil tüm kişilerinize gönderilecektir. + alert message + Your profile, contacts and delivered messages are stored on your device. Profiliniz, kişileriniz ve gönderilmiş mesajlar cihazınızda saklanır. @@ -7579,16 +8380,15 @@ SimpleX sunucuları profilinizi göremez. 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 servers + No comment provided by engineer. + Your settings Ayarlarınız @@ -7629,6 +8429,10 @@ SimpleX sunucuları profilinizi göremez. kabul edilen arama call status + + accepted invitation + chat list item title + admin yönetici @@ -7666,6 +8470,7 @@ SimpleX sunucuları profilinizi göremez. attempts + denemeler No comment provided by engineer. @@ -7710,6 +8515,7 @@ SimpleX sunucuları profilinizi göremez. call + Ara No comment provided by engineer. @@ -7815,7 +8621,7 @@ SimpleX sunucuları profilinizi göremez. connecting… bağlanılıyor… - chat list item title + No comment provided by engineer. connection established @@ -7864,6 +8670,7 @@ SimpleX sunucuları profilinizi göremez. decryption errors + Şifre çözme hataları No comment provided by engineer. @@ -7918,6 +8725,7 @@ SimpleX sunucuları profilinizi göremez. duplicates + Kopyalar No comment provided by engineer. @@ -8002,6 +8810,11 @@ SimpleX sunucuları profilinizi göremez. expired + Süresi dolmuş + No comment provided by engineer. + + + for better metadata privacy. No comment provided by engineer. @@ -8036,6 +8849,7 @@ SimpleX sunucuları profilinizi göremez. inactive + inaktif No comment provided by engineer. @@ -8080,6 +8894,7 @@ SimpleX sunucuları profilinizi göremez. invite + davet No comment provided by engineer. @@ -8139,6 +8954,7 @@ SimpleX sunucuları profilinizi göremez. message + mesaj No comment provided by engineer. @@ -8173,6 +8989,7 @@ SimpleX sunucuları profilinizi göremez. mute + Sessiz No comment provided by engineer. @@ -8229,10 +9046,12 @@ SimpleX sunucuları profilinizi göremez. other + diğer No comment provided by engineer. other errors + diğer hatalar No comment provided by engineer. @@ -8295,6 +9114,10 @@ SimpleX sunucuları profilinizi göremez. sen kaldırıldın rcv group event chat item + + requested to connect + chat list item title + saved kaydedildi @@ -8307,6 +9130,7 @@ SimpleX sunucuları profilinizi göremez. search + ara No comment provided by engineer. @@ -8395,6 +9219,7 @@ son alınan msj: %2$@ unmute + susturmayı kaldır No comment provided by engineer. @@ -8444,6 +9269,7 @@ son alınan msj: %2$@ video + video No comment provided by engineer. @@ -8617,6 +9443,33 @@ son alınan msj: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
@@ -8624,14 +9477,17 @@ son alınan msj: %2$@ SimpleX SE + SimpleX SE Bundle display name SimpleX SE + SimpleX SE Bundle name Copyright © 2024 SimpleX Chat. All rights reserved. + Telif Hakkı © 2024 SimpleX Chat. Tüm hakları saklıdır. Copyright (human-readable) @@ -8643,150 +9499,187 @@ son alınan msj: %2$@ %@ + %@ No comment provided by engineer. App is locked! + Uygulama kilitlendi! No comment provided by engineer. Cancel + İptal et No comment provided by engineer. Cannot access keychain to save database password + Veritabanı şifresini kaydetmek için Anahtar Zinciri'ne erişilemiyor No comment provided by engineer. Cannot forward message + Mesaj iletilemiyor No comment provided by engineer. Comment + Yorum No comment provided by engineer. Currently maximum supported file size is %@. + Şu anki maksimum desteklenen dosya boyutu %@ kadardır. No comment provided by engineer. Database downgrade required + Veritabanı sürüm düşürme gerekli No comment provided by engineer. Database encrypted! + Veritabanı şifrelendi! No comment provided by engineer. Database error + Veritabanı hatası No comment provided by engineer. Database passphrase is different from saved in the keychain. + Veritabanı parolası Anahtar Zinciri'nde kayıtlı olandan farklıdır. No comment provided by engineer. Database passphrase is required to open chat. + Konuşmayı açmak için veri tabanı parolası gerekli. No comment provided by engineer. Database upgrade required + Veritabanı yükseltmesi gerekli No comment provided by engineer. Error preparing file + Dosya hazırlanırken hata oluştu No comment provided by engineer. Error preparing message + Mesaj hazırlanırken hata oluştu No comment provided by engineer. Error: %@ + Hata: %@ No comment provided by engineer. File error + Dosya hatası No comment provided by engineer. Incompatible database version + Uyumsuz veritabanı sürümü No comment provided by engineer. Invalid migration confirmation + Geçerli olmayan taşıma onayı No comment provided by engineer. Keychain error + Anahtarlık hatası No comment provided by engineer. Large file! + Büyük dosya! No comment provided by engineer. No active profile + Aktif profil yok No comment provided by engineer. Ok + Tamam No comment provided by engineer. Open the app to downgrade the database. + Veritabanının sürümünü düşürmek için uygulamayı açın. No comment provided by engineer. Open the app to upgrade the database. + Veritabanını güncellemek için uygulamayı açın. No comment provided by engineer. Passphrase + Parola No comment provided by engineer. Please create a profile in the SimpleX app + Lütfen SimpleX uygulamasında bir profil oluşturun No comment provided by engineer. Selected chat preferences prohibit this message. + Seçilen sohbet tercihleri bu mesajı yasakladı. No comment provided by engineer. Sending a message takes longer than expected. + Mesaj göndermek beklenenden daha uzun sürüyor. No comment provided by engineer. Sending message… + Mesaj gönderiliyor… No comment provided by engineer. Share + Paylaş No comment provided by engineer. Slow network? + Ağ yavaş mı? No comment provided by engineer. Unknown database error: %@ + Bilinmeyen veritabanı hatası: %@ No comment provided by engineer. Unsupported format + Desteklenmeyen format No comment provided by engineer. Wait + Bekleyin No comment provided by engineer. Wrong database passphrase + Yanlış veritabanı parolası No comment provided by engineer. You can allow sharing in Privacy & Security / SimpleX Lock settings. + Gizlilik ve Güvenlik / SimpleX Lock ayarlarından paylaşıma izin verebilirsiniz. No comment provided by engineer. 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 index cf485752ea..cb83427195 100644 --- 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 @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 ee06975768..d7dcc58dcd 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -127,6 +112,16 @@ %@ перевірено No comment provided by engineer. + + %@ server + %@ сервер + No comment provided by engineer. + + + %@ servers + %@ сервери + No comment provided by engineer. + %@ uploaded %@ завантажено @@ -137,6 +132,11 @@ %@ хоче підключитися! notification title + + %1$@, %2$@ + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ та %lld учасників @@ -157,11 +157,36 @@ %d днів time interval + + %d file(s) are still being downloaded. + %их файл(ів) ще досі завантажуються. + forward confirmation reason + + + %d file(s) failed to download. + %их файлів не вийшло завантажити. + forward confirmation reason + + + %d file(s) were deleted. + %их файл(ів) було видалено. + forward confirmation reason + + + %d file(s) were not downloaded. + %d файл(и) не було завантажено. + forward confirmation reason + %d hours %d годин time interval + + %d messages not forwarded + %d повідомлень не переслано + alert title + %d min %d хв @@ -322,14 +347,9 @@ ) 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 or link for your contact. - **Додати новий контакт**: щоб створити одноразовий QR-код або посилання для свого контакту. + + **Create 1-time link**: to create and share a new invitation link. + **Додати контакт**: створити нове посилання-запрошення. No comment provided by engineer. @@ -337,13 +357,13 @@ **Створити групу**: створити нову групу. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **Більш приватний**: перевіряти нові повідомлення кожні 20 хвилин. Серверу SimpleX Chat передається токен пристрою, але не кількість контактів або повідомлень, які ви маєте. 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **Найбільш приватний**: не використовуйте сервер сповіщень SimpleX Chat, періодично перевіряйте повідомлення у фоновому режимі (залежить від того, як часто ви користуєтесь додатком). No comment provided by engineer. @@ -357,11 +377,16 @@ **Зверніть увагу: ви НЕ зможете відновити або змінити пароль, якщо втратите його. 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **Рекомендується**: токен пристрою та сповіщення надсилаються на сервер сповіщень SimpleX Chat, але не вміст повідомлення, його розмір або від кого воно надійшло. No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + **Відсканувати / Вставити посилання**: підключитися за отриманим посиланням. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **Попередження**: Для отримання миттєвих пуш-сповіщень потрібна парольна фраза, збережена у брелоку. @@ -468,6 +493,16 @@ 1 тиждень time interval + + 1-time link + Одноразове посилання + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + Одноразове посилання можна використовувати *тільки з одним контактом* - поділіться ним особисто або через будь-який месенджер. + No comment provided by engineer. + 5 minutes 5 хвилин @@ -537,23 +572,18 @@ Скасувати зміну адреси? No comment provided by engineer. - - About SimpleX - Про SimpleX - No comment provided by engineer. - About SimpleX Chat Про чат SimpleX No comment provided by engineer. - - About SimpleX address - Про адресу SimpleX + + About operators No comment provided by engineer. Accent + Акцент No comment provided by engineer. @@ -563,6 +593,11 @@ accept incoming call via notification swipe action + + Accept conditions + Прийняти умови + No comment provided by engineer. + Accept connection request? Прийняти запит на підключення? @@ -579,16 +614,24 @@ accept contact request via notification swipe action + + Accepted conditions + Прийняті умови + No comment provided by engineer. + Acknowledged + Визнано No comment provided by engineer. Acknowledgement errors + Помилки підтвердження No comment provided by engineer. Active connections + Активні з'єднання No comment provided by engineer. @@ -596,14 +639,8 @@ Додайте адресу до свого профілю, щоб ваші контакти могли поділитися нею з іншими людьми. Повідомлення про оновлення профілю буде надіслано вашим контактам. No comment provided by engineer. - - Add contact - Додати контакт - No comment provided by engineer. - - - Add preset servers - Додавання попередньо встановлених серверів + + Add friends No comment provided by engineer. @@ -621,6 +658,10 @@ Додайте сервери, відсканувавши QR-код. No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device Додати до іншого пристрою @@ -631,16 +672,33 @@ Додати вітальне повідомлення No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + Додано медіа та файлові сервери + No comment provided by engineer. + + + Added message servers + Додано сервери повідомлень + No comment provided by engineer. + Additional accent + Додатковий акцент No comment provided by engineer. Additional accent 2 + Додатковий акцент 2 No comment provided by engineer. Additional secondary + Додаткова вторинна No comment provided by engineer. @@ -653,6 +711,16 @@ Зміна адреси буде скасована. Буде використано стару адресу отримання. No comment provided by engineer. + + Address or 1-time link? + Адреса чи одноразове посилання? + No comment provided by engineer. + + + Address settings + Налаштування адреси + No comment provided by engineer. + Admins can block a member for all. Адміністратори можуть заблокувати користувача для всіх. @@ -670,6 +738,7 @@ Advanced settings + Додаткові налаштування No comment provided by engineer. @@ -687,8 +756,9 @@ Всі дані стираються при введенні. No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. + Всі дані є приватними для вашого пристрою. No comment provided by engineer. @@ -696,6 +766,11 @@ Всі учасники групи залишаться на зв'язку. No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + Всі повідомлення та файли надсилаються **наскрізним шифруванням**, з пост-квантовим захистом у прямих повідомленнях. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! Усі повідомлення будуть видалені - цю дію не можна скасувати! @@ -713,7 +788,8 @@ All profiles - No comment provided by engineer. + Всі профілі + profile dropdown All your contacts will remain connected. @@ -742,6 +818,7 @@ Allow calls? + Дозволити дзвінки? No comment provided by engineer. @@ -781,6 +858,7 @@ Allow sharing + Дозволити спільний доступ No comment provided by engineer. @@ -873,6 +951,11 @@ Відповісти на дзвінок No comment provided by engineer. + + Anybody can host servers. + Кожен може хостити сервери. + No comment provided by engineer. + App build: %@ Збірка програми: %@ @@ -903,6 +986,11 @@ Пароль програми замінено на пароль самознищення. No comment provided by engineer. + + App session + Сесія програми + No comment provided by engineer. + App version Версія програми @@ -925,6 +1013,7 @@ Apply to + Звертатися до No comment provided by engineer. @@ -934,10 +1023,12 @@ Archive contacts to chat later. + Архівуйте контакти, щоб поспілкуватися пізніше. No comment provided by engineer. Archived contacts + Архівні контакти No comment provided by engineer. @@ -1005,6 +1096,11 @@ Автоматичне прийняття зображень No comment provided by engineer. + + Auto-accept settings + Автоприйняття налаштувань + alert title + Back Назад @@ -1012,6 +1108,7 @@ Background + Фон No comment provided by engineer. @@ -1029,11 +1126,21 @@ Поганий хеш повідомлення No comment provided by engineer. + + Better calls + Кращі дзвінки + No comment provided by engineer. + Better groups Кращі групи No comment provided by engineer. + + Better message dates. + Кращі дати повідомлень. + No comment provided by engineer. + Better messages Кращі повідомлення @@ -1041,10 +1148,27 @@ Better networking + Краща мережа + No comment provided by engineer. + + + Better notifications + Кращі сповіщення + No comment provided by engineer. + + + Better security ✅ + Краща безпека ✅ + No comment provided by engineer. + + + Better user experience + Покращений користувацький досвід No comment provided by engineer. Black + Чорний No comment provided by engineer. @@ -1084,10 +1208,12 @@ Blur for better privacy. + Розмиття для кращої приватності. No comment provided by engineer. Blur media + Розмиття медіа No comment provided by engineer. @@ -1120,6 +1246,14 @@ Болгарською, фінською, тайською та українською мовами - завдяки користувачам та [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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). @@ -1137,6 +1271,7 @@ Calls prohibited! + Дзвінки заборонені! No comment provided by engineer. @@ -1146,10 +1281,12 @@ Can't call contact + Не вдається додзвонитися до контакту No comment provided by engineer. Can't call member + Не вдається зателефонувати користувачеві No comment provided by engineer. @@ -1164,12 +1301,14 @@ Can't message member + Не можу надіслати повідомлення користувачеві No comment provided by engineer. Cancel Скасувати - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1183,12 +1322,13 @@ Cannot forward message + Неможливо переслати повідомлення No comment provided by engineer. Cannot receive file Не вдається отримати файл - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. @@ -1205,6 +1345,11 @@ Зміна No comment provided by engineer. + + Change chat profiles + Зміна профілів користувачів + authentication reason + Change database passphrase? Змінити пароль до бази даних? @@ -1251,13 +1396,21 @@ authentication reason set passcode view - - Chat archive - Архів чату + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. Chat colors + Кольори чату No comment provided by engineer. @@ -1277,6 +1430,7 @@ Chat database exported + Експортовано базу даних чату No comment provided by engineer. @@ -1301,6 +1455,7 @@ Chat list + Список чатів No comment provided by engineer. @@ -1313,8 +1468,27 @@ Налаштування чату No comment provided by engineer. + + Chat preferences were changed. + Змінено налаштування чату. + alert message + + + Chat profile + Профіль користувача + No comment provided by engineer. + Chat theme + Тема чату + No comment provided by engineer. + + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! No comment provided by engineer. @@ -1322,10 +1496,20 @@ Чати No comment provided by engineer. + + Check messages every 20 min. + Перевіряйте повідомлення кожні 20 хв. + No comment provided by engineer. + + + Check messages when allowed. + Перевірте повідомлення, коли це дозволено. + No comment provided by engineer. + Check server address and try again. Перевірте адресу сервера та спробуйте ще раз. - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1349,14 +1533,17 @@ Chunks deleted + Фрагменти видалено No comment provided by engineer. Chunks downloaded + Завантажено фрагменти No comment provided by engineer. Chunks uploaded + Завантажено фрагменти No comment provided by engineer. @@ -1386,10 +1573,12 @@ Color chats with the new themes. + Кольорові чати з новими темами. No comment provided by engineer. Color mode + Колірний режим No comment provided by engineer. @@ -1404,6 +1593,52 @@ Completed + Завершено + No comment provided by engineer. + + + Conditions accepted on: %@. + Умови приймаються на: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + Для оператора(ів) приймаються умови: **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + Умови вже прийняті для наступних операторів: **%@**. + No comment provided by engineer. + + + Conditions of use + Умови використання + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + Умови будуть прийняті для ввімкнених операторів через 30 днів. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + Умови приймаються для оператора(ів): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + Для оператора(ів) приймаються умови: **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + Умови приймаються на: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. + Умови будуть автоматично прийняті для увімкнених операторів на: %@. No comment provided by engineer. @@ -1411,10 +1646,6 @@ Налаштування серверів ICE No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm Підтвердити @@ -1427,6 +1658,7 @@ Confirm contact deletion? + Підтвердити видалення контакту? No comment provided by engineer. @@ -1486,6 +1718,7 @@ Connect to your friends faster. + Швидше спілкуйтеся з друзями. No comment provided by engineer. @@ -1529,6 +1762,7 @@ This is your own one-time link! Connected + Підключено No comment provided by engineer. @@ -1538,6 +1772,7 @@ This is your own one-time link! Connected servers + Підключені сервери No comment provided by engineer. @@ -1547,6 +1782,7 @@ This is your own one-time link! Connecting + Підключення No comment provided by engineer. @@ -1561,6 +1797,7 @@ This is your own one-time link! Connecting to contact, please wait or check later! + З'єднання з контактом, будь ласка, зачекайте або перевірте пізніше! No comment provided by engineer. @@ -1575,6 +1812,7 @@ This is your own one-time link! Connection and servers status. + Стан з'єднання та серверів. No comment provided by engineer. @@ -1589,6 +1827,7 @@ This is your own one-time link! Connection notifications + Сповіщення про підключення No comment provided by engineer. @@ -1596,6 +1835,11 @@ This is your own one-time link! Запит на підключення відправлено! No comment provided by engineer. + + Connection security + Безпека з'єднання + No comment provided by engineer. + Connection terminated З'єднання розірвано @@ -1608,10 +1852,12 @@ This is your own one-time link! Connection with desktop stopped + Припинено зв'язок з робочим столом No comment provided by engineer. Connections + З'єднання No comment provided by engineer. @@ -1626,6 +1872,7 @@ This is your own one-time link! Contact deleted! + Контакт видалено! No comment provided by engineer. @@ -1640,6 +1887,7 @@ This is your own one-time link! Contact is deleted. + Контакт видалено. No comment provided by engineer. @@ -1654,6 +1902,7 @@ This is your own one-time link! Contact will be deleted - this cannot be undone! + Контакт буде видалено - це неможливо скасувати! No comment provided by engineer. @@ -1673,6 +1922,7 @@ This is your own one-time link! Conversation deleted! + Розмова видалена! No comment provided by engineer. @@ -1682,6 +1932,7 @@ This is your own one-time link! Copy error + Помилка копіювання No comment provided by engineer. @@ -1689,6 +1940,11 @@ This is your own one-time link! Основна версія: v%@ No comment provided by engineer. + + Corner + Кут + No comment provided by engineer. + Correct name to %@? Виправити ім'я на %@? @@ -1699,6 +1955,11 @@ This is your own one-time link! Створити No comment provided by engineer. + + Create 1-time link + Створити одноразове посилання + No comment provided by engineer. + Create SimpleX address Створіть адресу SimpleX @@ -1709,11 +1970,6 @@ This is your own one-time link! Створіть групу, використовуючи випадковий профіль. No comment provided by engineer. - - Create an address to let people connect with you. - Створіть адресу, щоб люди могли з вами зв'язатися. - No comment provided by engineer. - Create file Створити файл @@ -1761,6 +2017,7 @@ This is your own one-time link! Created + Створено No comment provided by engineer. @@ -1773,11 +2030,6 @@ This is your own one-time link! Створено за адресою: %@ copied message info - - Created on %@ - Створено %@ - No comment provided by engineer. - Creating archive link Створення архівного посилання @@ -1793,6 +2045,11 @@ This is your own one-time link! Поточний пароль No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + Текст поточних умов не вдалося завантажити, ви можете переглянути умови за цим посиланням: + No comment provided by engineer. + Current passphrase… Поточна парольна фраза… @@ -1800,6 +2057,7 @@ This is your own one-time link! Current profile + Поточний профіль No comment provided by engineer. @@ -1812,8 +2070,14 @@ This is your own one-time link! Індивідуальний час No comment provided by engineer. + + Customizable message shape. + Налаштовується форма повідомлення. + No comment provided by engineer. + Customize theme + Налаштувати тему No comment provided by engineer. @@ -1823,6 +2087,7 @@ This is your own one-time link! Dark mode colors + Кольори темного режиму No comment provided by engineer. @@ -1941,11 +2206,13 @@ This is your own one-time link! Delete Видалити - chat item action + alert action + chat item action swipe action Delete %lld messages of members? + Видалити %lld повідомлень користувачів? No comment provided by engineer. @@ -1978,14 +2245,8 @@ This is your own one-time link! Видалити та повідомити контакт No comment provided by engineer. - - Delete archive - Видалити архів - No comment provided by engineer. - - - Delete chat archive? - Видалити архів чату? + + Delete chat No comment provided by engineer. @@ -1998,6 +2259,10 @@ This is your own one-time link! Видалити профіль чату? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection Видалити підключення @@ -2010,6 +2275,7 @@ This is your own one-time link! Delete contact? + Видалити контакт? No comment provided by engineer. @@ -2102,6 +2368,11 @@ This is your own one-time link! Видалити стару базу даних? No comment provided by engineer. + + Delete or moderate up to 200 messages. + Видалити або модерувати до 200 повідомлень. + No comment provided by engineer. + Delete pending connection? Видалити очікуване з'єднання? @@ -2119,6 +2390,7 @@ This is your own one-time link! Delete up to 20 messages at once. + Видаляйте до 20 повідомлень одночасно. No comment provided by engineer. @@ -2128,10 +2400,12 @@ This is your own one-time link! Delete without notification + Видалення без попередження No comment provided by engineer. Deleted + Видалено No comment provided by engineer. @@ -2146,6 +2420,12 @@ This is your own one-time link! Deletion errors + Помилки видалення + No comment provided by engineer. + + + Delivered even when Apple drops them. + Доставляються навіть тоді, коли Apple кидає їх. No comment provided by engineer. @@ -2185,6 +2465,7 @@ This is your own one-time link! Destination server address of %@ is incompatible with forwarding server %@ settings. + Адреса сервера призначення %@ несумісна з налаштуваннями сервера пересилання %@. No comment provided by engineer. @@ -2194,14 +2475,17 @@ This is your own one-time link! Destination server version of %@ is incompatible with forwarding server %@. + Версія сервера призначення %@ несумісна з версією сервера переадресації %@. No comment provided by engineer. Detailed statistics + Детальна статистика No comment provided by engineer. Details + Деталі No comment provided by engineer. @@ -2211,6 +2495,7 @@ This is your own one-time link! Developer options + Можливості для розробників No comment provided by engineer. @@ -2243,8 +2528,12 @@ This is your own one-time link! Прямі повідомлення chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. У цій групі заборонені прямі повідомлення між учасниками. No comment provided by engineer. @@ -2265,6 +2554,7 @@ This is your own one-time link! Disabled + Вимкнено No comment provided by engineer. @@ -2282,8 +2572,8 @@ This is your own one-time link! Зникаючі повідомлення в цьому чаті заборонені. No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. У цій групі заборонено зникаючі повідомлення. No comment provided by engineer. @@ -2342,6 +2632,11 @@ This is your own one-time link! Не надсилайте історію новим користувачам. No comment provided by engineer. + + Do not use credentials with proxy. + Не використовуйте облікові дані з проксі. + No comment provided by engineer. + Don't create address Не створювати адресу @@ -2365,10 +2660,12 @@ This is your own one-time link! Download Завантажити - chat item action + alert button + chat item action Download errors + Помилки завантаження No comment provided by engineer. @@ -2381,12 +2678,19 @@ This is your own one-time link! Завантажити файл server test step + + Download files + Завантажити файли + alert action + Downloaded + Завантажено No comment provided by engineer. Downloaded files + Завантажені файли No comment provided by engineer. @@ -2409,6 +2713,11 @@ This is your own one-time link! Тривалість No comment provided by engineer. + + E2E encrypted notifications. + Зашифровані сповіщення E2E. + No comment provided by engineer. + Edit Редагувати @@ -2429,6 +2738,11 @@ This is your own one-time link! Увімкнути (зберегти перевизначення) No comment provided by engineer. + + Enable Flux + Увімкнути Flux + No comment provided by engineer. + Enable SimpleX Lock Увімкнути SimpleX Lock @@ -2491,6 +2805,7 @@ This is your own one-time link! Enabled + Увімкнено No comment provided by engineer. @@ -2633,26 +2948,36 @@ This is your own one-time link! Помилка скасування зміни адреси No comment provided by engineer. + + Error accepting conditions + Помилка прийняття умов + alert title + Error accepting contact request Помилка при прийнятті запиту на контакт No comment provided by engineer. - - Error accessing database file - Помилка доступу до файлу бази даних - No comment provided by engineer. - Error adding member(s) Помилка додавання користувача(ів) No comment provided by engineer. + + Error adding server + Помилка додавання сервера + alert title + Error changing address Помилка зміни адреси No comment provided by engineer. + + Error changing connection profile + Помилка при зміні профілю з'єднання + No comment provided by engineer. + Error changing role Помилка зміни ролі @@ -2663,8 +2988,14 @@ This is your own one-time link! Помилка зміни налаштування No comment provided by engineer. + + Error changing to incognito! + Помилка переходу на інкогніто! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. + Помилка підключення до сервера переадресації %@. Спробуйте пізніше. No comment provided by engineer. @@ -2764,6 +3095,7 @@ This is your own one-time link! Error exporting theme: %@ + Помилка експорту теми: %@ No comment provided by engineer. @@ -2776,9 +3108,14 @@ This is your own one-time link! Помилка приєднання до групи No comment provided by engineer. - - Error loading %@ servers - Помилка завантаження %@ серверів + + Error loading servers + Помилка завантаження серверів + alert title + + + Error migrating settings + Помилка міграції налаштувань No comment provided by engineer. @@ -2789,14 +3126,16 @@ This is your own one-time link! Error receiving file Помилка отримання файлу - No comment provided by engineer. + alert title Error reconnecting server + Помилка перепідключення сервера No comment provided by engineer. Error reconnecting servers + Помилка перепідключення серверів No comment provided by engineer. @@ -2806,11 +3145,7 @@ This is your own one-time link! Error resetting statistics - No comment provided by engineer. - - - Error saving %@ servers - Помилка збереження %@ серверів + Статистика скидання помилок No comment provided by engineer. @@ -2833,6 +3168,11 @@ This is your own one-time link! Помилка збереження пароля на keychain No comment provided by engineer. + + Error saving servers + Сервери збереження помилок + alert title + Error saving settings Налаштування збереження помилок @@ -2878,10 +3218,15 @@ This is your own one-time link! Помилка зупинки чату No comment provided by engineer. + + Error switching profile + Помилка перемикання профілю + No comment provided by engineer. + Error switching profile! Помилка перемикання профілю! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2898,6 +3243,11 @@ This is your own one-time link! Повідомлення про помилку оновлення No comment provided by engineer. + + Error updating server + Помилка оновлення сервера + alert title + Error updating settings Помилка оновлення налаштувань @@ -2926,8 +3276,7 @@ This is your own one-time link! Error: %@ Помилка: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2941,8 +3290,14 @@ This is your own one-time link! Errors + Помилки No comment provided by engineer. + + Errors in servers configuration. + Помилки в конфігурації серверів. + servers error + Even when disabled in the conversation. Навіть коли вимкнений у розмові. @@ -2970,6 +3325,7 @@ This is your own one-time link! Export theme + Тема експорту No comment provided by engineer. @@ -3009,22 +3365,34 @@ This is your own one-time link! File error + Помилка файлу No comment provided by engineer. + + File errors: +%@ + Помилки файлів: +%@ + alert message + File not found - most likely file was deleted or cancelled. + Файл не знайдено - найімовірніше, файл було видалено або скасовано. file error text File server error: %@ + Помилка файлового сервера: %@ file error text File status + Статус файлу No comment provided by engineer. File status: %@ + Статус файлу: %@ copied message info @@ -3062,8 +3430,8 @@ This is your own one-time link! Файли і медіа chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. Файли та медіа в цій групі заборонені. No comment provided by engineer. @@ -3132,21 +3500,61 @@ This is your own one-time link! Виправлення не підтримується учасником групи No comment provided by engineer. + + For chat profile %@: + Для профілю чату %@: + servers error + For console Для консолі No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + Наприклад, якщо ваш контакт отримує повідомлення через сервер SimpleX Chat, ваш додаток доставлятиме їх через сервер Flux. + No comment provided by engineer. + + + For private routing + Для приватної маршрутизації + No comment provided by engineer. + + + For social media + Для соціальних мереж + No comment provided by engineer. + Forward Пересилання chat item action + + Forward %d message(s)? + Переслати %d повідомлення(ь)? + alert title + Forward and save messages Пересилання та збереження повідомлень No comment provided by engineer. + + Forward messages + Пересилання повідомлень + alert action + + + Forward messages without files? + Пересилати повідомлення без файлів? + alert message + + + Forward up to 20 messages at once. + Пересилайте до 20 повідомлень одночасно. + No comment provided by engineer. + Forwarded Переслано @@ -3157,16 +3565,24 @@ This is your own one-time link! Переслано з No comment provided by engineer. + + Forwarding %lld messages + Пересилання повідомлень %lld + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. + Серверу переадресації %@ не вдалося з'єднатися з сервером призначення %@. Спробуйте пізніше. No comment provided by engineer. Forwarding server address is incompatible with network settings: %@. + Адреса сервера переадресації несумісна з налаштуваннями мережі: %@. No comment provided by engineer. Forwarding server version is incompatible with network settings: %@. + Версія сервера переадресації несумісна з мережевими налаштуваннями: %@. No comment provided by engineer. @@ -3203,11 +3619,6 @@ Error: %2$@ Повне ім'я (необов'язково) No comment provided by engineer. - - Full name: - Повне ім'я: - No comment provided by engineer. - Fully decentralized – visible only to members. Повністю децентралізована - видима лише для учасників. @@ -3230,10 +3641,12 @@ Error: %2$@ Good afternoon! + Доброго дня! message preview Good morning! + Доброго ранку! message preview @@ -3291,41 +3704,6 @@ Error: %2$@ Групові посилання No comment provided by engineer. - - Group members can add message reactions. - Учасники групи можуть додавати реакції на повідомлення. - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - Учасники групи можуть безповоротно видаляти надіслані повідомлення. (24 години) - No comment provided by engineer. - - - Group members can send SimpleX links. - Учасники групи можуть надсилати посилання SimpleX. - No comment provided by engineer. - - - Group members can send direct messages. - Учасники групи можуть надсилати прямі повідомлення. - No comment provided by engineer. - - - Group members can send disappearing messages. - Учасники групи можуть надсилати зникаючі повідомлення. - No comment provided by engineer. - - - Group members can send files and media. - Учасники групи можуть надсилати файли та медіа. - No comment provided by engineer. - - - Group members can send voice messages. - Учасники групи можуть надсилати голосові повідомлення. - No comment provided by engineer. - Group message: Групове повідомлення: @@ -3421,9 +3799,14 @@ Error: %2$@ Як працює SimpleX No comment provided by engineer. - - How it works - Як це працює + + How it affects privacy + Як це впливає на конфіденційність + No comment provided by engineer. + + + How it helps privacy + Як це захищає приватність No comment provided by engineer. @@ -3451,6 +3834,11 @@ Error: %2$@ Сервери ICE (по одному на лінію) No comment provided by engineer. + + IP address + IP-адреса + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. Якщо ви не можете зустрітися особисто, покажіть QR-код у відеодзвінку або поділіться посиланням. @@ -3491,8 +3879,8 @@ Error: %2$@ Негайно No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam Імунітет до спаму та зловживань No comment provided by engineer. @@ -3518,6 +3906,7 @@ Error: %2$@ Import theme + Імпорт теми No comment provided by engineer. @@ -3525,6 +3914,13 @@ Error: %2$@ Імпорт архіву No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + Покращена доставка, зменшене використання трафіку. +Незабаром з'являться нові покращення! + No comment provided by engineer. + Improved message delivery Покращена доставка повідомлень @@ -3625,6 +4021,11 @@ Error: %2$@ Встановіть [SimpleX Chat для терміналу](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + Миттєво + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3632,11 +4033,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - Миттєво - No comment provided by engineer. - Interface Інтерфейс @@ -3644,6 +4040,7 @@ Error: %2$@ Interface colors + Кольори інтерфейсу No comment provided by engineer. @@ -3684,7 +4081,7 @@ Error: %2$@ Invalid server address! Неправильна адреса сервера! - No comment provided by engineer. + alert title Invalid status @@ -3706,6 +4103,10 @@ Error: %2$@ Запросити учасників No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group Запросити до групи @@ -3721,8 +4122,8 @@ Error: %2$@ У цьому чаті заборонено безповоротне видалення повідомлень. No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. У цій групі заборонено безповоротне видалення повідомлень. No comment provided by engineer. @@ -3749,6 +4150,7 @@ Error: %2$@ It protects your IP address and connections. + Він захищає вашу IP-адресу та з'єднання. No comment provided by engineer. @@ -3811,10 +4213,11 @@ This is your link for group %@! Keep Тримай - No comment provided by engineer. + alert action Keep conversation + Підтримуйте розмову No comment provided by engineer. @@ -3825,7 +4228,7 @@ This is your link for group %@! Keep unused invitation? Зберігати невикористані запрошення? - No comment provided by engineer. + alert title Keep your connections @@ -3862,6 +4265,14 @@ This is your link for group %@! Залишити swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group Покинути групу @@ -3912,11 +4323,6 @@ This is your link for group %@! Живі повідомлення No comment provided by engineer. - - Local - Локально - No comment provided by engineer. - Local name Місцева назва @@ -3937,11 +4343,6 @@ This is your link for group %@! Режим блокування No comment provided by engineer. - - Make a private connection - Створіть приватне з'єднання - No comment provided by engineer. - Make one message disappear Зробити так, щоб одне повідомлення зникло @@ -3952,21 +4353,11 @@ This is your link for group %@! Зробіть профіль приватним! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - Переконайтеся, що адреси серверів %@ мають правильний формат, розділені рядками і не дублюються (%@). - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. Переконайтеся, що адреси серверів WebRTC ICE мають правильний формат, розділені рядками і не дублюються. No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - Багато людей запитували: *якщо SimpleX не має ідентифікаторів користувачів, як він може доставляти повідомлення?* - No comment provided by engineer. - Mark deleted for everyone Позначити видалено для всіх @@ -3994,10 +4385,12 @@ This is your link for group %@! Media & file servers + Медіа та файлові сервери No comment provided by engineer. Medium + Середній blur media @@ -4007,8 +4400,13 @@ This is your link for group %@! Member inactive + Користувач неактивний item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. Роль учасника буде змінено на "%@". Всі учасники групи будуть повідомлені про це. @@ -4019,13 +4417,53 @@ This is your link for group %@! Роль учасника буде змінено на "%@". Учасник отримає нове запрошення. No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! Учасник буде видалений з групи - це неможливо скасувати! No comment provided by engineer. + + Members can add message reactions. + Учасники групи можуть додавати реакції на повідомлення. + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + Учасники групи можуть безповоротно видаляти надіслані повідомлення. (24 години) + No comment provided by engineer. + + + Members can send SimpleX links. + Учасники групи можуть надсилати посилання SimpleX. + No comment provided by engineer. + + + Members can send direct messages. + Учасники групи можуть надсилати прямі повідомлення. + No comment provided by engineer. + + + Members can send disappearing messages. + Учасники групи можуть надсилати зникаючі повідомлення. + No comment provided by engineer. + + + Members can send files and media. + Учасники групи можуть надсилати файли та медіа. + No comment provided by engineer. + + + Members can send voice messages. + Учасники групи можуть надсилати голосові повідомлення. + No comment provided by engineer. + Menus + Меню No comment provided by engineer. @@ -4050,10 +4488,12 @@ This is your link for group %@! Message forwarded + Повідомлення переслано item status text Message may be delivered later if member becomes active. + Повідомлення може бути доставлене пізніше, якщо користувач стане активним. item status description @@ -4071,17 +4511,24 @@ This is your link for group %@! Реакції на повідомлення в цьому чаті заборонені. No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. Реакції на повідомлення в цій групі заборонені. No comment provided by engineer. Message reception + Прийом повідомлень No comment provided by engineer. Message servers + Сервери повідомлень + No comment provided by engineer. + + + Message shape + Форма повідомлення No comment provided by engineer. @@ -4091,10 +4538,12 @@ This is your link for group %@! Message status + Статус повідомлення No comment provided by engineer. Message status: %@ + Статус повідомлення: %@ copied message info @@ -4124,12 +4573,19 @@ This is your link for group %@! Messages received + Отримані повідомлення No comment provided by engineer. Messages sent + Надіслані повідомлення No comment provided by engineer. + + Messages were deleted after you selected them. + Повідомлення були видалені після того, як ви їх вибрали. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. Повідомлення, файли та дзвінки захищені **наскрізним шифруванням** з ідеальною секретністю переадресації, відмовою та відновленням після злому. @@ -4195,9 +4651,9 @@ This is your link for group %@! Міграцію завершено No comment provided by engineer. - - Migrations: %@ - Міграції: %@ + + Migrations: + Міграції: No comment provided by engineer. @@ -4225,6 +4681,11 @@ This is your link for group %@! Більш надійне з'єднання з мережею. No comment provided by engineer. + + More reliable notifications + Більш надійні сповіщення + No comment provided by engineer. + Most likely this connection is deleted. Швидше за все, це з'єднання видалено. @@ -4260,6 +4721,11 @@ This is your link for group %@! Підключення до мережі No comment provided by engineer. + + Network decentralization + Децентралізація мережі + No comment provided by engineer. + Network issues - message expired after many attempts to send it. Проблеми з мережею - термін дії повідомлення закінчився після багатьох спроб надіслати його. @@ -4270,6 +4736,11 @@ This is your link for group %@! Керування мережею No comment provided by engineer. + + Network operator + Мережевий оператор + No comment provided by engineer. + Network settings Налаштування мережі @@ -4285,6 +4756,16 @@ This is your link for group %@! Новий пароль No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + Нові облікові дані SOCKS будуть використовуватися при кожному запуску програми. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + Для кожного сервера будуть використовуватися нові облікові дані SOCKS. + No comment provided by engineer. + New chat Новий чат @@ -4292,6 +4773,7 @@ This is your link for group %@! New chat experience 🎉 + Новий досвід спілкування в чаті 🎉 No comment provided by engineer. @@ -4304,11 +4786,6 @@ This is your link for group %@! Новий контакт: notification - - New database archive - Новий архів бази даних - No comment provided by engineer. - New desktop app! Новий десктопний додаток! @@ -4319,6 +4796,11 @@ This is your link for group %@! Нове ім'я відображення No comment provided by engineer. + + New events + Нові події + notification + New in %@ Нове в %@ @@ -4326,6 +4808,7 @@ This is your link for group %@! New media options + Нові медіа-опції No comment provided by engineer. @@ -4343,6 +4826,11 @@ This is your link for group %@! Новий пароль… No comment provided by engineer. + + New server + Новий сервер + No comment provided by engineer. + No Ні @@ -4375,6 +4863,7 @@ This is your link for group %@! No direct connection yet, message is forwarded by admin. + Прямого зв'язку ще немає, повідомлення пересилається адміністратором. item status description @@ -4394,23 +4883,74 @@ This is your link for group %@! No info, try to reload + Немає інформації, спробуйте перезавантажити No comment provided by engineer. + + No media & file servers. + Ніяких медіа та файлових серверів. + servers error + + + No message servers. + Ніяких серверів повідомлень. + servers error + No network connection Немає підключення до мережі No comment provided by engineer. + + No permission to record speech + Немає дозволу на запис промови + No comment provided by engineer. + + + No permission to record video + Немає дозволу на запис відео + No comment provided by engineer. + No permission to record voice message Немає дозволу на запис голосового повідомлення No comment provided by engineer. + + No push server + Локально + No comment provided by engineer. + No received or sent files Немає отриманих або відправлених файлів No comment provided by engineer. + + No servers for private message routing. + Немає серверів для маршрутизації приватних повідомлень. + servers error + + + No servers to receive files. + Немає серверів для отримання файлів. + servers error + + + No servers to receive messages. + Немає серверів для отримання повідомлень. + servers error + + + No servers to send files. + Немає серверів для надсилання файлів. + servers error + + + No user identifiers. + Ніяких ідентифікаторів користувачів. + No comment provided by engineer. + Not compatible! Не сумісні! @@ -4418,8 +4958,14 @@ This is your link for group %@! Nothing selected + Нічого не вибрано No comment provided by engineer. + + Nothing to forward! + Нічого пересилати! + alert title + Notifications Сповіщення @@ -4430,6 +4976,11 @@ This is your link for group %@! Сповіщення вимкнено! No comment provided by engineer. + + Notifications privacy + Сповіщення про приватність + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4452,18 +5003,13 @@ This is your link for group %@! Ok Гаразд - No comment provided by engineer. + alert button Old database Стара база даних No comment provided by engineer. - - Old database archive - Старий архів бази даних - No comment provided by engineer. - One-time invitation link Посилання на одноразове запрошення @@ -4488,13 +5034,18 @@ Requires compatible VPN. Onion хости не будуть використовуватися. No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. Тільки клієнтські пристрої зберігають профілі користувачів, контакти, групи та повідомлення, надіслані за допомогою **2-шарового наскрізного шифрування**. No comment provided by engineer. Only delete conversation + Видаляйте тільки розмови No comment provided by engineer. @@ -4572,6 +5123,11 @@ Requires compatible VPN. Відкрийте Налаштування No comment provided by engineer. + + Open changes + Відкриті зміни + No comment provided by engineer. + Open chat Відкритий чат @@ -4582,6 +5138,11 @@ Requires compatible VPN. Відкрийте консоль чату authentication reason + + Open conditions + Відкриті умови + No comment provided by engineer. + Open group Відкрита група @@ -4592,25 +5153,25 @@ Requires compatible VPN. Відкрита міграція на інший пристрій authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - Відкрити профілі користувачів - authentication reason - - - Open-source protocol and code – anybody can run the servers. - Протокол і код з відкритим вихідним кодом - будь-хто може запускати сервери. - No comment provided by engineer. - Opening app… Відкриваємо програму… No comment provided by engineer. + + Operator + Оператор + No comment provided by engineer. + + + Operator server + Сервер оператора + alert title + + + Or import archive file + No comment provided by engineer. + Or paste archive link Або вставте посилання на архів @@ -4631,14 +5192,22 @@ Requires compatible VPN. Або покажіть цей код No comment provided by engineer. + + Or to share privately + Або поділитися приватно + No comment provided by engineer. + Other Інше No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + Інші помилки файлів: +%@ + alert message PING count @@ -4675,6 +5244,11 @@ Requires compatible VPN. Пароль встановлено! No comment provided by engineer. + + Password + Пароль + No comment provided by engineer. + Password to show Показати пароль @@ -4707,15 +5281,11 @@ Requires compatible VPN. Pending + В очікуванні No comment provided by engineer. - - People can connect to you only via the links you share. - Люди можуть зв'язатися з вами лише за посиланнями, якими ви ділитеся. - No comment provided by engineer. - - - Periodically + + Periodic Періодично No comment provided by engineer. @@ -4731,10 +5301,12 @@ Requires compatible VPN. Play from the chat list. + Грати зі списку чату. No comment provided by engineer. Please ask your contact to enable calls. + Будь ласка, попросіть свого контакту ввімкнути дзвінки. No comment provided by engineer. @@ -4745,6 +5317,8 @@ Requires compatible VPN. Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection. Please share any other issues with the developers. + Переконайтеся, що мобільний і настільний комп'ютери підключені до однієї локальної мережі, і що брандмауер настільного комп'ютера дозволяє з'єднання. +Будь ласка, повідомте про будь-які інші проблеми розробникам. No comment provided by engineer. @@ -4819,6 +5393,11 @@ Error: %@ Польський інтерфейс No comment provided by engineer. + + Port + Порт + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect Можливо, в адресі сервера неправильно вказано відбиток сертифіката @@ -4829,16 +5408,16 @@ Error: %@ Зберегти чернетку останнього повідомлення з вкладеннями. No comment provided by engineer. - - Preset server - Попередньо встановлений сервер - No comment provided by engineer. - Preset server address Попередньо встановлена адреса сервера No comment provided by engineer. + + Preset servers + Попередньо встановлені сервери + No comment provided by engineer. + Preview Попередній перегляд @@ -4846,6 +5425,7 @@ Error: %@ Previously connected servers + Раніше підключені сервери No comment provided by engineer. @@ -4853,6 +5433,10 @@ Error: %@ Конфіденційність і безпека No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined Конфіденційність переглянута @@ -4885,6 +5469,7 @@ Error: %@ Private routing error + Помилка приватної маршрутизації No comment provided by engineer. @@ -4902,16 +5487,6 @@ Error: %@ Зображення профілю No comment provided by engineer. - - Profile name - Назва профілю - No comment provided by engineer. - - - Profile name: - Ім'я профілю: - No comment provided by engineer. - Profile password Пароль до профілю @@ -4919,12 +5494,13 @@ Error: %@ Profile theme + Тема профілю No comment provided by engineer. Profile update will be sent to your contacts. Оновлення профілю буде надіслано вашим контактам. - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -5005,15 +5581,22 @@ Enable in *Network & servers* settings. Proxied + Проксі-сервер No comment provided by engineer. Proxied servers + Проксі-сервери + No comment provided by engineer. + + + Proxy requires password + Проксі вимагає пароль No comment provided by engineer. Push notifications - Push-повідомлення + Push-сповіщення No comment provided by engineer. @@ -5033,6 +5616,7 @@ Enable in *Network & servers* settings. Reachable chat toolbar + Доступна панель інструментів чату No comment provided by engineer. @@ -5050,26 +5634,21 @@ Enable in *Network & servers* settings. Читати далі 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). Читайте більше в [User Guide](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + Читайте більше в [Посібнику користувача](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 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). No comment provided by engineer. - - Read more in our GitHub repository. - Читайте більше в нашому репозиторії на GitHub. - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). Читайте більше в нашому [GitHub репозиторії](https://github.com/simplex-chat/simplex-chat#readme). @@ -5082,6 +5661,7 @@ Enable in *Network & servers* settings. Receive errors + Отримання помилок No comment provided by engineer. @@ -5106,14 +5686,17 @@ Enable in *Network & servers* settings. Received messages + Отримані повідомлення No comment provided by engineer. Received reply + Отримано відповідь No comment provided by engineer. Received total + Отримано всього No comment provided by engineer. @@ -5148,6 +5731,7 @@ Enable in *Network & servers* settings. Reconnect + Повторне підключення No comment provided by engineer. @@ -5157,18 +5741,22 @@ Enable in *Network & servers* settings. Reconnect all servers + Перепідключіть усі сервери No comment provided by engineer. Reconnect all servers? + Перепідключити всі сервери? No comment provided by engineer. Reconnect server to force message delivery. It uses additional traffic. + Перепідключити сервер для примусової доставки повідомлень. Використовує додатковий трафік. No comment provided by engineer. Reconnect server? + Перепідключити сервер? No comment provided by engineer. @@ -5222,8 +5810,14 @@ Enable in *Network & servers* settings. Видалити No comment provided by engineer. + + Remove archive? + Видалити архів? + No comment provided by engineer. + Remove image + Видалити зображення No comment provided by engineer. @@ -5298,14 +5892,17 @@ Enable in *Network & servers* settings. Reset all hints + Скинути всі підказки No comment provided by engineer. Reset all statistics + Скинути всю статистику No comment provided by engineer. Reset all statistics? + Скинути всю статистику? No comment provided by engineer. @@ -5315,6 +5912,7 @@ Enable in *Network & servers* settings. Reset to app theme + Повернутися до теми програми No comment provided by engineer. @@ -5324,6 +5922,7 @@ Enable in *Network & servers* settings. Reset to user theme + Повернутися до теми користувача No comment provided by engineer. @@ -5366,6 +5965,16 @@ Enable in *Network & servers* settings. Показувати chat item action + + Review conditions + Умови перегляду + No comment provided by engineer. + + + Review later + Перегляньте пізніше + No comment provided by engineer. + Revoke Відкликати @@ -5393,6 +6002,12 @@ Enable in *Network & servers* settings. SMP server + Сервер SMP + No comment provided by engineer. + + + SOCKS proxy + Проксі SOCKS No comment provided by engineer. @@ -5408,17 +6023,18 @@ Enable in *Network & servers* settings. Save Зберегти - chat item action + alert button + chat item action Save (and notify contacts) Зберегти (і повідомити контактам) - No comment provided by engineer. + alert button Save and notify contact Зберегти та повідомити контакт - No comment provided by engineer. + alert button Save and notify group members @@ -5427,6 +6043,7 @@ Enable in *Network & servers* settings. Save and reconnect + Збережіть і підключіться знову No comment provided by engineer. @@ -5434,16 +6051,6 @@ Enable in *Network & servers* settings. Збереження та оновлення профілю групи No comment provided by engineer. - - Save archive - Зберегти архів - No comment provided by engineer. - - - Save auto-accept settings - Зберегти налаштування автоприйому - No comment provided by engineer. - Save group profile Зберегти профіль групи @@ -5462,7 +6069,7 @@ Enable in *Network & servers* settings. Save preferences? Зберегти настройки? - No comment provided by engineer. + alert title Save profile password @@ -5477,18 +6084,18 @@ Enable in *Network & servers* settings. Save servers? Зберегти сервери? - No comment provided by engineer. - - - Save settings? - Зберегти налаштування? - No comment provided by engineer. + alert title Save welcome message? Зберегти вітальне повідомлення? No comment provided by engineer. + + Save your profile? + Зберегти свій профіль? + alert title + Saved Збережено @@ -5509,12 +6116,19 @@ Enable in *Network & servers* settings. Збережене повідомлення message info title + + Saving %lld messages + Збереження повідомлень %lld + No comment provided by engineer. + Scale + Масштаб No comment provided by engineer. Scan / Paste link + Відсканувати / Вставити посилання No comment provided by engineer. @@ -5559,6 +6173,7 @@ Enable in *Network & servers* settings. Secondary + Вторинний No comment provided by engineer. @@ -5568,6 +6183,7 @@ Enable in *Network & servers* settings. Secured + Забезпечено No comment provided by engineer. @@ -5585,12 +6201,19 @@ Enable in *Network & servers* settings. Виберіть chat item action + + Select chat profile + Виберіть профіль чату + No comment provided by engineer. + Selected %lld + Вибрано %lld No comment provided by engineer. Selected chat preferences prohibit this message. + Вибрані налаштування чату забороняють це повідомлення. No comment provided by engineer. @@ -5640,6 +6263,7 @@ Enable in *Network & servers* settings. Send errors + Помилки надсилання No comment provided by engineer. @@ -5654,6 +6278,7 @@ Enable in *Network & servers* settings. Send message to enable calls. + Надішліть повідомлення, щоб увімкнути дзвінки. No comment provided by engineer. @@ -5671,11 +6296,6 @@ Enable in *Network & servers* settings. Надсилати сповіщення No comment provided by engineer. - - Send notifications: - Надсилати сповіщення: - No comment provided by engineer. - Send questions and ideas Надсилайте запитання та ідеї @@ -5699,7 +6319,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. Відправник скасував передачу файлу. - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5758,6 +6378,7 @@ Enable in *Network & servers* settings. Sent directly + Відправлено напряму No comment provided by engineer. @@ -5772,6 +6393,7 @@ Enable in *Network & servers* settings. Sent messages + Надіслані повідомлення No comment provided by engineer. @@ -5781,18 +6403,32 @@ Enable in *Network & servers* settings. Sent reply + Надіслано відповідь No comment provided by engineer. Sent total + Відправлено всього No comment provided by engineer. Sent via proxy + Відправлено через проксі No comment provided by engineer. + + Server + Сервер + No comment provided by engineer. + + + Server added to operator %@. + Сервер додано до оператора %@. + alert message + Server address + Адреса сервера No comment provided by engineer. @@ -5802,8 +6438,24 @@ Enable in *Network & servers* settings. Server address is incompatible with network settings: %@. + Адреса сервера несумісна з налаштуваннями мережі: %@. No comment provided by engineer. + + Server operator changed. + Оператор сервера змінився. + alert title + + + Server operators + Оператори серверів + No comment provided by engineer. + + + Server protocol changed. + Протокол сервера змінено. + alert title + Server requires authorization to create queues, check password Сервер вимагає авторизації для створення черг, перевірте пароль @@ -5821,6 +6473,7 @@ Enable in *Network & servers* settings. Server type + Тип сервера No comment provided by engineer. @@ -5830,6 +6483,7 @@ Enable in *Network & servers* settings. Server version is incompatible with your app: %@. + Версія сервера несумісна з вашим додатком: %@. No comment provided by engineer. @@ -5839,10 +6493,12 @@ Enable in *Network & servers* settings. Servers info + Інформація про сервери No comment provided by engineer. Servers statistics will be reset - this cannot be undone! + Статистика серверів буде скинута - це неможливо скасувати! No comment provided by engineer. @@ -5862,6 +6518,7 @@ Enable in *Network & servers* settings. Set default theme + Встановлення теми за замовчуванням No comment provided by engineer. @@ -5904,6 +6561,11 @@ Enable in *Network & servers* settings. Налаштування No comment provided by engineer. + + Settings were changed. + Налаштування були змінені. + alert message + Shape profile images Сформуйте зображення профілю @@ -5912,25 +6574,42 @@ Enable in *Network & servers* settings. Share Поділіться - chat item action + alert action + chat item action Share 1-time link Поділитися 1-разовим посиланням No comment provided by engineer. + + Share 1-time link with a friend + Поділіться одноразовим посиланням з другом + No comment provided by engineer. + + + Share SimpleX address on social media. + Поділіться адресою SimpleX у соціальних мережах. + No comment provided by engineer. + Share address Поділитися адресою No comment provided by engineer. + + Share address publicly + Поділіться адресою публічно + No comment provided by engineer. + Share address with contacts? Поділіться адресою з контактами? - No comment provided by engineer. + alert title Share from other apps. + Діліться з інших програм. No comment provided by engineer. @@ -5938,6 +6617,11 @@ Enable in *Network & servers* settings. Поділіться посиланням No comment provided by engineer. + + Share profile + Поділіться профілем + No comment provided by engineer. + Share this 1-time invite link Поділіться цим одноразовим посиланням-запрошенням @@ -5945,6 +6629,7 @@ Enable in *Network & servers* settings. Share to SimpleX + Поділіться з SimpleX No comment provided by engineer. @@ -5979,6 +6664,7 @@ Enable in *Network & servers* settings. Show percentage + Показати відсоток No comment provided by engineer. @@ -5998,6 +6684,7 @@ Enable in *Network & servers* settings. SimpleX + SimpleX No comment provided by engineer. @@ -6005,6 +6692,10 @@ Enable in *Network & servers* settings. Адреса SimpleX No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. Безпека SimpleX Chat була перевірена компанією Trail of Bits. @@ -6035,6 +6726,16 @@ Enable in *Network & servers* settings. Адреса SimpleX No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + SimpleX-адреси та одноразові посилання можна безпечно ділитися через будь-який месенджер. + No comment provided by engineer. + + + SimpleX address or 1-time link? + SimpleX адреса або одноразове посилання? + No comment provided by engineer. + SimpleX contact address Контактна адреса SimpleX @@ -6055,8 +6756,8 @@ Enable in *Network & servers* settings. Посилання SimpleX chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. У цій групі заборонені посилання на SimpleX. No comment provided by engineer. @@ -6070,6 +6771,11 @@ Enable in *Network & servers* settings. Одноразове запрошення SimpleX simplex link type + + SimpleX protocols reviewed by Trail of Bits. + Протоколи SimpleX, розглянуті Trail of Bits. + No comment provided by engineer. + Simplified incognito mode Спрощений режим інкогніто @@ -6077,6 +6783,7 @@ Enable in *Network & servers* settings. Size + Розмір No comment provided by engineer. @@ -6096,10 +6803,17 @@ Enable in *Network & servers* settings. Soft + М'який blur media + + Some app settings were not migrated. + Деякі налаштування програми не були перенесені. + No comment provided by engineer. + Some file(s) were not exported: + Деякі файли не було експортовано: No comment provided by engineer. @@ -6109,8 +6823,16 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: + Під час імпорту виникли деякі несмертельні помилки: No comment provided by engineer. + + Some servers failed the test: +%@ + Деякі сервери не пройшли тестування: +%@ + alert message + Somebody Хтось @@ -6138,10 +6860,12 @@ Enable in *Network & servers* settings. Starting from %@. + Починаючи з %@. No comment provided by engineer. Statistics + Статистика No comment provided by engineer. @@ -6159,11 +6883,6 @@ Enable in *Network & servers* settings. Припинити чат No comment provided by engineer. - - Stop chat to enable database actions - Зупиніть чат, щоб увімкнути дії з базою даних - 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. Зупиніть чат, щоб експортувати, імпортувати або видалити базу даних чату. Ви не зможете отримувати та надсилати повідомлення, поки чат зупинено. @@ -6192,12 +6911,12 @@ Enable in *Network & servers* settings. Stop sharing Припиніть ділитися - No comment provided by engineer. + alert action Stop sharing address? Припинити ділитися адресою? - No comment provided by engineer. + alert title Stopping chat @@ -6206,6 +6925,7 @@ Enable in *Network & servers* settings. Strong + Сильний blur media @@ -6215,14 +6935,17 @@ Enable in *Network & servers* settings. Subscribed + Підписано No comment provided by engineer. Subscription errors + Помилки підписки No comment provided by engineer. Subscriptions ignored + Підписки ігноруються No comment provided by engineer. @@ -6230,6 +6953,16 @@ Enable in *Network & servers* settings. Підтримка чату SimpleX No comment provided by engineer. + + Switch audio and video during the call. + Перемикайте аудіо та відео під час дзвінка. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + Переключіть профіль чату для отримання одноразових запрошень. + No comment provided by engineer. + System Система @@ -6242,6 +6975,7 @@ Enable in *Network & servers* settings. TCP connection + TCP-з'єднання No comment provided by engineer. @@ -6264,11 +6998,20 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + Хвіст + No comment provided by engineer. + Take picture Сфотографуйте No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button Натисніть кнопку @@ -6306,6 +7049,7 @@ Enable in *Network & servers* settings. Temporary file error + Тимчасова помилка файлу No comment provided by engineer. @@ -6326,7 +7070,7 @@ Enable in *Network & servers* settings. Tests failed! Тести не пройшли! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6343,11 +7087,6 @@ Enable in *Network & servers* settings. Дякуємо користувачам - зробіть свій внесок через Weblate! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - Перша платформа без жодних ідентифікаторів користувачів – приватна за дизайном. - No comment provided by engineer. - 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. @@ -6360,6 +7099,11 @@ It can happen because of some bug or when the connection is compromised.Додаток може сповіщати вас, коли ви отримуєте повідомлення або запити на контакт - будь ласка, відкрийте налаштування, щоб увімкнути цю функцію. No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + Додаток захищає вашу конфіденційність, використовуючи різних операторів у кожній розмові. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). Програма попросить підтвердити завантаження з невідомих файлових серверів (крім .onion). @@ -6375,6 +7119,11 @@ It can happen because of some bug or when the connection is compromised.Відсканований вами код не є QR-кодом посилання SimpleX. No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + З'єднання досягло ліміту недоставлених повідомлень, ваш контакт може бути офлайн. + No comment provided by engineer. + The connection you accepted will be cancelled! Прийняте вами з'єднання буде скасовано! @@ -6395,6 +7144,11 @@ It can happen because of some bug or when the connection is compromised.Шифрування працює і нова угода про шифрування не потрібна. Це може призвести до помилок з'єднання! No comment provided by engineer. + + The future of messaging + Наступне покоління приватних повідомлень + No comment provided by engineer. + The hash of the previous message is different. Хеш попереднього повідомлення відрізняється. @@ -6412,15 +7166,12 @@ It can happen because of some bug or when the connection is compromised. The messages will be deleted for all members. + Повідомлення будуть видалені для всіх учасників. No comment provided by engineer. The messages will be marked as moderated for all members. - No comment provided by engineer. - - - The next generation of private messaging - Наступне покоління приватних повідомлень + Повідомлення будуть позначені як модеровані для всіх учасників. No comment provided by engineer. @@ -6433,6 +7184,21 @@ It can happen because of some bug or when the connection is compromised.Профіль доступний лише вашим контактам. No comment provided by engineer. + + The same conditions will apply to operator **%@**. + Такі ж умови діятимуть і для оператора **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + Такі ж умови будуть застосовуватися до оператора(ів): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + Другий попередньо встановлений оператор у застосунку! + No comment provided by engineer. + The second tick we missed! ✅ Другу галочку ми пропустили! ✅ @@ -6448,13 +7214,29 @@ It can happen because of some bug or when the connection is compromised.Сервери для нових підключень вашого поточного профілю чату **%@**. No comment provided by engineer. + + The servers for new files 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. + + The uploaded database archive will be permanently removed from the servers. + Завантажений архів бази даних буде назавжди видалено з серверів. + No comment provided by engineer. + Themes + Теми + No comment provided by engineer. + + + These conditions will also apply for: **%@**. + Ці умови також поширюються на: **%@**. No comment provided by engineer. @@ -6524,6 +7306,7 @@ It can happen because of some bug or when the connection is compromised. This link was used with another mobile device, please create a new link on the desktop. + Це посилання було використано з іншого мобільного пристрою, будь ласка, створіть нове посилання на робочому столі. No comment provided by engineer. @@ -6533,6 +7316,7 @@ It can happen because of some bug or when the connection is compromised. Title + Заголовок No comment provided by engineer. @@ -6555,9 +7339,9 @@ It can happen because of some bug or when the connection is compromised.Щоб створити нове з'єднання 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. - Щоб захистити конфіденційність, замість ідентифікаторів користувачів, які використовуються на всіх інших платформах, SimpleX має ідентифікатори для черг повідомлень, окремі для кожного з ваших контактів. + + To protect against your link being replaced, you can compare contact security codes. + Щоб захиститися від заміни вашого посилання, ви можете порівняти коди безпеки контактів. No comment provided by engineer. @@ -6577,6 +7361,26 @@ You will be prompted to complete authentication before this feature is enabled.< Перед увімкненням цієї функції вам буде запропоновано пройти автентифікацію. No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + Щоб захистити конфіденційність, замість ідентифікаторів користувачів, які використовуються на всіх інших платформах, SimpleX має ідентифікатори для черг повідомлень, окремі для кожного з ваших контактів. + No comment provided by engineer. + + + To receive + Щоб отримати + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + Для запису промови, будь ласка, надайте дозвіл на використання мікрофону. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + Для запису відео, будь ласка, надайте дозвіл на використання камери. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. Щоб записати голосове повідомлення, будь ласка, надайте дозвіл на використання мікрофону. @@ -6587,11 +7391,21 @@ You will be prompted to complete authentication before this feature is enabled.< Щоб відкрити свій прихований профіль, введіть повний пароль у поле пошуку на сторінці **Ваші профілі чату**. No comment provided by engineer. + + To send + Щоб відправити + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. Для підтримки миттєвих push-повідомлень необхідно перенести базу даних чату. No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + Щоб користуватися серверами **%@**, прийміть умови використання. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. Щоб перевірити наскрізне шифрування з вашим контактом, порівняйте (або відскануйте) код на ваших пристроях. @@ -6599,6 +7413,7 @@ You will be prompted to complete authentication before this feature is enabled.< Toggle chat list: + Перемикання списку чату: No comment provided by engineer. @@ -6608,10 +7423,12 @@ You will be prompted to complete authentication before this feature is enabled.< Toolbar opacity + Непрозорість панелі інструментів No comment provided by engineer. Total + Всього No comment provided by engineer. @@ -6621,6 +7438,7 @@ You will be prompted to complete authentication before this feature is enabled.< Transport sessions + Транспортні сесії No comment provided by engineer. @@ -6678,6 +7496,11 @@ You will be prompted to complete authentication before this feature is enabled.< Розблокувати учасника? No comment provided by engineer. + + Undelivered messages + Недоставлені повідомлення + No comment provided by engineer. + Unexpected migration state Неочікуваний стан міграції @@ -6726,7 +7549,7 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! Невідомі сервери! - No comment provided by engineer. + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6792,6 +7615,7 @@ To connect, please ask your contact to create another connection link and check Update settings? + Оновити налаштування? No comment provided by engineer. @@ -6806,6 +7630,7 @@ To connect, please ask your contact to create another connection link and check Upload errors + Помилки завантаження No comment provided by engineer. @@ -6820,10 +7645,12 @@ To connect, please ask your contact to create another connection link and check Uploaded + Завантажено No comment provided by engineer. Uploaded files + Завантажені файли No comment provided by engineer. @@ -6831,11 +7658,21 @@ To connect, please ask your contact to create another connection link and check Завантаження архіву No comment provided by engineer. + + Use %@ + Використовуйте %@ + No comment provided by engineer. + Use .onion hosts Використовуйте хости .onion No comment provided by engineer. + + Use SOCKS proxy + Використовуйте SOCKS проксі + No comment provided by engineer. + Use SimpleX Chat servers? Використовувати сервери SimpleX Chat? @@ -6851,6 +7688,16 @@ To connect, please ask your contact to create another connection link and check Використовувати поточний профіль No comment provided by engineer. + + Use for files + Використовуйте для файлів + No comment provided by engineer. + + + Use for messages + Використовуйте для повідомлень + No comment provided by engineer. + Use for new connections Використовуйте для нових з'єднань @@ -6891,6 +7738,11 @@ To connect, please ask your contact to create another connection link and check Використовувати сервер No comment provided by engineer. + + Use servers + Використовуйте сервери + No comment provided by engineer. + Use the app while in the call. Використовуйте додаток під час розмови. @@ -6898,15 +7750,17 @@ To connect, please ask your contact to create another connection link and check Use the app with one hand. - No comment provided by engineer. - - - User profile - Профіль користувача + Використовуйте додаток однією рукою. No comment provided by engineer. User selection + Вибір користувача + No comment provided by engineer. + + + Username + Ім'я користувача No comment provided by engineer. @@ -6979,11 +7833,21 @@ To connect, please ask your contact to create another connection link and check Відео та файли до 1 Гб No comment provided by engineer. + + View conditions + Умови перегляду + No comment provided by engineer. + View security code Переглянути код безпеки No comment provided by engineer. + + View updated conditions + Переглянути оновлені умови + No comment provided by engineer. + Visible history Видима історія @@ -6999,8 +7863,8 @@ To connect, please ask your contact to create another connection link and check Голосові повідомлення в цьому чаті заборонені. No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. Голосові повідомлення в цій групі заборонені. No comment provided by engineer. @@ -7041,10 +7905,12 @@ To connect, please ask your contact to create another connection link and check Wallpaper accent + Акцент на шпалерах No comment provided by engineer. Wallpaper background + Фон шпалер No comment provided by engineer. @@ -7092,9 +7958,9 @@ To connect, please ask your contact to create another connection link and check При підключенні аудіо та відеодзвінків. No comment provided by engineer. - - When people request to connect, you can accept or reject it. - Коли люди звертаються із запитом на підключення, ви можете прийняти або відхилити його. + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. + Коли увімкнено більше одного оператора, жоден з них не має метаданих, щоб дізнатися, хто з ким спілкується. No comment provided by engineer. @@ -7140,7 +8006,7 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. Без Tor або VPN ваша IP-адреса буде видимою для цих XFTP-ретрансляторів: %@. - No comment provided by engineer. + alert message Wrong database passphrase @@ -7154,6 +8020,7 @@ To connect, please ask your contact to create another connection link and check Wrong key or unknown file chunk address - most likely file is deleted. + Неправильний ключ або невідома адреса фрагмента файлу - найімовірніше, файл видалено. file error text @@ -7163,11 +8030,7 @@ To connect, please ask your contact to create another connection link and check XFTP server - No comment provided by engineer. - - - You - Ти + XFTP-сервер No comment provided by engineer. @@ -7195,6 +8058,10 @@ To connect, please ask your contact to create another connection link and check Ви вже підключені до %@. No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. Ви вже з'єднані з %@. @@ -7244,6 +8111,7 @@ Repeat join request? You are not connected to these servers. Private routing is used to deliver messages to them. + Не підключені до цих серверів. Для доставлення повідомлень до них використовується приватна маршрутизація. No comment provided by engineer. @@ -7253,6 +8121,17 @@ Repeat join request? You can change it in Appearance settings. + Ви можете змінити його в налаштуваннях зовнішнього вигляду. + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + Ви можете налаштувати операторів у налаштуваннях Мережі та серверів. + No comment provided by engineer. + + + You can configure servers via settings. + Ви можете налаштувати сервери за допомогою налаштувань. No comment provided by engineer. @@ -7292,6 +8171,12 @@ Repeat join request? You can send messages to %@ from Archived contacts. + Ви можете надсилати повідомлення на %@ з архівних контактів. + No comment provided by engineer. + + + You can set connection name, to remember who the link was shared with. + Ви можете задати ім'я з'єднання, щоб запам'ятати, з ким ви поділилися посиланням. No comment provided by engineer. @@ -7309,11 +8194,6 @@ Repeat join request? Ви можете поділитися цією адресою зі своїми контактами, щоб вони могли зв'язатися з **%@**. No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - Ви можете поділитися своєю адресою у вигляді посилання або QR-коду - будь-хто зможе зв'язатися з вами. - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app Запустити чат можна через Налаштування програми / База даних або перезапустивши програму @@ -7321,6 +8201,7 @@ Repeat join request? You can still view conversation with %@ in the list of chats. + Ви все ще можете переглянути розмову з %@ у списку чатів. No comment provided by engineer. @@ -7336,23 +8217,23 @@ Repeat join request? You can view invitation link again in connection details. Ви можете переглянути посилання на запрошення ще раз у деталях підключення. - No comment provided by engineer. + alert message You can't send messages! Ви не можете надсилати повідомлення! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - Ви контролюєте, через який(і) сервер(и) **отримувати** повідомлення, ваші контакти - сервери, які ви використовуєте для надсилання їм повідомлень. - No comment provided by engineer. - You could not be verified; please try again. Вас не вдалося верифікувати, спробуйте ще раз. No comment provided by engineer. + + You decide who can connect. + Ви вирішуєте, хто може під'єднатися. + No comment provided by engineer. + You have already requested connection via this address! Ви вже надсилали запит на підключення за цією адресою! @@ -7387,10 +8268,12 @@ Repeat connection request? You may migrate the exported database. + Ви можете мігрувати експортовану базу даних. No comment provided by engineer. You may save the exported archive. + Ви можете зберегти експортований архів. No comment provided by engineer. @@ -7400,6 +8283,7 @@ Repeat connection request? You need to allow your contact to call to be able to call them. + Щоб мати змогу зателефонувати контакту, вам потрібно дозволити йому зателефонувати. No comment provided by engineer. @@ -7452,6 +8336,10 @@ Repeat connection request? Ви все одно отримуватимете дзвінки та сповіщення від вимкнених профілів, якщо вони активні. No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. Ви перестанете отримувати повідомлення від цієї групи. Історія чату буде збережена. @@ -7472,11 +8360,6 @@ Repeat connection request? Ви використовуєте профіль інкогніто для цієї групи - щоб запобігти поширенню вашого основного профілю, запрошення контактів заборонено No comment provided by engineer. - - Your %@ servers - Ваші сервери %@ - No comment provided by engineer. - Your ICE servers Ваші сервери ICE @@ -7492,11 +8375,6 @@ Repeat connection request? Ваша адреса SimpleX No comment provided by engineer. - - Your XFTP servers - Ваші XFTP-сервери - No comment provided by engineer. - Your calls Твої дзвінки @@ -7512,11 +8390,21 @@ Repeat connection request? Ваша база даних чату не зашифрована - встановіть ключову фразу, щоб зашифрувати її. No comment provided by engineer. + + Your chat preferences + Ваші налаштування чату + alert title + Your chat profiles Ваші профілі чату No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + Ваше з'єднання було переміщено на %@, але під час перенаправлення на профіль сталася несподівана помилка. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). Ваш контакт надіслав файл, розмір якого перевищує підтримуваний на цей момент максимальний розмір (%@). @@ -7532,6 +8420,11 @@ Repeat connection request? Ваші контакти залишаться на зв'язку. No comment provided by engineer. + + Your credentials may be sent unencrypted. + Ваші облікові дані можуть бути надіслані незашифрованими. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. Ваша поточна база даних чату буде ВИДАЛЕНА і ЗАМІНЕНА імпортованою. @@ -7562,13 +8455,16 @@ Repeat connection request? Ваш профіль **%@** буде опублікований. No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. -Сервери SimpleX не бачать ваш профіль. + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + Ваш профіль зберігається на вашому пристрої і доступний лише вашим контактам. Сервери SimpleX не бачать ваш профіль. No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + Ваш профіль було змінено. Якщо ви збережете його, оновлений профіль буде надіслано всім вашим контактам. + alert message + Your profile, contacts and delivered messages are stored on your device. Ваш профіль, контакти та доставлені повідомлення зберігаються на вашому пристрої. @@ -7579,16 +8475,16 @@ SimpleX servers cannot see your profile. Ваш випадковий профіль No comment provided by engineer. - - Your server - Ваш сервер - No comment provided by engineer. - Your server address Адреса вашого сервера No comment provided by engineer. + + Your servers + Ваші сервери + No comment provided by engineer. + Your settings Ваші налаштування @@ -7629,6 +8525,10 @@ SimpleX servers cannot see your profile. прийнято виклик call status + + accepted invitation + chat list item title + admin адмін @@ -7666,6 +8566,7 @@ SimpleX servers cannot see your profile. attempts + спроби No comment provided by engineer. @@ -7710,6 +8611,7 @@ SimpleX servers cannot see your profile. call + дзвонити No comment provided by engineer. @@ -7815,7 +8717,7 @@ SimpleX servers cannot see your profile. connecting… з'єднання… - chat list item title + No comment provided by engineer. connection established @@ -7864,6 +8766,7 @@ SimpleX servers cannot see your profile. decryption errors + помилки розшифровки No comment provided by engineer. @@ -7918,6 +8821,7 @@ SimpleX servers cannot see your profile. duplicates + дублікати No comment provided by engineer. @@ -8002,6 +8906,12 @@ SimpleX servers cannot see your profile. expired + закінчився + No comment provided by engineer. + + + for better metadata privacy. + для кращої конфіденційності метаданих. No comment provided by engineer. @@ -8036,6 +8946,7 @@ SimpleX servers cannot see your profile. inactive + неактивний No comment provided by engineer. @@ -8080,6 +8991,7 @@ SimpleX servers cannot see your profile. invite + запросити No comment provided by engineer. @@ -8139,6 +9051,7 @@ SimpleX servers cannot see your profile. message + повідомлення No comment provided by engineer. @@ -8173,6 +9086,7 @@ SimpleX servers cannot see your profile. mute + приглушити No comment provided by engineer. @@ -8229,10 +9143,12 @@ SimpleX servers cannot see your profile. other + інший No comment provided by engineer. other errors + інші помилки No comment provided by engineer. @@ -8295,6 +9211,10 @@ SimpleX servers cannot see your profile. прибрали вас rcv group event chat item + + requested to connect + chat list item title + saved збережено @@ -8307,6 +9227,7 @@ SimpleX servers cannot see your profile. search + пошук No comment provided by engineer. @@ -8395,6 +9316,7 @@ last received msg: %2$@ unmute + увімкнути звук No comment provided by engineer. @@ -8444,6 +9366,7 @@ last received msg: %2$@ video + відео No comment provided by engineer. @@ -8617,6 +9540,38 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + %d нових подій + notification body + + + From: %@ + Від: %@ + notification body + + + New events + Нові події + notification + + + New messages + Нові повідомлення + notification + + + New messages in %d chats + Нові повідомлення в чатах %d + notification body + + +
@@ -8624,14 +9579,17 @@ last received msg: %2$@ SimpleX SE + SimpleX SE Bundle display name SimpleX SE + SimpleX SE Bundle name Copyright © 2024 SimpleX Chat. All rights reserved. + Copyright © 2024 SimpleX Chat. Всі права захищені. Copyright (human-readable) @@ -8643,150 +9601,187 @@ last received msg: %2$@ %@ + %@ No comment provided by engineer. App is locked! + Додаток заблоковано! No comment provided by engineer. Cancel + Скасувати No comment provided by engineer. Cannot access keychain to save database password + Не вдається отримати доступ до зв'язки ключів для збереження пароля до бази даних No comment provided by engineer. Cannot forward message + Неможливо переслати повідомлення No comment provided by engineer. Comment + Коментар No comment provided by engineer. Currently maximum supported file size is %@. + Наразі максимальний підтримуваний розмір файлу - %@. No comment provided by engineer. Database downgrade required + Потрібне оновлення бази даних No comment provided by engineer. Database encrypted! + База даних зашифрована! No comment provided by engineer. Database error + Помилка в базі даних No comment provided by engineer. Database passphrase is different from saved in the keychain. + Парольна фраза бази даних відрізняється від збереженої у в’язці ключів. No comment provided by engineer. Database passphrase is required to open chat. + Для відкриття чату потрібно ввести пароль до бази даних. No comment provided by engineer. Database upgrade required + Потрібне оновлення бази даних No comment provided by engineer. Error preparing file + Помилка підготовки файлу No comment provided by engineer. Error preparing message + Повідомлення про підготовку до помилки No comment provided by engineer. Error: %@ + Помилка: %@ No comment provided by engineer. File error + Помилка файлу No comment provided by engineer. Incompatible database version + Несумісна версія бази даних No comment provided by engineer. Invalid migration confirmation + Недійсне підтвердження міграції No comment provided by engineer. Keychain error + Помилка зв'язки ключів No comment provided by engineer. Large file! + Великий файл! No comment provided by engineer. No active profile + Немає активного профілю No comment provided by engineer. Ok + Гаразд No comment provided by engineer. Open the app to downgrade the database. + Відкрийте програму, щоб знизити версію бази даних. No comment provided by engineer. Open the app to upgrade the database. + Відкрийте програму, щоб оновити базу даних. No comment provided by engineer. Passphrase + Парольна фраза No comment provided by engineer. Please create a profile in the SimpleX app + Будь ласка, створіть профіль у додатку SimpleX No comment provided by engineer. Selected chat preferences prohibit this message. + Вибрані налаштування чату забороняють це повідомлення. No comment provided by engineer. Sending a message takes longer than expected. + Надсилання повідомлення займає більше часу, ніж очікувалося. No comment provided by engineer. Sending message… + Надсилаю повідомлення… No comment provided by engineer. Share + Поділіться No comment provided by engineer. Slow network? + Повільна мережа? No comment provided by engineer. Unknown database error: %@ + Невідома помилка бази даних: %@ No comment provided by engineer. Unsupported format + Непідтримуваний формат No comment provided by engineer. Wait + Зачекай No comment provided by engineer. Wrong database passphrase + Неправильна ключова фраза до бази даних No comment provided by engineer. You can allow sharing in Privacy & Security / SimpleX Lock settings. + Ви можете дозволити спільний доступ у налаштуваннях Конфіденційність і безпека / SimpleX Lock. No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/uk.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 8c3641549d..d6e548c6be 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 @@ -12,21 +12,6 @@ No comment provided by engineer. - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - - - - - No comment provided by engineer. - ( ( @@ -109,6 +94,7 @@ %@ downloaded + %@ 已下载 No comment provided by engineer. @@ -126,8 +112,17 @@ %@ 已认证 No comment provided by engineer. + + %@ server + No comment provided by engineer. + + + %@ servers + No comment provided by engineer. + %@ uploaded + %@ 已上传 No comment provided by engineer. @@ -135,6 +130,10 @@ %@ 要连接! notification title + + %1$@, %2$@ + format for date separator in chat + %@, %@ and %lld members %@, %@ 和 %lld 成员 @@ -155,11 +154,31 @@ %d 天 time interval + + %d file(s) are still being downloaded. + forward confirmation reason + + + %d file(s) failed to download. + forward confirmation reason + + + %d file(s) were deleted. + forward confirmation reason + + + %d file(s) were not downloaded. + forward confirmation reason + %d hours %d 小时 time interval + + %d messages not forwarded + alert title + %d min %d 分钟 @@ -222,14 +241,17 @@ %lld messages blocked by admin + %lld 被管理员阻止的消息 No comment provided by engineer. %lld messages marked deleted + %lld 标记为已删除的消息 No comment provided by engineer. %lld messages moderated by %@ + %lld 审核的留言 by %@ No comment provided by engineer. @@ -304,10 +326,12 @@ (new) + (新) No comment provided by engineer. (this device v%@) + (此设备 v%@) No comment provided by engineer. @@ -315,31 +339,29 @@ ) 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 or link for your contact. - **添加新联系人**:为您的联系人创建一次性二维码或者链接。 + + **Create 1-time link**: to create and share a new invitation link. + **添加联系人**: 创建新的邀请链接,或通过您收到的链接进行连接. No comment provided by engineer. **Create group**: to create a new group. + **创建群组**: 创建一个新群组. 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **更私密**:每20分钟检查新消息。设备令牌和 SimpleX Chat 服务器共享,但是不会共享有您有多少联系人或者消息。 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **最私密**:不使用 SimpleX Chat 通知服务器,在后台定期检查消息(取决于您多经常使用应用程序)。 No comment provided by engineer. **Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection. + **请注意**: 在两台设备上使用相同的数据库将破坏来自您的连接的消息解密,作为一种安全保护. No comment provided by engineer. @@ -347,11 +369,15 @@ **请注意**:如果您丢失密码,您将无法恢复或者更改密码。 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **推荐**:设备令牌和通知会发送至 SimpleX Chat 通知服务器,但是消息内容、大小或者发送人不会。 No comment provided by engineer. + + **Scan / Paste link**: to connect via a link you received. + No comment provided by engineer. + **Warning**: Instant push notifications require passphrase saved in Keychain. **警告**:及时推送通知需要保存在钥匙串的密码。 @@ -359,6 +385,7 @@ **Warning**: the archive will be removed. + **警告**: 存档将被删除. No comment provided by engineer. @@ -424,6 +451,7 @@ 0 sec + 0 秒 time to disappear @@ -456,6 +484,14 @@ 1周 time interval + + 1-time link + No comment provided by engineer. + + + 1-time link can be used *with one contact only* - share in person or via any messenger. + No comment provided by engineer. + 5 minutes 5分钟 @@ -525,23 +561,18 @@ 中止地址更改? No comment provided by engineer. - - About SimpleX - 关于SimpleX - No comment provided by engineer. - About SimpleX Chat 关于SimpleX Chat No comment provided by engineer. - - About SimpleX address - 关于 SimpleX 地址 + + About operators No comment provided by engineer. Accent + 强调 No comment provided by engineer. @@ -551,6 +582,10 @@ accept incoming call via notification swipe action + + Accept conditions + No comment provided by engineer. + Accept connection request? 接受联系人? @@ -567,16 +602,23 @@ accept contact request via notification swipe action + + Accepted conditions + No comment provided by engineer. + Acknowledged + 确认 No comment provided by engineer. Acknowledgement errors + 确认错误 No comment provided by engineer. Active connections + 活动连接 No comment provided by engineer. @@ -584,14 +626,8 @@ 将地址添加到您的个人资料,以便您的联系人可以与其他人共享。个人资料更新将发送给您的联系人。 No comment provided by engineer. - - Add contact - 添加联系人 - No comment provided by engineer. - - - Add preset servers - 添加预设服务器 + + Add friends No comment provided by engineer. @@ -609,6 +645,10 @@ 扫描二维码来添加服务器。 No comment provided by engineer. + + Add team members + No comment provided by engineer. + Add to another device 添加另一设备 @@ -619,16 +659,31 @@ 添加欢迎信息 No comment provided by engineer. + + Add your team members to the conversations. + No comment provided by engineer. + + + Added media & file servers + No comment provided by engineer. + + + Added message servers + No comment provided by engineer. + Additional accent + 附加重音 No comment provided by engineer. Additional accent 2 + 附加重音 2 No comment provided by engineer. Additional secondary + 附加二级 No comment provided by engineer. @@ -641,6 +696,14 @@ 将中止地址更改。将使用旧接收地址。 No comment provided by engineer. + + Address or 1-time link? + No comment provided by engineer. + + + Address settings + No comment provided by engineer. + Admins can block a member for all. 管理员可以为所有人封禁一名成员。 @@ -658,6 +721,7 @@ Advanced settings + 高级设置 No comment provided by engineer. @@ -675,8 +739,9 @@ 所有数据在输入后将被删除。 No comment provided by engineer. - - All data is private to your device. + + All data is kept private on your device. + 所有数据都是您设备的私有数据. No comment provided by engineer. @@ -684,6 +749,10 @@ 所有群组成员将保持连接。 No comment provided by engineer. + + All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages. + No comment provided by engineer. + All messages will be deleted - this cannot be undone! 所有消息都将被删除 - 这无法被撤销! @@ -696,11 +765,13 @@ All new messages from %@ will be hidden! + 来自 %@ 的所有新消息都将被隐藏! No comment provided by engineer. All profiles - No comment provided by engineer. + 所有配置文件 + profile dropdown All your contacts will remain connected. @@ -729,6 +800,7 @@ Allow calls? + 允许通话? No comment provided by engineer. @@ -738,11 +810,12 @@ Allow downgrade + 允许降级 No comment provided by engineer. Allow irreversible message deletion only if your contact allows it to you. (24 hours) - 仅有您的联系人许可后才允许不可撤回消息移除。 + 仅有您的联系人许可后才允许不可撤回消息移除 No comment provided by engineer. @@ -767,11 +840,12 @@ Allow sharing + 允许共享 No comment provided by engineer. Allow to irreversibly delete sent messages. (24 hours) - 允许不可撤回地删除已发送消息。 + 允许不可撤回地删除已发送消息 No comment provided by engineer. @@ -811,7 +885,7 @@ Allow your contacts to irreversibly delete sent messages. (24 hours) - 允许您的联系人不可撤回地删除已发送消息。 + 允许您的联系人不可撤回地删除已发送消息 No comment provided by engineer. @@ -841,6 +915,7 @@ Always use private routing. + 始终使用私有路由。 No comment provided by engineer. @@ -858,6 +933,11 @@ 接听来电 No comment provided by engineer. + + Anybody can host servers. + 任何人都可以托管服务器。 + No comment provided by engineer. + App build: %@ 应用程序构建:%@ @@ -888,6 +968,10 @@ 应用程序密码被替换为自毁密码。 No comment provided by engineer. + + App session + No comment provided by engineer. + App version 应用程序版本 @@ -910,6 +994,7 @@ Apply to + 应用于 No comment provided by engineer. @@ -919,10 +1004,12 @@ Archive contacts to chat later. + 存档联系人以便稍后聊天. No comment provided by engineer. Archived contacts + 已存档的联系人 No comment provided by engineer. @@ -990,6 +1077,10 @@ 自动接受图片 No comment provided by engineer. + + Auto-accept settings + alert title + Back 返回 @@ -997,6 +1088,7 @@ Background + 背景 No comment provided by engineer. @@ -1014,11 +1106,19 @@ 错误消息散列 No comment provided by engineer. + + Better calls + No comment provided by engineer. + Better groups 更佳的群组 No comment provided by engineer. + + Better message dates. + No comment provided by engineer. + Better messages 更好的消息 @@ -1026,10 +1126,24 @@ Better networking + 更好的网络 + No comment provided by engineer. + + + Better notifications + No comment provided by engineer. + + + Better security ✅ + No comment provided by engineer. + + + Better user experience No comment provided by engineer. Black + 黑色 No comment provided by engineer. @@ -1069,10 +1183,12 @@ Blur for better privacy. + 模糊处理,提高私密性. No comment provided by engineer. Blur media + 模糊媒体 No comment provided by engineer. @@ -1082,7 +1198,7 @@ Both you and your contact can irreversibly delete sent messages. (24 hours) - 您和您的联系人都可以不可逆转地删除已发送的消息。 + 您和您的联系人都可以不可逆转地删除已发送的消息 No comment provided by engineer. @@ -1105,6 +1221,14 @@ 保加利亚语、芬兰语、泰语和乌克兰语——感谢用户和[Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)! No comment provided by engineer. + + Business address + No comment provided by engineer. + + + Business chats + 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)。 @@ -1122,6 +1246,7 @@ Calls prohibited! + 禁止来电! No comment provided by engineer. @@ -1131,10 +1256,12 @@ Can't call contact + 无法呼叫联系人 No comment provided by engineer. Can't call member + 无法呼叫成员 No comment provided by engineer. @@ -1149,12 +1276,14 @@ Can't message member + 无法向成员发送消息 No comment provided by engineer. Cancel 取消 - No comment provided by engineer. + alert action + alert button Cancel migration @@ -1168,15 +1297,17 @@ Cannot forward message + 无法转发消息 No comment provided by engineer. Cannot receive file 无法接收文件 - No comment provided by engineer. + alert title Capacity exceeded - recipient did not receive previously sent messages. + 超出容量-收件人未收到以前发送的邮件。 snd error text @@ -1189,6 +1320,10 @@ 更改 No comment provided by engineer. + + Change chat profiles + authentication reason + Change database passphrase? 更改数据库密码? @@ -1235,13 +1370,21 @@ authentication reason set passcode view - - Chat archive - 聊天档案 + + Chat + No comment provided by engineer. + + + Chat already exists + No comment provided by engineer. + + + Chat already exists! No comment provided by engineer. Chat colors + 聊天颜色 No comment provided by engineer. @@ -1261,6 +1404,7 @@ Chat database exported + 导出的聊天数据库 No comment provided by engineer. @@ -1285,6 +1429,7 @@ Chat list + 聊天列表 No comment provided by engineer. @@ -1297,8 +1442,26 @@ 聊天偏好设置 No comment provided by engineer. + + Chat preferences were changed. + alert message + + + Chat profile + 用户资料 + No comment provided by engineer. + Chat theme + 聊天主题 + No comment provided by engineer. + + + Chat will be deleted for all members - this cannot be undone! + No comment provided by engineer. + + + Chat will be deleted for you - this cannot be undone! No comment provided by engineer. @@ -1306,10 +1469,18 @@ 聊天 No comment provided by engineer. + + Check messages every 20 min. + No comment provided by engineer. + + + Check messages when allowed. + No comment provided by engineer. + Check server address and try again. 检查服务器地址并再试一次。 - No comment provided by engineer. + alert title Chinese and Spanish interface @@ -1318,6 +1489,7 @@ Choose _Migrate from another device_ on the new device and scan QR code. + 在新设备上选择“从另一个设备迁移”并扫描二维码。 No comment provided by engineer. @@ -1332,14 +1504,17 @@ Chunks deleted + 已删除的块 No comment provided by engineer. Chunks downloaded + 下载的块 No comment provided by engineer. Chunks uploaded + 已下载的区块 No comment provided by engineer. @@ -1369,10 +1544,12 @@ Color chats with the new themes. + 使用新主题为聊天着色。 No comment provided by engineer. Color mode + 颜色模式 No comment provided by engineer. @@ -1387,6 +1564,43 @@ Completed + 已完成 + No comment provided by engineer. + + + Conditions accepted on: %@. + No comment provided by engineer. + + + Conditions are accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions are already accepted for these operator(s): **%@**. + No comment provided by engineer. + + + Conditions of use + No comment provided by engineer. + + + Conditions will be accepted for enabled operators after 30 days. + No comment provided by engineer. + + + Conditions will be accepted for operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted for the operator(s): **%@**. + No comment provided by engineer. + + + Conditions will be accepted on: %@. + No comment provided by engineer. + + + Conditions will be automatically accepted for enabled operators on: %@. No comment provided by engineer. @@ -1394,10 +1608,6 @@ 配置 ICE 服务器 No comment provided by engineer. - - Configured %@ servers - No comment provided by engineer. - Confirm 确认 @@ -1410,6 +1620,7 @@ Confirm contact deletion? + 确认删除联系人? No comment provided by engineer. @@ -1419,6 +1630,7 @@ Confirm files from unknown servers. + 确认来自未知服务器的文件。 No comment provided by engineer. @@ -1468,6 +1680,7 @@ Connect to your friends faster. + 更快地与您的朋友联系。 No comment provided by engineer. @@ -1478,15 +1691,20 @@ Connect to yourself? This is your own SimpleX address! + 与自己建立联系? +这是您自己的 SimpleX 地址! No comment provided by engineer. Connect to yourself? This is your own one-time link! + 与自己建立联系? +这是您自己的一次性链接! No comment provided by engineer. Connect via contact address + 通过联系地址连接 No comment provided by engineer. @@ -1501,10 +1719,12 @@ This is your own one-time link! Connect with %@ + 与 %@连接 No comment provided by engineer. Connected + 已连接 No comment provided by engineer. @@ -1514,6 +1734,7 @@ This is your own one-time link! Connected servers + 已连接的服务器 No comment provided by engineer. @@ -1523,6 +1744,7 @@ This is your own one-time link! Connecting + 正在连接 No comment provided by engineer. @@ -1537,6 +1759,7 @@ This is your own one-time link! Connecting to contact, please wait or check later! + 正在连接到联系人,请稍候或稍后检查! No comment provided by engineer. @@ -1551,6 +1774,7 @@ This is your own one-time link! Connection and servers status. + 连接和服务器状态。 No comment provided by engineer. @@ -1565,6 +1789,7 @@ This is your own one-time link! Connection notifications + 连接通知 No comment provided by engineer. @@ -1572,6 +1797,10 @@ This is your own one-time link! 已发送连接请求! No comment provided by engineer. + + Connection security + No comment provided by engineer. + Connection terminated 连接被终止 @@ -1584,10 +1813,12 @@ This is your own one-time link! Connection with desktop stopped + 与桌面的连接已停止 No comment provided by engineer. Connections + 连接 No comment provided by engineer. @@ -1602,6 +1833,7 @@ This is your own one-time link! Contact deleted! + 联系人已删除! No comment provided by engineer. @@ -1616,6 +1848,7 @@ This is your own one-time link! Contact is deleted. + 联系人被删除。 No comment provided by engineer. @@ -1630,6 +1863,7 @@ This is your own one-time link! Contact will be deleted - this cannot be undone! + 联系人将被删除-这是无法撤消的! No comment provided by engineer. @@ -1649,6 +1883,7 @@ This is your own one-time link! Conversation deleted! + 对话已删除! No comment provided by engineer. @@ -1658,6 +1893,7 @@ This is your own one-time link! Copy error + 复制错误 No comment provided by engineer. @@ -1665,8 +1901,13 @@ This is your own one-time link! 核心版本: v%@ No comment provided by engineer. + + Corner + No comment provided by engineer. + Correct name to %@? + 将名称更正为 %@? No comment provided by engineer. @@ -1674,6 +1915,10 @@ This is your own one-time link! 创建 No comment provided by engineer. + + Create 1-time link + No comment provided by engineer. + Create SimpleX address 创建 SimpleX 地址 @@ -1681,12 +1926,7 @@ This is your own one-time link! Create a group using a random profile. - 使用随机身份创建群组 - No comment provided by engineer. - - - Create an address to let people connect with you. - 创建一个地址,让人们与您联系。 + 使用随机身份创建群组. No comment provided by engineer. @@ -1736,6 +1976,7 @@ This is your own one-time link! Created + 已创建 No comment provided by engineer. @@ -1745,13 +1986,9 @@ This is your own one-time link! Created at: %@ + 创建于:%@ copied message info - - Created on %@ - 创建于 %@ - No comment provided by engineer. - Creating archive link 正在创建存档链接 @@ -1767,6 +2004,10 @@ This is your own one-time link! 当前密码 No comment provided by engineer. + + Current conditions text couldn't be loaded, you can review conditions via this link: + No comment provided by engineer. + Current passphrase… 现有密码…… @@ -1774,6 +2015,7 @@ This is your own one-time link! Current profile + 当前配置文件 No comment provided by engineer. @@ -1786,8 +2028,13 @@ This is your own one-time link! 自定义时间 No comment provided by engineer. + + Customizable message shape. + No comment provided by engineer. + Customize theme + 自定义主题 No comment provided by engineer. @@ -1797,6 +2044,7 @@ This is your own one-time link! Dark mode colors + 深色模式颜色 No comment provided by engineer. @@ -1899,6 +2147,7 @@ This is your own one-time link! Debug delivery + 调试交付 No comment provided by engineer. @@ -1914,15 +2163,18 @@ This is your own one-time link! Delete 删除 - chat item action + alert action + chat item action swipe action Delete %lld messages of members? + 删除成员的 %lld 消息? No comment provided by engineer. Delete %lld messages? + 删除 %lld 消息? No comment provided by engineer. @@ -1950,14 +2202,8 @@ This is your own one-time link! 删除并通知联系人 No comment provided by engineer. - - Delete archive - 删除档案 - No comment provided by engineer. - - - Delete chat archive? - 删除聊天档案? + + Delete chat No comment provided by engineer. @@ -1970,6 +2216,10 @@ This is your own one-time link! 删除聊天资料? No comment provided by engineer. + + Delete chat? + No comment provided by engineer. + Delete connection 删除连接 @@ -1982,6 +2232,7 @@ This is your own one-time link! Delete contact? + 删除联系人? No comment provided by engineer. @@ -2074,6 +2325,10 @@ This is your own one-time link! 删除旧数据库吗? No comment provided by engineer. + + Delete or moderate up to 200 messages. + No comment provided by engineer. + Delete pending connection? 删除待定连接? @@ -2091,6 +2346,7 @@ This is your own one-time link! Delete up to 20 messages at once. + 一次最多删除 20 条信息。 No comment provided by engineer. @@ -2100,10 +2356,12 @@ This is your own one-time link! Delete without notification + 删除而不通知 No comment provided by engineer. Deleted + 已删除 No comment provided by engineer. @@ -2118,6 +2376,11 @@ This is your own one-time link! Deletion errors + 删除错误 + No comment provided by engineer. + + + Delivered even when Apple drops them. No comment provided by engineer. @@ -2147,6 +2410,7 @@ This is your own one-time link! Desktop app version %@ is not compatible with this app. + 桌面应用程序版本 %@ 与此应用程序不兼容。 No comment provided by engineer. @@ -2156,22 +2420,27 @@ This is your own one-time link! Destination server address of %@ is incompatible with forwarding server %@ settings. + 目标服务器地址 %@ 与转发服务器 %@ 设置不兼容。 No comment provided by engineer. Destination server error: %@ + 目标服务器错误:%@ snd error text Destination server version of %@ is incompatible with forwarding server %@. + 目标服务器版本 %@ 与转发服务器 %@ 不兼容。 No comment provided by engineer. Detailed statistics + 详细的统计数据 No comment provided by engineer. Details + 详细信息 No comment provided by engineer. @@ -2181,6 +2450,7 @@ This is your own one-time link! Developer options + 开发者选项 No comment provided by engineer. @@ -2213,8 +2483,12 @@ This is your own one-time link! 私信 chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited in this chat. + No comment provided by engineer. + + + Direct messages between members are prohibited. 此群中禁止成员之间私信。 No comment provided by engineer. @@ -2235,6 +2509,7 @@ This is your own one-time link! Disabled + 禁用 No comment provided by engineer. @@ -2252,8 +2527,8 @@ This is your own one-time link! 此聊天中禁止显示限时消息。 No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. 该组禁止限时消息。 No comment provided by engineer. @@ -2289,6 +2564,7 @@ This is your own one-time link! Do NOT send messages directly, even if your or destination server does not support private routing. + 请勿直接发送消息,即使您的服务器或目标服务器不支持私有路由。 No comment provided by engineer. @@ -2298,6 +2574,7 @@ This is your own one-time link! Do NOT use private routing. + 不要使用私有路由。 No comment provided by engineer. @@ -2310,6 +2587,10 @@ This is your own one-time link! 不给新成员发送历史消息。 No comment provided by engineer. + + Do not use credentials with proxy. + No comment provided by engineer. + Don't create address 不创建地址 @@ -2333,10 +2614,12 @@ This is your own one-time link! Download 下载 - chat item action + alert button + chat item action Download errors + 下载错误 No comment provided by engineer. @@ -2349,12 +2632,18 @@ This is your own one-time link! 下载文件 server test step + + Download files + alert action + Downloaded + 已下载 No comment provided by engineer. Downloaded files + 下载的文件 No comment provided by engineer. @@ -2377,6 +2666,10 @@ This is your own one-time link! 时长 No comment provided by engineer. + + E2E encrypted notifications. + No comment provided by engineer. + Edit 编辑 @@ -2397,6 +2690,10 @@ This is your own one-time link! 启用(保持覆盖) No comment provided by engineer. + + Enable Flux + No comment provided by engineer. + Enable SimpleX Lock 启用 SimpleX 锁定 @@ -2459,6 +2756,7 @@ This is your own one-time link! Enabled + 已启用 No comment provided by engineer. @@ -2498,6 +2796,7 @@ This is your own one-time link! Encrypted message: app is stopped + 加密消息:应用程序已停止 notification @@ -2547,6 +2846,7 @@ This is your own one-time link! Enter group name… + 输入组名称… No comment provided by engineer. @@ -2586,6 +2886,7 @@ This is your own one-time link! Enter your name… + 请输入您的姓名… No comment provided by engineer. @@ -2598,26 +2899,33 @@ This is your own one-time link! 中止地址更改错误 No comment provided by engineer. + + Error accepting conditions + alert title + Error accepting contact request 接受联系人请求错误 No comment provided by engineer. - - Error accessing database file - 访问数据库文件错误 - No comment provided by engineer. - Error adding member(s) 添加成员错误 No comment provided by engineer. + + Error adding server + alert title + Error changing address 更改地址错误 No comment provided by engineer. + + Error changing connection profile + No comment provided by engineer. + Error changing role 更改角色错误 @@ -2628,8 +2936,13 @@ This is your own one-time link! 更改设置错误 No comment provided by engineer. + + Error changing to incognito! + No comment provided by engineer. + Error connecting to forwarding server %@. Please try later. + 连接到转发服务器 %@ 时出错。请稍后尝试。 No comment provided by engineer. @@ -2729,6 +3042,7 @@ This is your own one-time link! Error exporting theme: %@ + 导出主题时出错: %@ No comment provided by engineer. @@ -2741,26 +3055,32 @@ This is your own one-time link! 加入群组错误 No comment provided by engineer. - - Error loading %@ servers - 加载 %@ 服务器错误 + + Error loading servers + alert title + + + Error migrating settings No comment provided by engineer. Error opening chat + 打开聊天时出错 No comment provided by engineer. Error receiving file 接收文件错误 - No comment provided by engineer. + alert title Error reconnecting server + 重新连接服务器时出错 No comment provided by engineer. Error reconnecting servers + 重新连接服务器时出错 No comment provided by engineer. @@ -2770,11 +3090,7 @@ This is your own one-time link! Error resetting statistics - No comment provided by engineer. - - - Error saving %@ servers - 保存 %@ 服务器错误 + 重置统计信息时出错 No comment provided by engineer. @@ -2797,6 +3113,10 @@ This is your own one-time link! 保存密码到钥匙串错误 No comment provided by engineer. + + Error saving servers + alert title + Error saving settings 保存设置出错 @@ -2809,6 +3129,7 @@ This is your own one-time link! Error scanning code: %@ + 扫描代码时出错:%@ No comment provided by engineer. @@ -2841,10 +3162,14 @@ This is your own one-time link! 停止聊天错误 No comment provided by engineer. + + Error switching profile + No comment provided by engineer. + Error switching profile! 切换资料错误! - No comment provided by engineer. + alertTitle Error synchronizing connection @@ -2861,6 +3186,10 @@ This is your own one-time link! 更新消息错误 No comment provided by engineer. + + Error updating server + alert title + Error updating settings 更新设置错误 @@ -2889,8 +3218,7 @@ This is your own one-time link! Error: %@ 错误: %@ - file error text - snd error text + alert message Error: URL is invalid @@ -2904,8 +3232,13 @@ This is your own one-time link! Errors + 错误 No comment provided by engineer. + + Errors in servers configuration. + servers error + Even when disabled in the conversation. 即使在对话中被禁用。 @@ -2933,6 +3266,7 @@ This is your own one-time link! Export theme + 导出主题 No comment provided by engineer. @@ -2972,22 +3306,32 @@ This is your own one-time link! File error + 文件错误 No comment provided by engineer. + + File errors: +%@ + alert message + File not found - most likely file was deleted or cancelled. + 找不到文件 - 很可能文件已被删除或取消。 file error text File server error: %@ + 文件服务器错误:%@ file error text File status + 文件状态 No comment provided by engineer. File status: %@ + 文件状态:%@ copied message info @@ -3012,6 +3356,7 @@ This is your own one-time link! Files + 文件 No comment provided by engineer. @@ -3024,8 +3369,8 @@ This is your own one-time link! 文件和媒体 chat feature - - Files and media are prohibited in this group. + + Files and media are prohibited. 此群组中禁止文件和媒体。 No comment provided by engineer. @@ -3051,7 +3396,7 @@ This is your own one-time link! Finalize migration on another device. - 在另一部设备上完成迁移 + 在另一部设备上完成迁移. No comment provided by engineer. @@ -3094,21 +3439,53 @@ This is your own one-time link! 修复群组成员不支持的问题 No comment provided by engineer. + + For chat profile %@: + servers error + For console 用于控制台 No comment provided by engineer. + + For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server. + No comment provided by engineer. + + + For private routing + No comment provided by engineer. + + + For social media + No comment provided by engineer. + Forward 转发 chat item action + + Forward %d message(s)? + alert title + Forward and save messages 转发并保存消息 No comment provided by engineer. + + Forward messages + alert action + + + Forward messages without files? + alert message + + + Forward up to 20 messages at once. + No comment provided by engineer. + Forwarded 已转发 @@ -3119,26 +3496,37 @@ This is your own one-time link! 转发自 No comment provided by engineer. + + Forwarding %lld messages + No comment provided by engineer. + Forwarding server %@ failed to connect to destination server %@. Please try later. + 转发服务器 %@ 无法连接到目标服务器 %@。请稍后尝试。 No comment provided by engineer. Forwarding server address is incompatible with network settings: %@. + 转发服务器地址与网络设置不兼容:%@。 No comment provided by engineer. Forwarding server version is incompatible with network settings: %@. + 转发服务器版本与网络设置不兼容:%@。 No comment provided by engineer. Forwarding server: %1$@ Destination server error: %2$@ + 转发服务器: %1$@ +目标服务器错误: %2$@ snd error text Forwarding server: %1$@ Error: %2$@ + 转发服务器: %1$@ +错误: %2$@ snd error text @@ -3161,11 +3549,6 @@ Error: %2$@ 全名(可选) No comment provided by engineer. - - Full name: - 全名: - No comment provided by engineer. - Fully decentralized – visible only to members. 完全去中心化 - 仅对成员可见。 @@ -3188,10 +3571,12 @@ Error: %2$@ Good afternoon! + 下午好! message preview Good morning! + 早上好! message preview @@ -3201,6 +3586,7 @@ Error: %2$@ Group already exists + 群组已存在 No comment provided by engineer. @@ -3248,41 +3634,6 @@ Error: %2$@ 群组链接 No comment provided by engineer. - - Group members can add message reactions. - 群组成员可以添加信息回应。 - No comment provided by engineer. - - - Group members can irreversibly delete sent messages. (24 hours) - 群组成员可以不可撤回地删除已发送的消息。 - No comment provided by engineer. - - - Group members can send SimpleX links. - 群成员可发送 SimpleX 链接。 - No comment provided by engineer. - - - Group members can send direct messages. - 群组成员可以私信。 - No comment provided by engineer. - - - Group members can send disappearing messages. - 群组成员可以发送限时消息。 - No comment provided by engineer. - - - Group members can send files and media. - 群组成员可以发送文件和媒体。 - No comment provided by engineer. - - - Group members can send voice messages. - 群组成员可以发送语音消息。 - No comment provided by engineer. - Group message: 群组消息: @@ -3378,9 +3729,12 @@ Error: %2$@ SimpleX的工作原理 No comment provided by engineer. - - How it works - 工作原理 + + How it affects privacy + No comment provided by engineer. + + + How it helps privacy No comment provided by engineer. @@ -3400,6 +3754,7 @@ Error: %2$@ Hungarian interface + 匈牙利语界面 No comment provided by engineer. @@ -3407,6 +3762,10 @@ Error: %2$@ ICE 服务器(每行一个) No comment provided by engineer. + + IP address + No comment provided by engineer. + If you can't meet in person, show QR code in a video call, or share the link. 如果您不能亲自见面,可以在视频通话中展示二维码,或分享链接。 @@ -3447,8 +3806,8 @@ Error: %2$@ 立即 No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam 不受垃圾和骚扰消息影响 No comment provided by engineer. @@ -3474,6 +3833,7 @@ Error: %2$@ Import theme + 导入主题 No comment provided by engineer. @@ -3481,6 +3841,11 @@ Error: %2$@ 正在导入存档 No comment provided by engineer. + + Improved delivery, reduced traffic usage. +More improvements are coming soon! + No comment provided by engineer. + Improved message delivery 改进了消息传递 @@ -3581,6 +3946,11 @@ Error: %2$@ 安装[用于终端的 SimpleX Chat](https://github.com/simplex-chat/simplex-chat) No comment provided by engineer. + + Instant + 即时 + No comment provided by engineer. + Instant push notifications will be hidden! @@ -3588,11 +3958,6 @@ Error: %2$@ No comment provided by engineer. - - Instantly - 即时 - No comment provided by engineer. - Interface 界面 @@ -3600,6 +3965,7 @@ Error: %2$@ Interface colors + 界面颜色 No comment provided by engineer. @@ -3634,12 +4000,13 @@ Error: %2$@ Invalid response + 无效的响应 No comment provided by engineer. Invalid server address! 无效的服务器地址! - No comment provided by engineer. + alert title Invalid status @@ -3661,6 +4028,10 @@ Error: %2$@ 邀请成员 No comment provided by engineer. + + Invite to chat + No comment provided by engineer. + Invite to group 邀请加入群组 @@ -3676,8 +4047,8 @@ Error: %2$@ 此聊天中禁止不可撤回消息移除。 No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. 此群组中禁止不可撤回消息移除。 No comment provided by engineer. @@ -3704,6 +4075,7 @@ Error: %2$@ It protects your IP address and connections. + 它可以保护您的 IP 地址和连接。 No comment provided by engineer. @@ -3748,11 +4120,14 @@ Error: %2$@ Join with current profile + 使用当前档案加入 No comment provided by engineer. Join your group? This is your link for group %@! + 加入您的群组? +这是您组 %@ 的链接! No comment provided by engineer. @@ -3763,20 +4138,22 @@ This is your link for group %@! Keep 保留 - No comment provided by engineer. + alert action Keep conversation + 保持对话 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. + alert title Keep your connections @@ -3813,6 +4190,14 @@ This is your link for group %@! 离开 swipe action + + Leave chat + No comment provided by engineer. + + + Leave chat? + No comment provided by engineer. + Leave group 离开群组 @@ -3863,11 +4248,6 @@ This is your link for group %@! 实时消息 No comment provided by engineer. - - Local - 本地 - No comment provided by engineer. - Local name 本地名称 @@ -3888,11 +4268,6 @@ This is your link for group %@! 锁定模式 No comment provided by engineer. - - Make a private connection - 建立私密连接 - No comment provided by engineer. - Make one message disappear 使一条消息消失 @@ -3903,21 +4278,11 @@ This is your link for group %@! 将个人资料设为私密! No comment provided by engineer. - - Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@). - 请确保 %@服 务器地址格式正确,每行一个地址并且不重复 (%@)。 - No comment provided by engineer. - Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated. 确保 WebRTC ICE 服务器地址格式正确、每行分开且不重复。 No comment provided by engineer. - - Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?* - 许多人问: *如果SimpleX没有用户标识符,它怎么传递信息?* - No comment provided by engineer. - Mark deleted for everyone 标记为所有人已删除 @@ -3945,10 +4310,12 @@ This is your link for group %@! Media & file servers + Media & file servers No comment provided by engineer. Medium + 中等 blur media @@ -3958,8 +4325,13 @@ This is your link for group %@! Member inactive + 成员不活跃 item status text + + Member role will be changed to "%@". All chat members will be notified. + No comment provided by engineer. + Member role will be changed to "%@". All group members will be notified. 成员角色将更改为 "%@"。所有群成员将收到通知。 @@ -3970,13 +4342,53 @@ This is your link for group %@! 成员角色将更改为 "%@"。该成员将收到一份新的邀请。 No comment provided by engineer. + + Member will be removed from chat - this cannot be undone! + No comment provided by engineer. + Member will be removed from group - this cannot be undone! 成员将被移出群组——此操作无法撤消! No comment provided by engineer. + + Members can add message reactions. + 群组成员可以添加信息回应。 + No comment provided by engineer. + + + Members can irreversibly delete sent messages. (24 hours) + 群组成员可以不可撤回地删除已发送的消息 + No comment provided by engineer. + + + Members can send SimpleX links. + 群成员可发送 SimpleX 链接。 + No comment provided by engineer. + + + Members can send direct messages. + 群组成员可以私信。 + No comment provided by engineer. + + + Members can send disappearing messages. + 群组成员可以发送限时消息。 + No comment provided by engineer. + + + Members can send files and media. + 群组成员可以发送文件和媒体。 + No comment provided by engineer. + + + Members can send voice messages. + 群组成员可以发送语音消息。 + No comment provided by engineer. + Menus + 菜单 No comment provided by engineer. @@ -3991,6 +4403,7 @@ This is your link for group %@! Message delivery warning + 消息传递警告 item status text @@ -4000,14 +4413,17 @@ This is your link for group %@! Message forwarded + 消息已转发 item status text Message may be delivered later if member becomes active. + 如果 member 变为活动状态,则稍后可能会发送消息。 item status description Message queue info + 消息队列信息 No comment provided by engineer. @@ -4020,17 +4436,23 @@ This is your link for group %@! 该聊天禁用了消息回应。 No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. 该群组禁用了消息回应。 No comment provided by engineer. Message reception + 消息接收 No comment provided by engineer. Message servers + 消息服务器 + No comment provided by engineer. + + + Message shape No comment provided by engineer. @@ -4040,10 +4462,12 @@ This is your link for group %@! Message status + 消息状态 No comment provided by engineer. Message status: %@ + 消息状态:%@ copied message info @@ -4068,22 +4492,31 @@ This is your link for group %@! Messages from %@ will be shown! + 将显示来自 %@ 的消息! No comment provided by engineer. Messages received + 收到的消息 No comment provided by engineer. Messages sent + 已发送的消息 No comment provided by engineer. + + Messages were deleted after you selected them. + alert message + Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery. + 消息、文件和通话受到 **端到端加密** 的保护,具有完全正向保密、否认和闯入恢复。 No comment provided by engineer. Messages, files and calls are protected by **quantum resistant e2e encryption** with perfect forward secrecy, repudiation and break-in recovery. + 消息、文件和通话受到 **抗量子 e2e 加密** 的保护,具有完全正向保密、否认和闯入恢复。 No comment provided by engineer. @@ -4141,9 +4574,9 @@ This is your link for group %@! 迁移完成 No comment provided by engineer. - - Migrations: %@ - 迁移:%@ + + Migrations: + 迁移 No comment provided by engineer. @@ -4171,6 +4604,10 @@ This is your link for group %@! 更可靠的网络连接。 No comment provided by engineer. + + More reliable notifications + No comment provided by engineer. + Most likely this connection is deleted. 此连接很可能已被删除。 @@ -4206,8 +4643,13 @@ This is your link for group %@! 网络连接 No comment provided by engineer. + + Network decentralization + No comment provided by engineer. + Network issues - message expired after many attempts to send it. + 网络问题 - 消息在多次尝试发送后过期。 snd error text @@ -4215,6 +4657,10 @@ This is your link for group %@! 网络管理 No comment provided by engineer. + + Network operator + No comment provided by engineer. + Network settings 网络设置 @@ -4230,6 +4676,14 @@ This is your link for group %@! 新密码 No comment provided by engineer. + + New SOCKS credentials will be used every time you start the app. + No comment provided by engineer. + + + New SOCKS credentials will be used for each server. + No comment provided by engineer. + New chat 新聊天 @@ -4237,6 +4691,7 @@ This is your link for group %@! New chat experience 🎉 + 新的聊天体验 🎉 No comment provided by engineer. @@ -4249,11 +4704,6 @@ This is your link for group %@! 新联系人: notification - - New database archive - 新数据库存档 - No comment provided by engineer. - New desktop app! 全新桌面应用! @@ -4264,6 +4714,10 @@ This is your link for group %@! 新显示名 No comment provided by engineer. + + New events + notification + New in %@ %@ 的新内容 @@ -4271,6 +4725,7 @@ This is your link for group %@! New media options + 新媒体选项 No comment provided by engineer. @@ -4288,6 +4743,10 @@ This is your link for group %@! 新密码…… No comment provided by engineer. + + New server + No comment provided by engineer. + No @@ -4320,6 +4779,7 @@ This is your link for group %@! No direct connection yet, message is forwarded by admin. + 还没有直接连接,消息由管理员转发。 item status description @@ -4339,23 +4799,66 @@ This is your link for group %@! No info, try to reload + 无信息,尝试重新加载 No comment provided by engineer. + + No media & file servers. + servers error + + + No message servers. + servers error + No network connection 无网络连接 No comment provided by engineer. + + No permission to record speech + No comment provided by engineer. + + + No permission to record video + No comment provided by engineer. + No permission to record voice message 没有录制语音消息的权限 No comment provided by engineer. + + No push server + 本地 + No comment provided by engineer. + No received or sent files 未收到或发送文件 No comment provided by engineer. + + No servers for private message routing. + servers error + + + No servers to receive files. + servers error + + + No servers to receive messages. + servers error + + + No servers to send files. + servers error + + + No user identifiers. + 没有用户标识符。 + No comment provided by engineer. + Not compatible! 不兼容! @@ -4363,8 +4866,13 @@ This is your link for group %@! Nothing selected + 未选中任何内容 No comment provided by engineer. + + Nothing to forward! + alert title + Notifications 通知 @@ -4375,6 +4883,10 @@ This is your link for group %@! 通知被禁用! No comment provided by engineer. + + Notifications privacy + No comment provided by engineer. + Now admins can: - delete members' messages. @@ -4397,18 +4909,13 @@ This is your link for group %@! Ok 好的 - No comment provided by engineer. + alert button Old database 旧的数据库 No comment provided by engineer. - - Old database archive - 旧数据库存档 - No comment provided by engineer. - One-time invitation link 一次性邀请链接 @@ -4417,13 +4924,15 @@ This is your link for group %@! Onion hosts will be **required** for connection. Requires compatible VPN. - Onion 主机将用于连接。需要启用 VPN。 + Onion 主机将是连接所必需的。 +需要兼容的 VPN。 No comment provided by engineer. Onion hosts will be used when available. Requires compatible VPN. - 当可用时,将使用 Onion 主机。需要启用 VPN。 + 如果可用,将使用洋葱主机。 +需要兼容的 VPN。 No comment provided by engineer. @@ -4431,13 +4940,18 @@ Requires compatible VPN. 将不会使用 Onion 主机。 No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only chat owners can change preferences. + No comment provided by engineer. + + + Only client devices store user profiles, contacts, groups, and messages. 只有客户端设备存储用户资料、联系人、群组和**双层端到端加密**发送的消息。 No comment provided by engineer. Only delete conversation + 仅删除对话 No comment provided by engineer. @@ -4462,7 +4976,7 @@ Requires compatible VPN. Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours) - 只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除)。 + 只有您可以不可撤回地删除消息(您的联系人可以将它们标记为删除) No comment provided by engineer. @@ -4487,7 +5001,7 @@ Requires compatible VPN. Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours) - 只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除)。 + 只有您的联系人才能不可撤回地删除消息(您可以将它们标记为删除) No comment provided by engineer. @@ -4515,6 +5029,10 @@ Requires compatible VPN. 打开设置 No comment provided by engineer. + + Open changes + No comment provided by engineer. + Open chat 打开聊天 @@ -4525,6 +5043,10 @@ Requires compatible VPN. 打开聊天控制台 authentication reason + + Open conditions + No comment provided by engineer. + Open group 打开群 @@ -4532,24 +5054,24 @@ Requires compatible VPN. Open migration to another device + 打开迁移到另一台设备 authentication reason - - Open server settings - No comment provided by engineer. - - - Open user profiles - 打开用户个人资料 - authentication reason - - - Open-source protocol and code – anybody can run the servers. - 开源协议和代码——任何人都可以运行服务器。 - No comment provided by engineer. - Opening app… + 正在打开应用程序… + No comment provided by engineer. + + + Operator + No comment provided by engineer. + + + Operator server + alert title + + + Or import archive file No comment provided by engineer. @@ -4572,14 +5094,19 @@ Requires compatible VPN. 或者显示此码 No comment provided by engineer. + + Or to share privately + No comment provided by engineer. + Other 其他 No comment provided by engineer. - - Other %@ servers - No comment provided by engineer. + + Other file errors: +%@ + alert message PING count @@ -4616,6 +5143,10 @@ Requires compatible VPN. 密码已设置! No comment provided by engineer. + + Password + No comment provided by engineer. + Password to show 显示密码 @@ -4623,6 +5154,7 @@ Requires compatible VPN. Past member %@ + 前任成员 %@ past/unknown group member @@ -4647,15 +5179,11 @@ Requires compatible VPN. Pending + 待定 No comment provided by engineer. - - People can connect to you only via the links you share. - 人们只能通过您共享的链接与您建立联系。 - No comment provided by engineer. - - - Periodically + + Periodic 定期 No comment provided by engineer. @@ -4671,10 +5199,12 @@ Requires compatible VPN. Play from the chat list. + 从聊天列表播放。 No comment provided by engineer. Please ask your contact to enable calls. + 请要求您的联系人开通通话功能。 No comment provided by engineer. @@ -4685,6 +5215,8 @@ Requires compatible VPN. Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection. Please share any other issues with the developers. + 请检查移动设备和桌面是否连接到同一本地网络,以及桌面防火墙是否允许连接。 +请与开发人员分享任何其他问题。 No comment provided by engineer. @@ -4710,6 +5242,8 @@ Please share any other issues with the developers. Please contact developers. Error: %@ + 请联系开发人员。 +错误:%@ No comment provided by engineer. @@ -4757,6 +5291,10 @@ Error: %@ 波兰语界面 No comment provided by engineer. + + Port + No comment provided by engineer. + Possibly, certificate fingerprint in server address is incorrect 服务器地址中的证书指纹可能不正确 @@ -4767,16 +5305,15 @@ Error: %@ 保留最后的消息草稿及其附件。 No comment provided by engineer. - - Preset server - 预设服务器 - No comment provided by engineer. - Preset server address 预设服务器地址 No comment provided by engineer. + + Preset servers + No comment provided by engineer. + Preview 预览 @@ -4784,6 +5321,7 @@ Error: %@ Previously connected servers + 以前连接的服务器 No comment provided by engineer. @@ -4791,6 +5329,10 @@ Error: %@ 隐私和安全 No comment provided by engineer. + + Privacy for your customers. + No comment provided by engineer. + Privacy redefined 重新定义隐私 @@ -4803,10 +5345,12 @@ Error: %@ Private message routing + 私有消息路由 No comment provided by engineer. Private message routing 🚀 + 私有消息路由 🚀 No comment provided by engineer. @@ -4816,10 +5360,12 @@ Error: %@ Private routing + 专用路由 No comment provided by engineer. Private routing error + 专用路由错误 No comment provided by engineer. @@ -4837,15 +5383,6 @@ Error: %@ 个人资料图 No comment provided by engineer. - - Profile name - No comment provided by engineer. - - - Profile name: - 显示名: - No comment provided by engineer. - Profile password 个人资料密码 @@ -4853,12 +5390,13 @@ Error: %@ Profile theme + 个人资料主题 No comment provided by engineer. Profile update will be sent to your contacts. 个人资料更新将被发送给您的联系人。 - No comment provided by engineer. + alert message Prohibit audio/video calls. @@ -4882,6 +5420,7 @@ Error: %@ Prohibit sending SimpleX links. + 禁止发送 SimpleX 链接。 No comment provided by engineer. @@ -4906,6 +5445,7 @@ Error: %@ Protect IP address + 保护 IP 地址 No comment provided by engineer. @@ -4916,6 +5456,8 @@ Error: %@ Protect your IP address from the messaging relays chosen by your contacts. Enable in *Network & servers* settings. + 保护您的 IP 地址免受联系人选择的消息中继的攻击。 +在*网络和服务器*设置中启用。 No comment provided by engineer. @@ -4935,10 +5477,16 @@ Enable in *Network & servers* settings. Proxied + 代理 No comment provided by engineer. Proxied servers + 代理服务器 + No comment provided by engineer. + + + Proxy requires password No comment provided by engineer. @@ -4948,6 +5496,7 @@ Enable in *Network & servers* settings. Push server + 推送服务器 No comment provided by engineer. @@ -4962,6 +5511,7 @@ Enable in *Network & servers* settings. Reachable chat toolbar + 可访问的聊天工具栏 No comment provided by engineer. @@ -4979,26 +5529,21 @@ Enable in *Network & servers* settings. 阅读更多 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). 阅读更多[User Guide](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses). + 在 [用户指南](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses) 中阅读更多内容。 + 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) 中阅读更多内容。 No comment provided by engineer. - - Read more in our GitHub repository. - 在我们的 GitHub 仓库中阅读更多内容。 - No comment provided by engineer. - Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme). 在我们的 [GitHub 仓库](https://github.com/simplex-chat/simplex-chat#readme) 中阅读更多信息。 @@ -5011,6 +5556,7 @@ Enable in *Network & servers* settings. Receive errors + 接收错误 No comment provided by engineer. @@ -5035,14 +5581,17 @@ Enable in *Network & servers* settings. Received messages + 收到的消息 No comment provided by engineer. Received reply + 已收到回复 No comment provided by engineer. Received total + 接收总数 No comment provided by engineer. @@ -5062,6 +5611,7 @@ Enable in *Network & servers* settings. 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. @@ -5076,6 +5626,7 @@ Enable in *Network & servers* settings. Reconnect + 重新连接 No comment provided by engineer. @@ -5085,18 +5636,22 @@ Enable in *Network & servers* settings. Reconnect all servers + 重新连接所有服务器 No comment provided by engineer. Reconnect all servers? + 重新连接所有服务器? No comment provided by engineer. Reconnect server to force message delivery. It uses additional traffic. + 重新连接服务器以强制发送信息。它使用额外的流量。 No comment provided by engineer. Reconnect server? + 重新连接服务器? No comment provided by engineer. @@ -5150,8 +5705,13 @@ Enable in *Network & servers* settings. 移除 No comment provided by engineer. + + Remove archive? + No comment provided by engineer. + Remove image + 移除图片 No comment provided by engineer. @@ -5226,14 +5786,17 @@ Enable in *Network & servers* settings. Reset all hints + 重置所有提示 No comment provided by engineer. Reset all statistics + 重置所有统计信息 No comment provided by engineer. Reset all statistics? + 重置所有统计信息? No comment provided by engineer. @@ -5243,6 +5806,7 @@ Enable in *Network & servers* settings. Reset to app theme + 重置为应用程序主题 No comment provided by engineer. @@ -5252,6 +5816,7 @@ Enable in *Network & servers* settings. Reset to user theme + 重置为用户主题 No comment provided by engineer. @@ -5294,6 +5859,14 @@ Enable in *Network & servers* settings. 揭示 chat item action + + Review conditions + No comment provided by engineer. + + + Review later + No comment provided by engineer. + Revoke 撤销 @@ -5321,10 +5894,16 @@ Enable in *Network & servers* settings. SMP server + SMP 服务器 + No comment provided by engineer. + + + SOCKS proxy No comment provided by engineer. Safely receive files + 安全接收文件 No comment provided by engineer. @@ -5335,17 +5914,18 @@ Enable in *Network & servers* settings. Save 保存 - chat item action + alert button + chat item action Save (and notify contacts) 保存(并通知联系人) - No comment provided by engineer. + alert button Save and notify contact 保存并通知联系人 - No comment provided by engineer. + alert button Save and notify group members @@ -5354,6 +5934,7 @@ Enable in *Network & servers* settings. Save and reconnect + 保存并重新连接 No comment provided by engineer. @@ -5361,16 +5942,6 @@ Enable in *Network & servers* settings. 保存和更新组配置文件 No comment provided by engineer. - - Save archive - 保存存档 - No comment provided by engineer. - - - Save auto-accept settings - 保存自动接受设置 - No comment provided by engineer. - Save group profile 保存群组资料 @@ -5389,7 +5960,7 @@ Enable in *Network & servers* settings. Save preferences? 保存偏好设置? - No comment provided by engineer. + alert title Save profile password @@ -5404,18 +5975,17 @@ Enable in *Network & servers* settings. Save servers? 保存服务器? - No comment provided by engineer. - - - Save settings? - 保存设置? - No comment provided by engineer. + alert title Save welcome message? 保存欢迎信息? No comment provided by engineer. + + Save your profile? + alert title + Saved 已保存 @@ -5436,12 +6006,18 @@ Enable in *Network & servers* settings. 已保存的消息 message info title + + Saving %lld messages + No comment provided by engineer. + Scale + 规模 No comment provided by engineer. Scan / Paste link + 扫描 / 粘贴链接 No comment provided by engineer. @@ -5486,6 +6062,7 @@ Enable in *Network & servers* settings. Secondary + 二级 No comment provided by engineer. @@ -5495,6 +6072,7 @@ Enable in *Network & servers* settings. Secured + 担保 No comment provided by engineer. @@ -5512,12 +6090,18 @@ Enable in *Network & servers* settings. 选择 chat item action + + Select chat profile + No comment provided by engineer. + Selected %lld + 选定的 %lld No comment provided by engineer. Selected chat preferences prohibit this message. + 选定的聊天首选项禁止此消息。 No comment provided by engineer. @@ -5567,6 +6151,7 @@ Enable in *Network & servers* settings. Send errors + 发送错误 No comment provided by engineer. @@ -5581,14 +6166,17 @@ Enable in *Network & servers* settings. Send message to enable calls. + 发送消息以启用呼叫。 No comment provided by engineer. Send messages directly when IP address is protected and your or destination server does not support private routing. + 当 IP 地址受到保护并且您或目标服务器不支持私有路由时,直接发送消息。 No comment provided by engineer. Send messages directly when your or destination server does not support private routing. + 当您或目标服务器不支持私有路由时,直接发送消息。 No comment provided by engineer. @@ -5596,11 +6184,6 @@ Enable in *Network & servers* settings. 发送通知 No comment provided by engineer. - - Send notifications: - 发送通知: - No comment provided by engineer. - Send questions and ideas 发送问题和想法 @@ -5624,7 +6207,7 @@ Enable in *Network & servers* settings. Sender cancelled file transfer. 发送人已取消文件传输。 - No comment provided by engineer. + alert message Sender may have deleted the connection request. @@ -5683,6 +6266,7 @@ Enable in *Network & servers* settings. Sent directly + 直接发送 No comment provided by engineer. @@ -5697,6 +6281,7 @@ Enable in *Network & servers* settings. Sent messages + 已发送的消息 No comment provided by engineer. @@ -5706,28 +6291,54 @@ Enable in *Network & servers* settings. Sent reply + 已发送回复 No comment provided by engineer. Sent total + 发送总数 No comment provided by engineer. Sent via proxy + 通过代理发送 No comment provided by engineer. + + Server + No comment provided by engineer. + + + Server added to operator %@. + alert message + Server address + 服务器地址 No comment provided by engineer. Server address is incompatible with network settings. + 服务器地址与网络设置不兼容。 srv error text. Server address is incompatible with network settings: %@. + 服务器地址与网络设置不兼容:%@。 No comment provided by engineer. + + Server operator changed. + alert title + + + Server operators + No comment provided by engineer. + + + Server protocol changed. + alert title + Server requires authorization to create queues, check password 服务器需要授权才能创建队列,检查密码 @@ -5745,14 +6356,17 @@ Enable in *Network & servers* settings. Server type + 服务器类型 No comment provided by engineer. Server version is incompatible with network settings. + 服务器版本与网络设置不兼容。 srv error text Server version is incompatible with your app: %@. + 服务器版本与你的应用程序不兼容:%@。 No comment provided by engineer. @@ -5762,10 +6376,12 @@ Enable in *Network & servers* settings. Servers info + 服务器信息 No comment provided by engineer. Servers statistics will be reset - this cannot be undone! + 服务器统计信息将被重置 - 此操作无法撤消! No comment provided by engineer. @@ -5785,6 +6401,7 @@ Enable in *Network & servers* settings. Set default theme + 设置默认主题 No comment provided by engineer. @@ -5827,6 +6444,10 @@ Enable in *Network & servers* settings. 设置 No comment provided by engineer. + + Settings were changed. + alert message + Shape profile images 改变个人资料图形状 @@ -5835,25 +6456,39 @@ Enable in *Network & servers* settings. Share 分享 - chat item action + alert action + chat item action Share 1-time link 分享一次性链接 No comment provided by engineer. + + Share 1-time link with a friend + No comment provided by engineer. + + + Share SimpleX address on social media. + No comment provided by engineer. + Share address 分享地址 No comment provided by engineer. + + Share address publicly + No comment provided by engineer. + Share address with contacts? 与联系人分享地址? - No comment provided by engineer. + alert title Share from other apps. + 从其他应用程序共享。 No comment provided by engineer. @@ -5861,6 +6496,10 @@ Enable in *Network & servers* settings. 分享链接 No comment provided by engineer. + + Share profile + No comment provided by engineer. + Share this 1-time invite link 分享此一次性邀请链接 @@ -5868,6 +6507,7 @@ Enable in *Network & servers* settings. Share to SimpleX + 分享到 SimpleX No comment provided by engineer. @@ -5897,10 +6537,12 @@ Enable in *Network & servers* settings. Show message status + 显示消息状态 No comment provided by engineer. Show percentage + 显示百分比 No comment provided by engineer. @@ -5910,6 +6552,7 @@ Enable in *Network & servers* settings. Show → on messages sent via private routing. + 显示 → 通过专用路由发送的信息. No comment provided by engineer. @@ -5919,6 +6562,7 @@ Enable in *Network & servers* settings. SimpleX + SimpleX No comment provided by engineer. @@ -5926,6 +6570,10 @@ Enable in *Network & servers* settings. SimpleX 地址 No comment provided by engineer. + + SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app. + No comment provided by engineer. + SimpleX Chat security was audited by Trail of Bits. SimpleX Chat 的安全性 由 Trail of Bits 审核。 @@ -5956,6 +6604,14 @@ Enable in *Network & servers* settings. SimpleX 地址 No comment provided by engineer. + + SimpleX address and 1-time links are safe to share via any messenger. + No comment provided by engineer. + + + SimpleX address or 1-time link? + No comment provided by engineer. + SimpleX contact address SimpleX 联系地址 @@ -5976,8 +6632,8 @@ Enable in *Network & servers* settings. SimpleX 链接 chat feature - - SimpleX links are prohibited in this group. + + SimpleX links are prohibited. 此群禁止 SimpleX 链接。 No comment provided by engineer. @@ -5991,6 +6647,10 @@ Enable in *Network & servers* settings. SimpleX 一次性邀请 simplex link type + + SimpleX protocols reviewed by Trail of Bits. + No comment provided by engineer. + Simplified incognito mode 简化的隐身模式 @@ -5998,6 +6658,7 @@ Enable in *Network & servers* settings. Size + 大小 No comment provided by engineer. @@ -6017,10 +6678,16 @@ Enable in *Network & servers* settings. Soft + blur media + + Some app settings were not migrated. + No comment provided by engineer. + Some file(s) were not exported: + 某些文件未导出: No comment provided by engineer. @@ -6030,8 +6697,14 @@ Enable in *Network & servers* settings. Some non-fatal errors occurred during import: + 导入过程中出现一些非致命错误: No comment provided by engineer. + + Some servers failed the test: +%@ + alert message + Somebody 某人 @@ -6039,7 +6712,7 @@ Enable in *Network & servers* settings. Square, circle, or anything in between. - 方形、圆形、或两者之间的任意形状 + 方形、圆形、或两者之间的任意形状. No comment provided by engineer. @@ -6059,10 +6732,12 @@ Enable in *Network & servers* settings. Starting from %@. + 从 %@ 开始。 No comment provided by engineer. Statistics + 统计 No comment provided by engineer. @@ -6080,11 +6755,6 @@ Enable in *Network & servers* settings. 停止聊天程序 No comment provided by engineer. - - Stop chat to enable database actions - 停止聊天以启用数据库操作 - 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. 停止聊天以便导出、导入或删除聊天数据库。在聊天停止期间,您将无法收发消息。 @@ -6113,12 +6783,12 @@ Enable in *Network & servers* settings. Stop sharing 停止分享 - No comment provided by engineer. + alert action Stop sharing address? 停止分享地址? - No comment provided by engineer. + alert title Stopping chat @@ -6127,6 +6797,7 @@ Enable in *Network & servers* settings. Strong + 加粗 blur media @@ -6136,14 +6807,17 @@ Enable in *Network & servers* settings. Subscribed + 已订阅 No comment provided by engineer. Subscription errors + 订阅错误 No comment provided by engineer. Subscriptions ignored + 忽略订阅 No comment provided by engineer. @@ -6151,6 +6825,14 @@ Enable in *Network & servers* settings. 支持 SimpleX Chat No comment provided by engineer. + + Switch audio and video during the call. + No comment provided by engineer. + + + Switch chat profile for 1-time invitations. + No comment provided by engineer. + System 系统 @@ -6163,6 +6845,7 @@ Enable in *Network & servers* settings. TCP connection + TCP 连接 No comment provided by engineer. @@ -6185,11 +6868,19 @@ Enable in *Network & servers* settings. TCP_KEEPINTVL No comment provided by engineer. + + Tail + No comment provided by engineer. + Take picture 拍照 No comment provided by engineer. + + Tap Create SimpleX address in the menu to create it later. + No comment provided by engineer. + Tap button 点击按钮 @@ -6227,6 +6918,7 @@ Enable in *Network & servers* settings. Temporary file error + 临时文件错误 No comment provided by engineer. @@ -6247,7 +6939,7 @@ Enable in *Network & servers* settings. Tests failed! 测试失败! - No comment provided by engineer. + alert title Thank you for installing SimpleX Chat! @@ -6264,11 +6956,6 @@ Enable in *Network & servers* settings. 感谢用户——通过 Weblate 做出贡献! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. - 第一个没有任何用户标识符的平台 - 隐私设计. - No comment provided by engineer. - 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. @@ -6281,8 +6968,13 @@ It can happen because of some bug or when the connection is compromised.该应用可以在您收到消息或联系人请求时通知您——请打开设置以启用通知。 No comment provided by engineer. + + The app protects your privacy by using different operators in each conversation. + No comment provided by engineer. + The app will ask to confirm downloads from unknown file servers (except .onion). + 该应用程序将要求确认从未知文件服务器(.onion 除外)下载。 No comment provided by engineer. @@ -6295,6 +6987,10 @@ It can happen because of some bug or when the connection is compromised.您扫描的码不是 SimpleX 链接的二维码。 No comment provided by engineer. + + The connection reached the limit of undelivered messages, your contact may be offline. + No comment provided by engineer. + The connection you accepted will be cancelled! 您接受的连接将被取消! @@ -6315,6 +7011,11 @@ It can happen because of some bug or when the connection is compromised.加密正在运行,不需要新的加密协议。这可能会导致连接错误! No comment provided by engineer. + + The future of messaging + 下一代私密通讯软件 + No comment provided by engineer. + The hash of the previous message is different. 上一条消息的散列不同。 @@ -6332,15 +7033,12 @@ It can happen because of some bug or when the connection is compromised. The messages will be deleted for all members. + 将删除所有成员的消息。 No comment provided by engineer. The messages will be marked as moderated for all members. - No comment provided by engineer. - - - The next generation of private messaging - 下一代私密通讯软件 + 对于所有成员,这些消息将被标记为已审核。 No comment provided by engineer. @@ -6353,6 +7051,18 @@ It can happen because of some bug or when the connection is compromised.该资料仅与您的联系人共享。 No comment provided by engineer. + + The same conditions will apply to operator **%@**. + No comment provided by engineer. + + + The same conditions will apply to operator(s): **%@**. + No comment provided by engineer. + + + The second preset operator in the app! + No comment provided by engineer. + The second tick we missed! ✅ 我们错过的第二个"√"!✅ @@ -6368,13 +7078,26 @@ It can happen because of some bug or when the connection is compromised.您当前聊天资料 **%@** 的新连接服务器。 No comment provided by engineer. + + The servers for new files 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. + + The uploaded database archive will be permanently removed from the servers. + No comment provided by engineer. + Themes + 主题 + No comment provided by engineer. + + + These conditions will also apply for: **%@**. No comment provided by engineer. @@ -6444,6 +7167,7 @@ It can happen because of some bug or when the connection is compromised. This link was used with another mobile device, please create a new link on the desktop. + 此链接已在其他移动设备上使用,请在桌面上创建新链接。 No comment provided by engineer. @@ -6453,6 +7177,7 @@ It can happen because of some bug or when the connection is compromised. Title + 标题 No comment provided by engineer. @@ -6475,9 +7200,8 @@ It can happen because of some bug or when the connection is compromised.建立新连接 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. - 为了保护隐私,SimpleX使用针对消息队列的标识符,而不是所有其他平台使用的用户ID,每个联系人都有独立的标识符。 + + To protect against your link being replaced, you can compare contact security codes. No comment provided by engineer. @@ -6487,6 +7211,7 @@ It can happen because of some bug or when the connection is compromised. To protect your IP address, private routing uses your SMP servers to deliver messages. + 为了保护您的 IP 地址,私有路由使用您的 SMP 服务器来传递邮件。 No comment provided by engineer. @@ -6496,6 +7221,23 @@ You will be prompted to complete authentication before this feature is enabled.< 在启用此功能之前,系统将提示您完成身份验证。 No comment provided by engineer. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. + 为了保护隐私,SimpleX使用针对消息队列的标识符,而不是所有其他平台使用的用户ID,每个联系人都有独立的标识符。 + No comment provided by engineer. + + + To receive + No comment provided by engineer. + + + To record speech please grant permission to use Microphone. + No comment provided by engineer. + + + To record video please grant permission to use Camera. + No comment provided by engineer. + To record voice message please grant permission to use Microphone. 请授权使用麦克风以录制语音消息。 @@ -6506,11 +7248,19 @@ You will be prompted to complete authentication before this feature is enabled.< 要显示您的隐藏的个人资料,请在**您的聊天个人资料**页面的搜索字段中输入完整密码。 No comment provided by engineer. + + To send + No comment provided by engineer. + To support instant push notifications the chat database has to be migrated. 为了支持即时推送通知,聊天数据库必须被迁移。 No comment provided by engineer. + + To use the servers of **%@**, accept conditions of use. + No comment provided by engineer. + To verify end-to-end encryption with your contact compare (or scan) the code on your devices. 要与您的联系人验证端到端加密,请比较(或扫描)您设备上的代码。 @@ -6518,6 +7268,7 @@ You will be prompted to complete authentication before this feature is enabled.< Toggle chat list: + 切换聊天列表: No comment provided by engineer. @@ -6527,10 +7278,12 @@ You will be prompted to complete authentication before this feature is enabled.< Toolbar opacity + 工具栏不透明度 No comment provided by engineer. Total + 共计 No comment provided by engineer. @@ -6540,6 +7293,7 @@ You will be prompted to complete authentication before this feature is enabled.< Transport sessions + 传输会话 No comment provided by engineer. @@ -6554,6 +7308,7 @@ You will be prompted to complete authentication before this feature is enabled.< Turkish interface + 土耳其语界面 No comment provided by engineer. @@ -6596,6 +7351,10 @@ You will be prompted to complete authentication before this feature is enabled.< 解封成员吗? No comment provided by engineer. + + Undelivered messages + No comment provided by engineer. + Unexpected migration state 未预料的迁移状态 @@ -6643,7 +7402,8 @@ You will be prompted to complete authentication before this feature is enabled.< Unknown servers! - No comment provided by engineer. + 未知服务器! + alert title Unless you use iOS call interface, enable Do Not Disturb mode to avoid interruptions. @@ -6709,6 +7469,7 @@ To connect, please ask your contact to create another connection link and check Update settings? + 更新设置? No comment provided by engineer. @@ -6723,6 +7484,7 @@ To connect, please ask your contact to create another connection link and check Upload errors + 上传错误 No comment provided by engineer. @@ -6737,10 +7499,12 @@ To connect, please ask your contact to create another connection link and check Uploaded + 已上传 No comment provided by engineer. Uploaded files + 已上传的文件 No comment provided by engineer. @@ -6748,11 +7512,19 @@ To connect, please ask your contact to create another connection link and check 正在上传存档 No comment provided by engineer. + + Use %@ + No comment provided by engineer. + Use .onion hosts 使用 .onion 主机 No comment provided by engineer. + + Use SOCKS proxy + No comment provided by engineer. + Use SimpleX Chat servers? 使用 SimpleX Chat 服务器? @@ -6768,6 +7540,14 @@ To connect, please ask your contact to create another connection link and check 使用当前配置文件 No comment provided by engineer. + + Use for files + No comment provided by engineer. + + + Use for messages + No comment provided by engineer. + Use for new connections 用于新连接 @@ -6790,14 +7570,17 @@ To connect, please ask your contact to create another connection link and check Use only local notifications? + 仅使用本地通知? No comment provided by engineer. Use private routing with unknown servers when IP address is not protected. + 当 IP 地址不受保护时,对未知服务器使用私有路由。 No comment provided by engineer. Use private routing with unknown servers. + 对未知服务器使用私有路由。 No comment provided by engineer. @@ -6805,22 +7588,27 @@ To connect, please ask your contact to create another connection link and check 使用服务器 No comment provided by engineer. + + Use servers + No comment provided by engineer. + Use the app while in the call. - 通话时使用本应用 + 通话时使用本应用. No comment provided by engineer. Use the app with one hand. - No comment provided by engineer. - - - User profile - 用户资料 + 用一只手使用应用程序。 No comment provided by engineer. User selection + 用户选择 + No comment provided by engineer. + + + Username No comment provided by engineer. @@ -6893,11 +7681,19 @@ To connect, please ask your contact to create another connection link and check 最大 1gb 的视频和文件 No comment provided by engineer. + + View conditions + No comment provided by engineer. + View security code 查看安全码 No comment provided by engineer. + + View updated conditions + No comment provided by engineer. + Visible history 可见的历史 @@ -6913,8 +7709,8 @@ To connect, please ask your contact to create another connection link and check 语音信息在此聊天中被禁止。 No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. 语音信息在该群组中被禁用。 No comment provided by engineer. @@ -6935,6 +7731,7 @@ To connect, please ask your contact to create another connection link and check Waiting for desktop... + 正在等待桌面... No comment provided by engineer. @@ -6954,15 +7751,17 @@ To connect, please ask your contact to create another connection link and check Wallpaper accent + 壁纸装饰 No comment provided by engineer. Wallpaper background + 壁纸背景 No comment provided by engineer. Warning: starting chat on multiple devices is not supported and will cause message delivery failures - 警告:不支持在多部设备上启动聊天,这么做会导致消息传送失败。 + 警告:不支持在多部设备上启动聊天,这么做会导致消息传送失败 No comment provided by engineer. @@ -7005,9 +7804,8 @@ To connect, please ask your contact to create another connection link and check 连接音频和视频通话时。 No comment provided by engineer. - - When people request to connect, you can accept or reject it. - 当人们请求连接时,您可以接受或拒绝它。 + + When more than one operator is enabled, none of them has metadata to learn who communicates with whom. No comment provided by engineer. @@ -7047,11 +7845,13 @@ To connect, please ask your contact to create another connection link and check Without Tor or VPN, your IP address will be visible to file servers. + 如果没有 Tor 或 VPN,您的 IP 地址将对文件服务器可见。 No comment provided by engineer. Without Tor or VPN, your IP address will be visible to these XFTP relays: %@. - No comment provided by engineer. + 如果没有 Tor 或 VPN,您的 IP 地址将对以下 XFTP 中继可见:%@。 + alert message Wrong database passphrase @@ -7060,10 +7860,12 @@ To connect, please ask your contact to create another connection link and check Wrong key or unknown connection - most likely this connection is deleted. + 密钥错误或连接未知 - 很可能此连接已被删除。 snd error text Wrong key or unknown file chunk address - most likely file is deleted. + 密钥错误或文件块地址未知 - 很可能文件已删除。 file error text @@ -7073,15 +7875,12 @@ To connect, please ask your contact to create another connection link and check XFTP server - No comment provided by engineer. - - - You - + XFTP 服务器 No comment provided by engineer. You **must not** use the same database on two devices. + 您 **不得** 在两台设备上使用相同的数据库。 No comment provided by engineer. @@ -7104,8 +7903,13 @@ To connect, please ask your contact to create another connection link and check 您已经连接到 %@。 No comment provided by engineer. + + You are already connected with %@. + No comment provided by engineer. + You are already connecting to %@. + 您已连接到 %@。 No comment provided by engineer. @@ -7115,14 +7919,17 @@ To connect, please ask your contact to create another connection link and check 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. @@ -7133,6 +7940,8 @@ To connect, please ask your contact to create another connection link and check You are already joining the group! Repeat join request? + 您已经加入了这个群组! +重复加入请求? No comment provided by engineer. @@ -7147,6 +7956,7 @@ Repeat join request? You are not connected to these servers. Private routing is used to deliver messages to them. + 您未连接到这些服务器。私有路由用于向他们发送消息。 No comment provided by engineer. @@ -7156,6 +7966,15 @@ Repeat join request? You can change it in Appearance settings. + 您可以在外观设置中更改它。 + No comment provided by engineer. + + + You can configure operators in Network & servers settings. + No comment provided by engineer. + + + You can configure servers via settings. No comment provided by engineer. @@ -7195,6 +8014,11 @@ Repeat join request? You can send messages to %@ from Archived contacts. + 您可以从存档的联系人向%@发送消息。 + No comment provided by engineer. + + + You can set connection name, to remember who the link was shared with. No comment provided by engineer. @@ -7212,11 +8036,6 @@ Repeat join request? 您可以与您的联系人分享该地址,让他们与 **%@** 联系。 No comment provided by engineer. - - You can share your address as a link or QR code - anybody can connect to you. - 您可以将您的地址作为链接或二维码共享——任何人都可以连接到您。 - No comment provided by engineer. - You can start chat via app Settings / Database or by restarting the app 您可以通过应用程序设置/数据库或重新启动应用程序开始聊天 @@ -7224,6 +8043,7 @@ Repeat join request? You can still view conversation with %@ in the list of chats. + 您仍然可以在聊天列表中查看与 %@的对话。 No comment provided by engineer. @@ -7239,23 +8059,23 @@ Repeat join request? You can view invitation link again in connection details. 您可以在连接详情中再次查看邀请链接。 - No comment provided by engineer. + alert message You can't send messages! 您无法发送消息! No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - 您可以控制接收信息使用的服务器,您的联系人则使用您发送信息时所使用的服务器。 - No comment provided by engineer. - You could not be verified; please try again. 您的身份无法验证,请再试一次。 No comment provided by engineer. + + You decide who can connect. + 你决定谁可以连接。 + No comment provided by engineer. + You have already requested connection via this address! 你已经请求通过此地址进行连接! @@ -7264,6 +8084,8 @@ Repeat join request? You have already requested connection! Repeat connection request? + 您已经请求连接了! +重复连接请求? No comment provided by engineer. @@ -7288,10 +8110,12 @@ Repeat connection request? You may migrate the exported database. + 您可以迁移导出的数据库。 No comment provided by engineer. You may save the exported archive. + 您可以保存导出的档案。 No comment provided by engineer. @@ -7301,6 +8125,7 @@ Repeat connection request? You need to allow your contact to call to be able to call them. + 您需要允许您的联系人呼叫才能呼叫他们。 No comment provided by engineer. @@ -7325,6 +8150,7 @@ Repeat connection request? You will be connected when group link host's device is online, please wait or check later! + 当 Group Link Host 的设备在线时,您将被连接,请稍候或稍后检查! No comment provided by engineer. @@ -7352,6 +8178,10 @@ Repeat connection request? 当静音配置文件处于活动状态时,您仍会收到来自静音配置文件的电话和通知。 No comment provided by engineer. + + You will stop receiving messages from this chat. Chat history will be preserved. + No comment provided by engineer. + You will stop receiving messages from this group. Chat history will be preserved. 您将停止接收来自该群组的消息。聊天记录将被保留。 @@ -7372,11 +8202,6 @@ Repeat connection request? 您正在为该群组使用隐身个人资料——为防止共享您的主要个人资料,不允许邀请联系人 No comment provided by engineer. - - Your %@ servers - 您的 %@ 服务器 - No comment provided by engineer. - Your ICE servers 您的 ICE 服务器 @@ -7392,11 +8217,6 @@ Repeat connection request? 您的 SimpleX 地址 No comment provided by engineer. - - Your XFTP servers - 您的 XFTP 服务器 - No comment provided by engineer. - Your calls 您的通话 @@ -7412,11 +8232,19 @@ Repeat connection request? 您的聊天数据库未加密——设置密码来加密。 No comment provided by engineer. + + Your chat preferences + alert title + Your chat profiles 您的聊天资料 No comment provided by engineer. + + Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile. + No comment provided by engineer. + Your contact sent a file that is larger than currently supported maximum size (%@). 您的联系人发送的文件大于当前支持的最大大小 (%@)。 @@ -7432,6 +8260,10 @@ Repeat connection request? 与您的联系人保持连接。 No comment provided by engineer. + + Your credentials may be sent unencrypted. + No comment provided by engineer. + Your current chat database will be DELETED and REPLACED with the imported one. 您当前的聊天数据库将被删除并替换为导入的数据库。 @@ -7454,6 +8286,7 @@ Repeat connection request? Your profile + 您的个人资料 No comment provided by engineer. @@ -7461,13 +8294,15 @@ Repeat connection request? 您的个人资料 **%@** 将被共享。 No comment provided by engineer. - - Your profile is stored on your device and shared only with your contacts. -SimpleX servers cannot see your profile. - 您的资料存储在您的设备上并仅与您的联系人共享。 -SimpleX 服务器无法看到您的资料。 + + Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile. + 您的资料存储在您的设备上并仅与您的联系人共享。 SimpleX 服务器无法看到您的资料。 No comment provided by engineer. + + Your profile was changed. If you save it, the updated profile will be sent to all your contacts. + alert message + Your profile, contacts and delivered messages are stored on your device. 您的资料、联系人和发送的消息存储在您的设备上。 @@ -7478,16 +8313,15 @@ SimpleX 服务器无法看到您的资料。 您的随机资料 No comment provided by engineer. - - Your server - 您的服务器 - No comment provided by engineer. - Your server address 您的服务器地址 No comment provided by engineer. + + Your servers + No comment provided by engineer. + Your settings 您的设置 @@ -7528,6 +8362,10 @@ SimpleX 服务器无法看到您的资料。 已接受通话 call status + + accepted invitation + chat list item title + admin 管理员 @@ -7560,10 +8398,12 @@ SimpleX 服务器无法看到您的资料。 and %lld other events + 和 %lld 其他事件 No comment provided by engineer. attempts + 尝试 No comment provided by engineer. @@ -7608,6 +8448,7 @@ SimpleX 服务器无法看到您的资料。 call + 呼叫 No comment provided by engineer. @@ -7713,7 +8554,7 @@ SimpleX 服务器无法看到您的资料。 connecting… 连接中…… - chat list item title + No comment provided by engineer. connection established @@ -7727,6 +8568,7 @@ SimpleX 服务器无法看到您的资料。 contact %1$@ changed to %2$@ + 联系人 %1$@ 已更改为 %2$@ profile update event chat item @@ -7761,6 +8603,7 @@ SimpleX 服务器无法看到您的资料。 decryption errors + 解密错误 No comment provided by engineer. @@ -7815,6 +8658,7 @@ SimpleX 服务器无法看到您的资料。 duplicates + 复本 No comment provided by engineer. @@ -7899,6 +8743,11 @@ SimpleX 服务器无法看到您的资料。 expired + 过期 + No comment provided by engineer. + + + for better metadata privacy. No comment provided by engineer. @@ -7933,6 +8782,7 @@ SimpleX 服务器无法看到您的资料。 inactive + 无效 No comment provided by engineer. @@ -7977,6 +8827,7 @@ SimpleX 服务器无法看到您的资料。 invite + 邀请 No comment provided by engineer. @@ -8026,6 +8877,7 @@ SimpleX 服务器无法看到您的资料。 member %1$@ changed to %2$@ + 成员 %1$@ 已更改为 %2$@ profile update event chat item @@ -8035,6 +8887,7 @@ SimpleX 服务器无法看到您的资料。 message + 消息 No comment provided by engineer. @@ -8069,6 +8922,7 @@ SimpleX 服务器无法看到您的资料。 mute + 静音 No comment provided by engineer. @@ -8125,10 +8979,12 @@ SimpleX 服务器无法看到您的资料。 other + 其他 No comment provided by engineer. other errors + 其他错误 No comment provided by engineer. @@ -8191,6 +9047,10 @@ SimpleX 服务器无法看到您的资料。 已将您移除 rcv group event chat item + + requested to connect + chat list item title + saved 已保存 @@ -8198,10 +9058,12 @@ SimpleX 服务器无法看到您的资料。 saved from %@ + 保存自 %@ No comment provided by engineer. search + 搜索 No comment provided by engineer. @@ -8233,6 +9095,9 @@ SimpleX 服务器无法看到您的资料。 server queue info: %1$@ last received msg: %2$@ + 服务器队列信息: %1$@ + +上次收到的消息: %2$@ queue info @@ -8267,6 +9132,7 @@ last received msg: %2$@ unblocked %@ + 未阻止 %@ rcv group event chat item @@ -8276,6 +9142,7 @@ last received msg: %2$@ unknown servers + 未知服务器 No comment provided by engineer. @@ -8285,10 +9152,12 @@ last received msg: %2$@ unmute + 取消静音 No comment provided by engineer. unprotected + 未受保护 No comment provided by engineer. @@ -8303,6 +9172,7 @@ last received msg: %2$@ v%@ + v%@ No comment provided by engineer. @@ -8332,6 +9202,7 @@ last received msg: %2$@ video + 视频 No comment provided by engineer. @@ -8361,6 +9232,7 @@ last received msg: %2$@ when IP hidden + 当 IP 隐藏时 No comment provided by engineer. @@ -8385,6 +9257,7 @@ last received msg: %2$@ you blocked %@ + 你阻止了%@ snd group event chat item @@ -8429,6 +9302,7 @@ last received msg: %2$@ you unblocked %@ + 您解封了 %@ snd group event chat item @@ -8465,6 +9339,7 @@ last received msg: %2$@ SimpleX uses local network access to allow using user chat profile via desktop app on the same network. + SimpleX 使用本地网络访问,允许通过同一网络上的桌面应用程序使用用户聊天配置文件。 Privacy - Local Network Usage Description @@ -8501,6 +9376,33 @@ last received msg: %2$@ + +
+ +
+ + + %d new events + notification body + + + From: %@ + notification body + + + New events + notification + + + New messages + notification + + + New messages in %d chats + notification body + + +
@@ -8508,14 +9410,17 @@ last received msg: %2$@ SimpleX SE + SimpleX SE Bundle display name SimpleX SE + SimpleX SE Bundle name Copyright © 2024 SimpleX Chat. All rights reserved. + 版权所有 © 2024 SimpleX Chat。保留所有权利。 Copyright (human-readable) @@ -8527,150 +9432,187 @@ last received msg: %2$@ %@ + %@ No comment provided by engineer. App is locked! + 应用程序已锁定! No comment provided by engineer. Cancel + 取消 No comment provided by engineer. Cannot access keychain to save database password + 无法访问钥匙串以保存数据库密码 No comment provided by engineer. Cannot forward message + 无法转发消息 No comment provided by engineer. Comment + 评论 No comment provided by engineer. Currently maximum supported file size is %@. + 当前支持的最大文件大小为 %@。 No comment provided by engineer. Database downgrade required + 需要数据库降级 No comment provided by engineer. Database encrypted! + 数据库已加密! No comment provided by engineer. Database error + 数据库错误 No comment provided by engineer. Database passphrase is different from saved in the keychain. + 数据库密码与保存在钥匙串中的密码不同。 No comment provided by engineer. Database passphrase is required to open chat. + 需要数据库密码才能打开聊天。 No comment provided by engineer. Database upgrade required + 需要升级数据库 No comment provided by engineer. Error preparing file + 准备文件时出错 No comment provided by engineer. Error preparing message + 准备消息时出错 No comment provided by engineer. Error: %@ + 错误:%@ No comment provided by engineer. File error + 文件错误 No comment provided by engineer. Incompatible database version + 不兼容的数据库版本 No comment provided by engineer. Invalid migration confirmation + 无效的迁移确认 No comment provided by engineer. Keychain error + 钥匙串错误 No comment provided by engineer. Large file! + 大文件! No comment provided by engineer. No active profile + 无活动配置文件 No comment provided by engineer. Ok + 好的 No comment provided by engineer. Open the app to downgrade the database. + 打开应用程序以降级数据库。 No comment provided by engineer. Open the app to upgrade the database. + 打开应用程序以升级数据库。 No comment provided by engineer. Passphrase + 密码 No comment provided by engineer. Please create a profile in the SimpleX app + 请在 SimpleX 应用程序中创建配置文件 No comment provided by engineer. Selected chat preferences prohibit this message. + 选定的聊天首选项禁止此消息。 No comment provided by engineer. Sending a message takes longer than expected. + 发送消息所需的时间比预期的要长。 No comment provided by engineer. Sending message… + 正在发送消息… No comment provided by engineer. Share + 共享 No comment provided by engineer. Slow network? + 网络速度慢? No comment provided by engineer. Unknown database error: %@ + 未知数据库错误: %@ No comment provided by engineer. Unsupported format + 不支持的格式 No comment provided by engineer. Wait + 等待 No comment provided by engineer. Wrong database passphrase + 数据库密码错误 No comment provided by engineer. You can allow sharing in Privacy & Security / SimpleX Lock settings. + 您可以在 "隐私与安全"/"SimpleX Lock "设置中允许共享。 No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Source Contents/en.lproj/Localizable.strings b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Source Contents/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Source Contents/en.lproj/Localizable.strings +++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Source Contents/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - 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 8bc5a3b25d..93b9725131 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 @@ -187,23 +187,18 @@ ) No comment provided by engineer. - - **Add new contact**: to create your one-time QR Code or link for your contact. - **新增新的聯絡人**:建立一次性二維碼或連結連接聯絡人。 - No comment provided by engineer. - **Create link / QR code** for your contact to use. **建立連結 / 二維碼** 讓你的聯絡人使用。 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. + + **More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata. **更有私隱**:每20分鐘會檢查一次訊息。裝置權杖與 SimpleX Chat 伺服器分享中,但是不包括你的聯絡人和訊息資料。 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). + + **Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app. **最有私隱**:不使用 SimpleX Chat 通知服務器,在後台定期檢查訊息(取決於你使用應用程序的頻率)。 No comment provided by engineer. @@ -217,8 +212,8 @@ **請注意**:如果你忘記了密碼你將不能再次復原或更改密碼。 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. + + **Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from. **建議**:裝置權杖和通知都會傳送去 SimpeleX Chat 的通知伺服器,但是不包括訊息內容、大小或傳送者資料。 No comment provided by engineer. @@ -314,7 +309,7 @@ About SimpleX Chat - 關於 SimpleX 對話 + 關於 SimpleX Chat No comment provided by engineer. @@ -445,7 +440,7 @@ Allow your contacts to send disappearing messages. - 允許你的聯絡人傳送自動銷毀的訊息。 + 允許您的聯絡人傳送限時訊息。 No comment provided by engineer. @@ -1178,8 +1173,8 @@ 私訊 chat feature - - Direct messages between members are prohibited in this group. + + Direct messages between members are prohibited. 私訊群組內的成員於這個群組內是禁用的。 No comment provided by engineer. @@ -1198,8 +1193,8 @@ 自動銷毀訊息已被禁止於此聊天室。 No comment provided by engineer. - - Disappearing messages are prohibited in this group. + + Disappearing messages are prohibited. 自動銷毀訊息於這個群組內是禁用的。 No comment provided by engineer. @@ -1623,18 +1618,18 @@ 群組內的成員可以不可逆地刪除訊息。 No comment provided by engineer. - - Group members can send direct messages. + + Members can send direct messages. 群組內的成員可以私訊群組內的成員。 No comment provided by engineer. - - Group members can send disappearing messages. + + Members can send disappearing messages. 群組內的成員可以傳送自動銷毀的訊息。 No comment provided by engineer. - - Group members can send voice messages. + + Members can send voice messages. 群組內的成員可以傳送語音訊息。 No comment provided by engineer. @@ -1747,8 +1742,8 @@ 下載圖片需要傳送者上線的時候才能下載圖片,請等待對方上線! No comment provided by engineer. - - Immune to spam and abuse + + Immune to spam 不受垃圾郵件和濫用行為影響 No comment provided by engineer. @@ -1869,8 +1864,8 @@ 不可逆地刪除訊息於這個聊天室內是禁用的。 No comment provided by engineer. - - Irreversible message deletion is prohibited in this group. + + Irreversible message deletion is prohibited. 不可逆地刪除訊息於這個群組內是禁用的。 No comment provided by engineer. @@ -2217,8 +2212,8 @@ We will be adding server redundancy to prevent lost messages. Onion 主機不會啟用。 No comment provided by engineer. - - Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**. + + Only client devices store user profiles, contacts, groups, and messages. 只有客戶端裝置才會儲存你的個人檔案、聯絡人,群組,所有訊息都會經過**兩層的端對端加密**。 No comment provided by engineer. @@ -2277,8 +2272,8 @@ We will be adding server redundancy to prevent lost messages. 使用終端機開啟對話 authentication reason - - Open-source protocol and code – anybody can run the servers. + + Anybody can host servers. 開放源碼協議和程式碼 – 任何人也可以運行伺服器。 No comment provided by engineer. @@ -2317,8 +2312,8 @@ We will be adding server redundancy to prevent lost messages. 將你接收到的連結貼上至下面的框內,以開始你與你的聯絡人對話。 No comment provided by engineer. - - People can connect to you only via the links you share. + + You decide who can connect. 人們只能在你分享了連結後,才能和你連接。 No comment provided by engineer. @@ -3010,8 +3005,8 @@ We will be adding server redundancy to prevent lost messages. 感謝你安裝SimpleX Chat! No comment provided by engineer. - - The 1st platform without any user identifiers – private by design. + + No user identifiers. 第一個沒有任何用戶識別符的通訊平台 – 以私隱為設計。 No comment provided by engineer. @@ -3049,8 +3044,8 @@ We will be adding server redundancy to prevent lost messages. The microphone does not work when the app is in the background. No comment provided by engineer. - - The next generation of private messaging + + The future of messaging 新一代的私密訊息平台 No comment provided by engineer. @@ -3118,8 +3113,8 @@ We will be adding server redundancy to prevent lost messages. To prevent the call interruption, enable Do Not Disturb mode. 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. + + To protect your privacy, SimpleX uses separate IDs for each of your contacts. 為了保護隱私,而不像是其他平台般需要提取和存儲用戶的 IDs 資料,SimpleX 平台有自家佇列的標識符,這對於你的每個聯絡人也是獨一無二的。 No comment provided by engineer. @@ -3321,8 +3316,8 @@ To connect, please ask your contact to create another connection link and check 語音訊息於這個聊天窒是禁用的。 No comment provided by engineer. - - Voice messages are prohibited in this group. + + Voice messages are prohibited. 語音訊息於這個群組內是禁用的。 No comment provided by engineer. @@ -3455,11 +3450,6 @@ To connect, please ask your contact to create another connection link and check 你可以使用 Markdown 語法以更清楚標明訊息: No comment provided by engineer. - - You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them. - 你可以控制通過哪一個伺服器 **來接收** 你的聯絡人訊息 – 這些伺服器用來接收他們傳送給你的訊息。 - No comment provided by engineer. - You could not be verified; please try again. 你未能通過認證;請再試一次。 @@ -4791,8 +4781,8 @@ Available in v5.1 訊息 & 檔案 No comment provided by engineer. - - Migrations: %@ + + Migrations: 遷移:%@ No comment provided by engineer. @@ -5523,8 +5513,8 @@ It can happen because of some bug or when the connection is compromised.啟用自毀密碼 set passcode view - - Group members can add message reactions. + + Members can add message reactions. 群組內的成員可以新增訊息互動。 No comment provided by engineer. @@ -5699,8 +5689,8 @@ It can happen because of some bug or when the connection is compromised.已移除在 No comment provided by engineer. - - Message reactions are prohibited in this group. + + Message reactions are prohibited. 訊息互動於這個群組內是禁用的。 No comment provided by engineer. @@ -5898,6 +5888,230 @@ It can happen because of some bug or when the connection is compromised.%@ 和 %@ 已連接 No comment provided by engineer. + + %@ downloaded + %@ 下載 + + + %@ uploaded + %@ 上傳 + + + Abort + 中止 + + + **Create group**: to create a new group. + **創建群組**: 創建一個新的群組。 + + + Abort changing address + 中止更改地址 + + + Accept connection request? + 接受連線請求? + + + Camera not available + 相機不可用 + + + All messages will be deleted - this cannot be undone! + 所有訊息都將被刪除 - 這不能還原! + + + Allow irreversible message deletion only if your contact allows it to you. (24 hours) + 只有你的聯絡人允許的情況下,才允許不可逆地將訊息刪除。(24小時) + + + Allow to irreversibly delete sent messages. (24 hours) + 允許將不可撤銷的訊息刪除。(24小時) + + + Allow your contacts to irreversibly delete sent messages. (24 hours) + 允許您的聯絡人不可復原地刪除已傳送的訊息。(24小時) + + + Bad desktop address + 無效的桌面地址 + + + Error decrypting file + 解密檔案時出錯 + + + Add contact + 新增聯絡人 + + + Advanced settings + 進階設定 + + + Allow calls? + 允許通話? + + + Allow to send files and media. + 允許傳送檔案和媒體。 + + + Already joining the group! + 已加入群組! + + + App data migration + 應用資料轉移 + + + Apply + 應用 + + + Apply to + 應用到 + + + Archive and upload + 儲存並上傳 + + + Block + 封鎖 + + + Block group members + 封鎖群組成員 + + + Block member + 封鎖成員 + + + 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)! + + + Can't call member + 無法與成員通話 + + + Can't message member + 無法傳送訊息給成員 + + + Cancel migration + 取消遷移 + + + Chat database exported + 導出聊天數據庫 + + + 0 sec + 0 秒 + + + All your contacts, conversations and files will be securely encrypted and uploaded in chunks to configured XFTP relays. + 你的所有聯絡人、對話和文件將被安全加密並切塊上傳到設置的 XFTP 中繼。 + + + Address change will be aborted. Old receiving address will be used. + 將取消地址更改。將使用舊聯絡地址。 + + + Archiving database + 正在儲存資料庫 + + + Cellular + 行動網路 + + + %@, %@ and %lld members + %@, %@ 和 %lld 成員 + + + %lld messages marked deleted + %lld 條訊息已刪除 + + + Already connecting! + 已連接! + + + Block member? + 封鎖成員? + + + (new) + (新) + + + %@, %@ and %lld other members connected + %@, %@ 和 %lld 個成員已連接 + + + A few more things + 其他 + + + Show last messages + 顯示最新的訊息 + + + App encrypts new local files (except videos). + 應用程式將為新的本機文件(影片除外)加密。 + + + Better groups + 更加的群組 + + + %lld new interface languages + %lld 種新的介面語言 + + + Blocked by admin + 由管理員封鎖 + + + Both you and your contact can irreversibly delete sent messages. (24 hours) + 您與您的聯絡人都可以不可復原地删除已傳送的訊息。(24小時) + + + Encrypt local files + 加密本機檔案 + + + - more stable message delivery. +- a bit better groups. +- and more! + - 更穩定的傳送! +- 更好的社群! +- 以及更多! + + + - optionally notify deleted contacts. +- profile names with spaces. +- and more! + - 可選擇通知已刪除的聯絡人 +- 帶空格的共人資料名稱。 +-以及更多! + + + Abort changing address? + 中止更改地址? + + + Allow to send SimpleX links. + 允許傳送 SimpleX 連結。 + + + Background + 後台 + diff --git a/apps/ios/SimpleX NSE/NotificationService.swift b/apps/ios/SimpleX NSE/NotificationService.swift index 1a2a27ba9b..ce80adf38f 100644 --- a/apps/ios/SimpleX NSE/NotificationService.swift +++ b/apps/ios/SimpleX NSE/NotificationService.swift @@ -26,14 +26,52 @@ enum NSENotification { case nse(UNMutableNotificationContent) case callkit(RcvCallInvitation) case empty - case msgInfo(NtfMsgInfo) +} - var isCallInvitation: Bool { +public enum NSENotificationData { + case connectionEvent(_ user: User, _ connEntity: ConnectionEntity) + case contactConnected(_ user: any UserLike, _ contact: Contact) + case contactRequest(_ user: any UserLike, _ contactRequest: UserContactRequest) + case messageReceived(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) + case callInvitation(_ invitation: RcvCallInvitation) + case msgInfo(NtfMsgAckInfo) + case noNtf + + var callInvitation: RcvCallInvitation? { switch self { - case let .nse(ntf): ntf.categoryIdentifier == ntfCategoryCallInvitation - case .callkit: true - case .empty: false - case .msgInfo: false + case let .callInvitation(invitation): invitation + default: nil + } + } + + func notificationContent(_ badgeCount: Int) -> UNMutableNotificationContent { + return switch self { + case let .connectionEvent(user, connEntity): createConnectionEventNtf(user, connEntity, badgeCount) + case let .contactConnected(user, contact): createContactConnectedNtf(user, contact, badgeCount) + case let .contactRequest(user, contactRequest): createContactRequestNtf(user, contactRequest, badgeCount) + case let .messageReceived(user, cInfo, cItem): createMessageReceivedNtf(user, cInfo, cItem, badgeCount) + case let .callInvitation(invitation): createCallInvitationNtf(invitation, badgeCount) + case .msgInfo: UNMutableNotificationContent() + case .noNtf: UNMutableNotificationContent() + } + } + + var notificationEvent: NSENotificationData? { + return switch self { + case .connectionEvent: self + case .contactConnected: self + case .contactRequest: self + case .messageReceived: self + case .callInvitation: self + case .msgInfo: nil + case .noNtf: nil + } + } + + var newMsgData: (any UserLike, ChatInfo)? { + return switch self { + case let .messageReceived(user, cInfo, _): (user, cInfo) + default: nil } } } @@ -43,9 +81,10 @@ enum NSENotification { // or when background notification is received. class NSEThreads { static let shared = NSEThreads() - private static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-threads.lock") + static let queue = DispatchQueue(label: "chat.simplex.app.SimpleX-NSE.notification-threads.lock") private var allThreads: Set = [] - private var activeThreads: [(UUID, NotificationService)] = [] + var activeThreads: [(UUID, NotificationService)] = [] + var droppedNotifications: [(ChatId, NSENotificationData)] = [] func newThread() -> UUID { NSEThreads.queue.sync { @@ -64,22 +103,19 @@ class NSEThreads { } } - func processNotification(_ id: ChatId, _ ntf: NSENotification) async -> Void { - var waitTime: Int64 = 5_000_000000 - while waitTime > 0 { - if let (_, nse) = rcvEntityThread(id), - nse.shouldProcessNtf && nse.processReceivedNtf(ntf) { - break - } else { - try? await Task.sleep(nanoseconds: 10_000000) - waitTime -= 10_000000 - } + func processNotification(_ id: ChatId, _ ntf: NSENotificationData) async -> Void { + if let (_, nse) = rcvEntityThread(id), + nse.expectedMessages[id]?.shouldProcessNtf ?? false { + nse.processReceivedNtf(id, ntf, signalReady: true) } } private func rcvEntityThread(_ id: ChatId) -> (UUID, NotificationService)? { NSEThreads.queue.sync { - activeThreads.first(where: { (_, nse) in nse.receiveEntityId == id }) + // this selects the earliest thread that: + // 1) has this connection in nse.expectedMessages + // 2) has not completed processing messages for this connection (not ready) + activeThreads.first(where: { (_, nse) in nse.expectedMessages[id]?.ready == false }) } } @@ -106,29 +142,38 @@ class NSEThreads { } } +struct ExpectedMessage { + var ntfConn: UserNtfConn + var receiveConnId: String? + var expectedMsgId: String? + var allowedGetNextAttempts: Int + var msgBestAttemptNtf: NSENotificationData? + var ready: Bool + var shouldProcessNtf: Bool + var startedProcessingNewMsgs: Bool + var semaphore: DispatchSemaphore +} + // Notification service extension creates a new instance of the class and calls didReceive for each notification. // Each didReceive is called in its own thread, but multiple calls can be made in one process, and, empirically, there is never // more than one process of notification service extension exists at a time. // Soon after notification service delivers the last notification it is either suspended or terminated. class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? - var bestAttemptNtf: NSENotification? + // served as notification if no message attempts (msgBestAttemptNtf) could be produced + var serviceBestAttemptNtf: NSENotification? var badgeCount: Int = 0 // thread is added to allThreads here - if thread did not start chat, // chat does not need to be suspended but NSE state still needs to be set to "suspended". var threadId: UUID? = NSEThreads.shared.newThread() - var notificationInfo: NtfMessages? - var receiveEntityId: String? - var expectedMessage: String? - // return true if the message is taken - it prevents sending it to another NotificationService instance for processing - var shouldProcessNtf = false + var expectedMessages: Dictionary = [:] // key is receiveEntityId var appSubscriber: AppSubscriber? var returnedSuspension = false override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { logger.debug("DEBUGGING: NotificationService.didReceive") let ntf = if let ntf_ = request.content.mutableCopy() as? UNMutableNotificationContent { ntf_ } else { UNMutableNotificationContent() } - setBestAttemptNtf(ntf) + setServiceBestAttemptNtf(ntf) self.contentHandler = contentHandler registerGroupDefaults() let appState = appStateGroupDefault.get() @@ -136,13 +181,11 @@ class NotificationService: UNNotificationServiceExtension { switch appState { case .stopped: setBadgeCount() - setBestAttemptNtf(createAppStoppedNtf()) + setServiceBestAttemptNtf(createAppStoppedNtf(badgeCount)) deliverBestAttemptNtf() case .suspended: - setBadgeCount() receiveNtfMessages(request, contentHandler) case .suspending: - setBadgeCount() Task { let state: AppState = await withCheckedContinuation { cont in appSubscriber = appStateSubscriber { s in @@ -169,8 +212,9 @@ class NotificationService: UNNotificationServiceExtension { deliverBestAttemptNtf() } } - default: - deliverBestAttemptNtf() + case .active: contentHandler(UNMutableNotificationContent()) + case .activating: contentHandler(UNMutableNotificationContent()) + case .bgRefresh: contentHandler(UNMutableNotificationContent()) } } @@ -190,62 +234,165 @@ class NotificationService: UNNotificationServiceExtension { if let t = threadId { NSEThreads.shared.startThread(t, self) } let dbStatus = startChat() if case .ok = dbStatus, - let ntfInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) { - logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfInfo.ntfMessage_ == nil ? 0 : 1))") - if let connEntity = ntfInfo.connEntity_ { - setBestAttemptNtf( - ntfInfo.ntfsEnabled - ? .nse(createConnectionEventNtf(ntfInfo.user, connEntity)) - : .empty - ) - if let id = connEntity.id, ntfInfo.msgTs != nil { - notificationInfo = ntfInfo - receiveEntityId = id - expectedMessage = ntfInfo.ntfMessage_.flatMap { $0.msgId } - shouldProcessNtf = true - return + let ntfConns = apiGetNtfConns(nonce: nonce, encNtfInfo: encNtfInfo) { + logger.debug("NotificationService: receiveNtfMessages: apiGetNtfConns ntfConns count = \(ntfConns.count)") + + for ntfConn in ntfConns { + addExpectedMessage(ntfConn: ntfConn) + } + + let connIdsToGet = expectedMessages.compactMap { (id, _) in + let started = NSEThreads.queue.sync { + let canStart = checkCanStart(id) + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: can start: \(canStart)") } + if canStart { + processDroppedNotifications(id) + expectedMessages[id]?.startedProcessingNewMsgs = true + expectedMessages[id]?.shouldProcessNtf = true + } + return canStart + } + if started { + return expectedMessages[id]?.receiveConnId + } else { + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: entity \(id, privacy: .private) waiting on semaphore") } + expectedMessages[id]?.semaphore.wait() + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): receiveNtfMessages: entity \(id, privacy: .private) proceeding after semaphore") } + Task { + NSEThreads.queue.sync { + processDroppedNotifications(id) + expectedMessages[id]?.startedProcessingNewMsgs = true + expectedMessages[id]?.shouldProcessNtf = true + } + if let connId = expectedMessages[id]?.receiveConnId { + let _ = getConnNtfMessage(connId: connId) + } + } + return nil } } + + if !connIdsToGet.isEmpty { + if let r = apiGetConnNtfMessages(connIds: connIdsToGet) { + logger.debug("NotificationService: receiveNtfMessages: apiGetConnNtfMessages count = \(r.count)") + } + return + } } else if let dbStatus = dbStatus { - setBestAttemptNtf(createErrorNtf(dbStatus)) + setServiceBestAttemptNtf(createErrorNtf(dbStatus, badgeCount)) } } deliverBestAttemptNtf() } + func addExpectedMessage(ntfConn: UserNtfConn) { + if let connEntity = ntfConn.connEntity_, + let receiveEntityId = connEntity.id, ntfConn.expectedMsg_ != nil { + let expectedMsgId = ntfConn.expectedMsg_?.msgId + logger.debug("NotificationService: addExpectedMessage: expectedMsgId = \(expectedMsgId ?? "nil", privacy: .private)") + expectedMessages[receiveEntityId] = ExpectedMessage( + ntfConn: ntfConn, + receiveConnId: connEntity.conn.agentConnId, + expectedMsgId: expectedMsgId, + allowedGetNextAttempts: 3, + msgBestAttemptNtf: ntfConn.defaultBestAttemptNtf, + ready: false, + shouldProcessNtf: false, + startedProcessingNewMsgs: false, + semaphore: DispatchSemaphore(value: 0) + ) + } + } + + func checkCanStart(_ entityId: String) -> Bool { + return !NSEThreads.shared.activeThreads.contains(where: { + (tId, nse) in tId != threadId && nse.expectedMessages.contains(where: { $0.key == entityId }) + }) + } + + func processDroppedNotifications(_ entityId: String) { + if !NSEThreads.shared.droppedNotifications.isEmpty { + let messagesToProcess = NSEThreads.shared.droppedNotifications.filter { (eId, _) in eId == entityId } + NSEThreads.shared.droppedNotifications.removeAll(where: { (eId, _) in eId == entityId }) + for (index, (_, ntf)) in messagesToProcess.enumerated() { + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entity \(entityId, privacy: .private): processing dropped notification \(index, privacy: .private)") } + processReceivedNtf(entityId, ntf, signalReady: false) + } + } + } + override func serviceExtensionTimeWillExpire() { logger.debug("DEBUGGING: NotificationService.serviceExtensionTimeWillExpire") deliverBestAttemptNtf(urgent: true) } - func processReceivedNtf(_ ntf: NSENotification) -> Bool { - guard let ntfInfo = notificationInfo, let msgTs = ntfInfo.msgTs else { return false } - if !ntfInfo.user.showNotifications { - self.setBestAttemptNtf(.empty) + var expectingMoreMessages: Bool { + !expectedMessages.allSatisfy { $0.value.ready } + } + + func processReceivedNtf(_ id: ChatId, _ ntf: NSENotificationData, signalReady: Bool) { + guard let expectedMessage = expectedMessages[id] else { + return + } + guard let expectedMsgTs = expectedMessage.ntfConn.expectedMsg_?.msgTs else { + NSEThreads.shared.droppedNotifications.append((id, ntf)) + if signalReady { entityReady(id) } + return } if case let .msgInfo(info) = ntf { - if info.msgId == expectedMessage { - expectedMessage = nil - logger.debug("NotificationService processNtf: msgInfo") + if info.msgId == expectedMessage.expectedMsgId { + logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): expected") + expectedMessages[id]?.expectedMsgId = nil + if signalReady { entityReady(id) } self.deliverBestAttemptNtf() - return true - } else if info.msgTs > msgTs { - logger.debug("NotificationService processNtf: unexpected msgInfo, let other instance to process it, stopping this one") + } else if let msgTs = info.msgTs_, msgTs > expectedMsgTs { + logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, let other instance to process it, stopping this one") + NSEThreads.shared.droppedNotifications.append((id, ntf)) + if signalReady { entityReady(id) } self.deliverBestAttemptNtf() - return false + } else if (expectedMessages[id]?.allowedGetNextAttempts ?? 0) > 0, let receiveConnId = expectedMessages[id]?.receiveConnId { + logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unexpected msgInfo, get next message") + expectedMessages[id]?.allowedGetNextAttempts -= 1 + if let receivedMsg = getConnNtfMessage(connId: receiveConnId) { + logger.debug("NotificationService processNtf, on getConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private), receivedMsg msgId = \(receivedMsg.msgId, privacy: .private)") + } else { + logger.debug("NotificationService processNtf, on getConnNtfMessage: msgInfo msgId = \(info.msgId, privacy: .private): no next message, deliver best attempt") + NSEThreads.shared.droppedNotifications.append((id, ntf)) + if signalReady { entityReady(id) } + self.deliverBestAttemptNtf() + } } else { - logger.debug("NotificationService processNtf: unknown message, let other instance to process it") - return false - } - } else if ntfInfo.user.showNotifications { - logger.debug("NotificationService processNtf: setting best attempt") - self.setBestAttemptNtf(ntf) - if ntf.isCallInvitation { + logger.debug("NotificationService processNtf: msgInfo msgId = \(info.msgId, privacy: .private): unknown message, let other instance to process it") + NSEThreads.shared.droppedNotifications.append((id, ntf)) + if signalReady { entityReady(id) } self.deliverBestAttemptNtf() } - return true + } else if expectedMessage.ntfConn.user.showNotifications { + logger.debug("NotificationService processNtf: setting best attempt") + if ntf.notificationEvent != nil { + setBadgeCount() + } + let prevBestAttempt = expectedMessages[id]?.msgBestAttemptNtf + if prevBestAttempt?.callInvitation != nil { + if ntf.callInvitation != nil { // replace with newer call + expectedMessages[id]?.msgBestAttemptNtf = ntf + } // otherwise keep call as best attempt + } else { + expectedMessages[id]?.msgBestAttemptNtf = ntf + } + } else { + NSEThreads.shared.droppedNotifications.append((id, ntf)) + if signalReady { entityReady(id) } + } + } + + func entityReady(_ entityId: ChatId) { + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entityReady: entity \(entityId, privacy: .private)") } + expectedMessages[entityId]?.ready = true + if let (tNext, nse) = NSEThreads.shared.activeThreads.first(where: { (_, nse) in nse.expectedMessages[entityId]?.startedProcessingNewMsgs == false }) { + if let t = threadId { logger.debug("NotificationService thread \(t, privacy: .private): entityReady: signal next thread \(tNext, privacy: .private) for entity \(entityId, privacy: .private)") } + nse.expectedMessages[entityId]?.semaphore.signal() } - return false } func setBadgeCount() { @@ -253,37 +400,32 @@ class NotificationService: UNNotificationServiceExtension { ntfBadgeCountGroupDefault.set(badgeCount) } - func setBestAttemptNtf(_ ntf: UNMutableNotificationContent) { - setBestAttemptNtf(.nse(ntf)) - } - - func setBestAttemptNtf(_ ntf: NSENotification) { - logger.debug("NotificationService.setBestAttemptNtf") - if case let .nse(notification) = ntf { - notification.badge = badgeCount as NSNumber - bestAttemptNtf = .nse(notification) - } else { - bestAttemptNtf = ntf - } + func setServiceBestAttemptNtf(_ ntf: UNMutableNotificationContent) { + logger.debug("NotificationService.setServiceBestAttemptNtf") + serviceBestAttemptNtf = .nse(ntf) } private func deliverBestAttemptNtf(urgent: Bool = false) { - logger.debug("NotificationService.deliverBestAttemptNtf") - // stop processing other messages - shouldProcessNtf = false + if (urgent || !expectingMoreMessages) { + logger.debug("NotificationService.deliverBestAttemptNtf") + // stop processing other messages + for (key, _) in expectedMessages { + expectedMessages[key]?.shouldProcessNtf = false + } - let suspend: Bool - if let t = threadId { - threadId = nil - suspend = NSEThreads.shared.endThread(t) && NSEThreads.shared.noThreads - } else { - suspend = false + let suspend: Bool + if let t = threadId { + threadId = nil + suspend = NSEThreads.shared.endThread(t) && NSEThreads.shared.noThreads + } else { + suspend = false + } + deliverCallkitOrNotification(urgent: urgent, suspend: suspend) } - deliverCallkitOrNotification(urgent: urgent, suspend: suspend) } private func deliverCallkitOrNotification(urgent: Bool, suspend: Bool = false) { - if case .callkit = bestAttemptNtf { + if useCallKit() && expectedMessages.contains(where: { $0.value.msgBestAttemptNtf?.callInvitation != nil }) { logger.debug("NotificationService.deliverCallkitOrNotification: will suspend, callkit") if urgent { // suspending NSE even though there may be other notifications @@ -321,34 +463,102 @@ class NotificationService: UNNotificationServiceExtension { } private func deliverNotification() { - if let handler = contentHandler, let ntf = bestAttemptNtf { + if let handler = contentHandler, let ntf = prepareNotification() { contentHandler = nil - bestAttemptNtf = nil - let deliver: (UNMutableNotificationContent?) -> Void = { ntf in - let useNtf = if let ntf = ntf { - appStateGroupDefault.get().running ? UNMutableNotificationContent() : ntf - } else { - UNMutableNotificationContent() - } - handler(useNtf) - } + serviceBestAttemptNtf = nil switch ntf { - case let .nse(content): deliver(content) + case let .nse(content): + content.badge = badgeCount as NSNumber + handler(content) case let .callkit(invitation): logger.debug("NotificationService reportNewIncomingVoIPPushPayload for \(invitation.contact.id)") CXProvider.reportNewIncomingVoIPPushPayload([ "displayName": invitation.contact.displayName, "contactId": invitation.contact.id, - "media": invitation.callType.media.rawValue + "callUUID": invitation.callUUID ?? "", + "media": invitation.callType.media.rawValue, + "callTs": invitation.callTs.timeIntervalSince1970 ]) { error in logger.debug("reportNewIncomingVoIPPushPayload result: \(error)") - deliver(error == nil ? nil : createCallInvitationNtf(invitation)) + handler(error == nil ? UNMutableNotificationContent() : createCallInvitationNtf(invitation, self.badgeCount)) } - case .empty: deliver(nil) // used to mute notifications that did not unsubscribe yet - case .msgInfo: deliver(nil) // unreachable, the best attempt is never set to msgInfo + case .empty: + handler(UNMutableNotificationContent()) // used to mute notifications that did not unsubscribe yet } } } + + private func prepareNotification() -> NSENotification? { + if expectedMessages.isEmpty { + return serviceBestAttemptNtf + } else if let callNtfKV = expectedMessages.first(where: { $0.value.msgBestAttemptNtf?.callInvitation != nil }), + let callInv = callNtfKV.value.msgBestAttemptNtf?.callInvitation, + let callNtf = callNtfKV.value.msgBestAttemptNtf { + return useCallKit() ? .callkit(callInv) : .nse(callNtf.notificationContent(badgeCount)) + } else { + let ntfEvents = expectedMessages.compactMap { $0.value.msgBestAttemptNtf?.notificationEvent } + if ntfEvents.isEmpty { + return .empty + } else if let ntfEvent = ntfEvents.count == 1 ? ntfEvents.first : nil { + return .nse(ntfEvent.notificationContent(badgeCount)) + } else { + return .nse(createJointNtf(ntfEvents)) + } + } + } + + private func createJointNtf(_ ntfEvents: [NSENotificationData]) -> UNMutableNotificationContent { + let previewMode = ntfPreviewModeGroupDefault.get() + let newMsgsData: [(any UserLike, ChatInfo)] = ntfEvents.compactMap { $0.newMsgData } + if !newMsgsData.isEmpty, let userId = newMsgsData.first?.0.userId { + let newMsgsChats: [ChatInfo] = newMsgsData.map { $0.1 } + let uniqueChatsNames = uniqueNewMsgsChatsNames(newMsgsChats) + var body: String + if previewMode == .hidden { + body = String.localizedStringWithFormat(NSLocalizedString("New messages in %d chats", comment: "notification body"), uniqueChatsNames.count) + } else { + body = String.localizedStringWithFormat(NSLocalizedString("From: %@", comment: "notification body"), newMsgsChatsNamesStr(uniqueChatsNames)) + } + return createNotification( + categoryIdentifier: ntfCategoryManyEvents, + title: NSLocalizedString("New messages", comment: "notification"), + body: body, + userInfo: ["userId": userId], + badgeCount: badgeCount + ) + } else { + return createNotification( + categoryIdentifier: ntfCategoryManyEvents, + title: NSLocalizedString("New events", comment: "notification"), + body: String.localizedStringWithFormat(NSLocalizedString("%d new events", comment: "notification body"), ntfEvents.count), + badgeCount: badgeCount + ) + } + } + + private func uniqueNewMsgsChatsNames(_ newMsgsChats: [ChatInfo]) -> [String] { + var seenChatIds = Set() + var uniqueChatsNames: [String] = [] + for chat in newMsgsChats { + if !seenChatIds.contains(chat.id) { + seenChatIds.insert(chat.id) + uniqueChatsNames.append(chat.chatViewName) + } + } + return uniqueChatsNames + } + + private func newMsgsChatsNamesStr(_ names: [String]) -> String { + return switch names.count { + case 1: names[0] + case 2: "\(names[0]) and \(names[1])" + case 3: "\(names[0] + ", " + names[1]) and \(names[2])" + default: + names.count > 3 + ? "\(names[0]), \(names[1]) and \(names.count - 2) other chats" + : "" + } + } } // nseStateGroupDefault must not be used in NSE directly, only via this singleton @@ -562,26 +772,28 @@ func chatRecvMsg() async -> ChatResponse? { private let isInChina = SKStorefront().countryCode == "CHN" private func useCallKit() -> Bool { !isInChina && callKitEnabledGroupDefault.get() } -func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? { +func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotificationData)? { logger.debug("NotificationService receivedMsgNtf: \(res.responseType)") switch res { case let .contactConnected(user, contact, _): - return (contact.id, .nse(createContactConnectedNtf(user, contact))) + return (contact.id, .contactConnected(user, contact)) // case let .contactConnecting(contact): // TODO profile update case let .receivedContactRequest(user, contactRequest): - return (UserContact(contactRequest: contactRequest).id, .nse(createContactRequestNtf(user, contactRequest))) - case let .newChatItem(user, aChatItem): - let cInfo = aChatItem.chatInfo - var cItem = aChatItem.chatItem - if !cInfo.ntfsEnabled { - ntfBadgeCountGroupDefault.set(max(0, ntfBadgeCountGroupDefault.get() - 1)) + return (UserContact(contactRequest: contactRequest).id, .contactRequest(user, contactRequest)) + case let .newChatItems(user, chatItems): + // Received items are created one at a time + if let chatItem = chatItems.first { + let cInfo = chatItem.chatInfo + var cItem = chatItem.chatItem + if let file = cItem.autoReceiveFile() { + cItem = autoReceiveFile(file) ?? cItem + } + let ntf: NSENotificationData = (cInfo.ntfsEnabled && cItem.showNotification) ? .messageReceived(user, cInfo, cItem) : .noNtf + return (chatItem.chatId, ntf) + } else { + return nil } - if let file = cItem.autoReceiveFile() { - cItem = autoReceiveFile(file) ?? cItem - } - let ntf: NSENotification = cInfo.ntfsEnabled ? .nse(createMessageReceivedNtf(user, cInfo, cItem)) : .empty - return cItem.showNotification ? (aChatItem.chatId, ntf) : nil case let .rcvFileSndCancelled(_, aChatItem, _): cleanupFile(aChatItem) return nil @@ -595,10 +807,7 @@ func receivedMsgNtf(_ res: ChatResponse) async -> (String, NSENotification)? { return nil case let .callInvitation(invitation): // Do not post it without CallKit support, iOS will stop launching the app without showing CallKit - return ( - invitation.contact.id, - useCallKit() ? .callkit(invitation) : .nse(createCallInvitationNtf(invitation)) - ) + return (invitation.contact.id, .callInvitation(invitation)) case let .ntfMessage(_, connEntity, ntfMessage): return if let id = connEntity.id { (id, .msgInfo(ntfMessage)) } else { nil } case .chatSuspended: @@ -679,15 +888,15 @@ func apiSetEncryptLocalFiles(_ enable: Bool) throws { throw r } -func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? { +func apiGetNtfConns(nonce: String, encNtfInfo: String) -> [UserNtfConn]? { guard apiGetActiveUser() != nil else { logger.debug("no active user") return nil } - let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo)) - if case let .ntfMessages(user, connEntity_, msgTs, ntfMessage_) = r, let user = user { - logger.debug("apiGetNtfMessage response ntfMessages: \(ntfMessage_ == nil ? 0 : 1)") - return NtfMessages(user: user, connEntity_: connEntity_, msgTs: msgTs, ntfMessage_: ntfMessage_) + let r = sendSimpleXCmd(.apiGetNtfConns(nonce: nonce, encNtfInfo: encNtfInfo)) + if case let .ntfConns(ntfConns) = r { + logger.debug("apiGetNtfConns response ntfConns: \(ntfConns.count)") + return ntfConns.compactMap { toUserNtfConn($0) } } else if case let .chatCmdError(_, error) = r { logger.debug("apiGetNtfMessage error response: \(String.init(describing: error))") } else { @@ -696,6 +905,36 @@ func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? { return nil } +func toUserNtfConn(_ ntfConn: NtfConn) -> UserNtfConn? { + if let user = ntfConn.user_ { + return UserNtfConn(user: user, connEntity_: ntfConn.connEntity_, expectedMsg_: ntfConn.expectedMsg_) + } else { + return nil + } +} + +func apiGetConnNtfMessages(connIds: [String]) -> [NtfMsgInfo?]? { + guard apiGetActiveUser() != nil else { + logger.debug("no active user") + return nil + } + let r = sendSimpleXCmd(.apiGetConnNtfMessages(connIds: connIds)) + if case let .connNtfMessages(receivedMsgs) = r { + logger.debug("apiGetConnNtfMessages response receivedMsgs: \(receivedMsgs.count)") + return receivedMsgs + } + logger.debug("apiGetConnNtfMessages error: \(responseError(r))") + return nil +} + +func getConnNtfMessage(connId: String) -> NtfMsgInfo? { + let r_ = apiGetConnNtfMessages(connIds: [connId]) + if let r = r_, let receivedMsg = r.count == 1 ? r.first : nil { + return receivedMsg + } + return nil +} + func apiReceiveFile(fileId: Int64, encrypted: Bool, inline: Bool? = nil) -> AChatItem? { let userApprovedRelays = !privacyAskToApproveRelaysGroupDefault.get() let r = sendSimpleXCmd(.receiveFile(fileId: fileId, userApprovedRelays: userApprovedRelays, encrypted: encrypted, inline: inline)) @@ -730,13 +969,33 @@ func setNetworkConfig(_ cfg: NetCfg) throws { throw r } -struct NtfMessages { +struct UserNtfConn { var user: User var connEntity_: ConnectionEntity? - var msgTs: Date? - var ntfMessage_: NtfMsgInfo? + var expectedMsg_: NtfMsgInfo? - var ntfsEnabled: Bool { - user.showNotifications && (connEntity_?.ntfsEnabled ?? false) + var defaultBestAttemptNtf: NSENotificationData { + return if !user.showNotifications { + .noNtf + } else if let connEntity = connEntity_ { + switch connEntity { + case let .rcvDirectMsgConnection(_, contact): + contact?.chatSettings.enableNtfs == .all + ? .connectionEvent(user, connEntity) + : .noNtf + case let .rcvGroupMsgConnection(_, groupInfo, _): + groupInfo.chatSettings.enableNtfs == .all + ? .connectionEvent(user, connEntity) + : .noNtf + case .sndFileConnection: .noNtf + case .rcvFileConnection: .noNtf + case let .userContactConnection(_, userContact): + userContact.groupId == nil + ? .connectionEvent(user, connEntity) + : .noNtf + } + } else { + .noNtf + } } } diff --git a/apps/ios/SimpleX NSE/de.lproj/Localizable.strings b/apps/ios/SimpleX NSE/de.lproj/Localizable.strings index 5ef592ec70..f9779c6e05 100644 --- a/apps/ios/SimpleX NSE/de.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/de.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d neue Ereignisse"; + +/* notification body */ +"From: %@" = "Von: %@"; + +/* notification */ +"New events" = "Neue Ereignisse"; + +/* notification */ +"New messages" = "Neue Nachrichten"; + +/* notification body */ +"New messages in %d chats" = "Neue Nachrichten in %d Chats"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/es.lproj/Localizable.strings b/apps/ios/SimpleX NSE/es.lproj/Localizable.strings index 5ef592ec70..fb190400e1 100644 --- a/apps/ios/SimpleX NSE/es.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/es.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d evento(s) nuevo(s)"; + +/* notification body */ +"From: %@" = "De: %@"; + +/* notification */ +"New events" = "Eventos nuevos"; + +/* notification */ +"New messages" = "Mensajes nuevos"; + +/* notification body */ +"New messages in %d chats" = "Mensajes nuevos en %d chat(s)"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/hu.lproj/Localizable.strings b/apps/ios/SimpleX NSE/hu.lproj/Localizable.strings index 5ef592ec70..e64c98df9e 100644 --- a/apps/ios/SimpleX NSE/hu.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/hu.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d új esemény"; + +/* notification body */ +"From: %@" = "Tőle: %@"; + +/* notification */ +"New events" = "Új események"; + +/* notification */ +"New messages" = "Új üzenetek"; + +/* notification body */ +"New messages in %d chats" = "Új üzenetek %d csevegésben"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/it.lproj/Localizable.strings b/apps/ios/SimpleX NSE/it.lproj/Localizable.strings index 5ef592ec70..31f463eb5b 100644 --- a/apps/ios/SimpleX NSE/it.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/it.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d nuovi eventi"; + +/* notification body */ +"From: %@" = "Da: %@"; + +/* notification */ +"New events" = "Nuovi eventi"; + +/* notification */ +"New messages" = "Nuovi messaggi"; + +/* notification body */ +"New messages in %d chats" = "Nuovi messaggi in %d chat"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/nl.lproj/Localizable.strings b/apps/ios/SimpleX NSE/nl.lproj/Localizable.strings index 5ef592ec70..4cf91689b5 100644 --- a/apps/ios/SimpleX NSE/nl.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/nl.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "‐%d nieuwe gebeurtenissen"; + +/* notification body */ +"From: %@" = "Van: %@"; + +/* notification */ +"New events" = "Nieuwe gebeurtenissen"; + +/* notification */ +"New messages" = "Nieuwe berichten"; + +/* notification body */ +"New messages in %d chats" = "Nieuwe berichten in %d chats"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/ru.lproj/Localizable.strings b/apps/ios/SimpleX NSE/ru.lproj/Localizable.strings index 5ef592ec70..6ba39ccc63 100644 --- a/apps/ios/SimpleX NSE/ru.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/ru.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d новых сообщений"; + +/* notification body */ +"From: %@" = "От: %@"; + +/* notification */ +"New events" = "Новые события"; + +/* notification */ +"New messages" = "Новые сообщения"; + +/* notification body */ +"New messages in %d chats" = "Новые сообщения в %d разговоре(ах)"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX NSE/uk.lproj/Localizable.strings b/apps/ios/SimpleX NSE/uk.lproj/Localizable.strings index 5ef592ec70..69cc53bff1 100644 --- a/apps/ios/SimpleX NSE/uk.lproj/Localizable.strings +++ b/apps/ios/SimpleX NSE/uk.lproj/Localizable.strings @@ -1,7 +1,15 @@ -/* - Localizable.strings - SimpleX +/* notification body */ +"%d new events" = "%d нових подій"; + +/* notification body */ +"From: %@" = "Від: %@"; + +/* notification */ +"New events" = "Нові події"; + +/* notification */ +"New messages" = "Нові повідомлення"; + +/* notification body */ +"New messages in %d chats" = "Нові повідомлення в чатах %d"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/ShareAPI.swift b/apps/ios/SimpleX SE/ShareAPI.swift index 47e072ae78..fcb78c64b1 100644 --- a/apps/ios/SimpleX SE/ShareAPI.swift +++ b/apps/ios/SimpleX SE/ShareAPI.swift @@ -54,32 +54,30 @@ func apiGetChats(userId: User.ID) throws -> Array { throw r } -func apiSendMessage( +func apiSendMessages( chatInfo: ChatInfo, - cryptoFile: CryptoFile?, - msgContent: MsgContent -) throws -> AChatItem { + composedMessages: [ComposedMessage] +) throws -> [AChatItem] { let r = sendSimpleXCmd( chatInfo.chatType == .local - ? .apiCreateChatItem( + ? .apiCreateChatItems( noteFolderId: chatInfo.apiId, - file: cryptoFile, - msg: msgContent + composedMessages: composedMessages ) - : .apiSendMessage( + : .apiSendMessages( type: chatInfo.chatType, id: chatInfo.apiId, - file: cryptoFile, - quotedItemId: nil, - msg: msgContent, live: false, - ttl: nil + ttl: nil, + composedMessages: composedMessages ) ) - if case let .newChatItem(_, chatItem) = r { - return chatItem + if case let .newChatItems(_, chatItems) = r { + return chatItems } else { - if let filePath = cryptoFile?.filePath { removeFile(filePath) } + for composedMessage in composedMessages { + if let filePath = composedMessage.fileSource?.filePath { removeFile(filePath) } + } throw r } } diff --git a/apps/ios/SimpleX SE/ShareModel.swift b/apps/ios/SimpleX SE/ShareModel.swift index 5bda361126..21908026b2 100644 --- a/apps/ios/SimpleX SE/ShareModel.swift +++ b/apps/ios/SimpleX SE/ShareModel.swift @@ -104,7 +104,7 @@ class ShareModel: ObservableObject { // Decode base64 images on background thread let profileImages = chats.reduce(into: Dictionary()) { dict, chatData in if let profileImage = chatData.chatInfo.image, - let uiImage = UIImage(base64Encoded: profileImage) { + let uiImage = imageFromBase64(profileImage) { dict[chatData.id] = uiImage } } @@ -141,23 +141,25 @@ class ShareModel: ObservableObject { do { SEChatState.shared.set(.sendingMessage) await waitForOtherProcessesToSuspend() - let ci = try apiSendMessage( + let chatItems = try apiSendMessages( chatInfo: selected.chatInfo, - cryptoFile: sharedContent.cryptoFile, - msgContent: sharedContent.msgContent(comment: self.comment) + composedMessages: [ComposedMessage(fileSource: sharedContent.cryptoFile, msgContent: sharedContent.msgContent(comment: self.comment))] ) if selected.chatInfo.chatType == .local { completion() } else { - await MainActor.run { self.bottomBar = .loadingBar(progress: 0) } - if let e = await handleEvents( - isGroupChat: ci.chatInfo.chatType == .group, - isWithoutFile: sharedContent.cryptoFile == nil, - chatItemId: ci.chatItem.id - ) { - await MainActor.run { errorAlert = e } - } else { - completion() + // TODO batch send: share multiple items + if let ci = chatItems.first { + await MainActor.run { self.bottomBar = .loadingBar(progress: 0) } + if let e = await handleEvents( + isGroupChat: ci.chatInfo.chatType == .group, + isWithoutFile: sharedContent.cryptoFile == nil, + chatItemId: ci.chatItem.id + ) { + await MainActor.run { errorAlert = e } + } else { + completion() + } } } } catch { @@ -318,7 +320,8 @@ class ShareModel: ObservableObject { } await ch.completeFile() if await !ch.isRunning { break } - case let .chatItemStatusUpdated(_, ci): + case let .chatItemsStatusesUpdated(_, chatItems): + guard let ci = chatItems.last else { continue } guard isMessage(for: ci) else { continue } if let (title, message) = ci.chatItem.meta.itemStatus.statusInfo { // `title` and `message` already localized and interpolated @@ -414,7 +417,7 @@ fileprivate func getSharedContent(_ ip: NSItemProvider) async -> Result Result Result some View { - if let img = UIImage(base64Encoded: img) { + @ViewBuilder private func imagePreview(_ imgStr: String) -> some View { + if let img = imageFromBase64(imgStr) { previewArea { Image(uiImage: img) .resizable() @@ -160,6 +160,29 @@ struct ShareView: View { } } + @ViewBuilder private func linkPreview(_ linkPreview: LinkPreview) -> some View { + previewArea { + HStack(alignment: .center, spacing: 8) { + if let uiImage = imageFromBase64(linkPreview.image) { + Image(uiImage: uiImage) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(maxWidth: 80, maxHeight: 60) + } + VStack(alignment: .center, spacing: 4) { + Text(linkPreview.title) + .lineLimit(1) + Text(linkPreview.uri.absoluteString) + .font(.caption) + .lineLimit(1) + .foregroundColor(.secondary) + } + .padding(.vertical, 5) + .frame(maxWidth: .infinity, minHeight: 60) + } + } + } + @ViewBuilder private func previewArea(@ViewBuilder content: @escaping () -> V) -> some View { HStack(alignment: .center, spacing: 8) { content() diff --git a/apps/ios/SimpleX SE/es.lproj/Localizable.strings b/apps/ios/SimpleX SE/es.lproj/Localizable.strings index 5ecdd410df..4cc5029537 100644 --- a/apps/ios/SimpleX SE/es.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/es.lproj/Localizable.strings @@ -29,7 +29,7 @@ "Database error" = "Error en base de datos"; /* No comment provided by engineer. */ -"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es distinta a la almacenada en keychain."; +"Database passphrase is different from saved in the keychain." = "La contraseña de la base de datos es diferente a la almacenada en keychain."; /* No comment provided by engineer. */ "Database passphrase is required to open chat." = "Se requiere la contraseña de la base de datos para abrir la aplicación."; diff --git a/apps/ios/SimpleX SE/fr.lproj/Localizable.strings b/apps/ios/SimpleX SE/fr.lproj/Localizable.strings index 41dda79fbd..46a458b471 100644 --- a/apps/ios/SimpleX SE/fr.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/fr.lproj/Localizable.strings @@ -82,15 +82,27 @@ /* No comment provided by engineer. */ "Selected chat preferences prohibit this message." = "Les paramètres de chat sélectionnés ne permettent pas l'envoi de ce message."; +/* No comment provided by engineer. */ +"Sending a message takes longer than expected." = "L'envoi d'un message prend plus de temps que prévu."; + +/* No comment provided by engineer. */ +"Sending message…" = "Envoi du message…"; + /* No comment provided by engineer. */ "Share" = "Partager"; +/* No comment provided by engineer. */ +"Slow network?" = "Réseau lent ?"; + /* No comment provided by engineer. */ "Unknown database error: %@" = "Erreur inconnue de la base de données : %@"; /* No comment provided by engineer. */ "Unsupported format" = "Format non pris en charge"; +/* No comment provided by engineer. */ +"Wait" = "Attendez"; + /* No comment provided by engineer. */ "Wrong database passphrase" = "Mauvaise phrase secrète pour la base de données"; diff --git a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings index 8ce4317a9b..94f18db853 100644 --- a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings @@ -17,7 +17,7 @@ "Comment" = "Hozzászólás"; /* No comment provided by engineer. */ -"Currently maximum supported file size is %@." = "Jelenleg a maximális támogatott fájlméret %@."; +"Currently maximum supported file size is %@." = "Jelenleg a maximálisan támogatott fájlméret: %@."; /* No comment provided by engineer. */ "Database downgrade required" = "Adatbázis visszafejlesztése szükséges"; @@ -26,13 +26,13 @@ "Database encrypted!" = "Adatbázis titkosítva!"; /* No comment provided by engineer. */ -"Database error" = "Adatbázis hiba"; +"Database error" = "Adatbázishiba"; /* No comment provided by engineer. */ "Database passphrase is different from saved in the keychain." = "Az adatbázis jelmondata eltér a kulcstartóban lévőtől."; /* No comment provided by engineer. */ -"Database passphrase is required to open chat." = "Adatbázis jelmondat szükséges a csevegés megnyitásához."; +"Database passphrase is required to open chat." = "Adatbázis-jelmondat szükséges a csevegés megnyitásához."; /* No comment provided by engineer. */ "Database upgrade required" = "Adatbázis fejlesztése szükséges"; @@ -50,13 +50,13 @@ "File error" = "Fájlhiba"; /* No comment provided by engineer. */ -"Incompatible database version" = "Nem kompatibilis adatbázis verzió"; +"Incompatible database version" = "Nem kompatibilis adatbázis-verzió"; /* No comment provided by engineer. */ "Invalid migration confirmation" = "Érvénytelen átköltöztetési visszaigazolás"; /* No comment provided by engineer. */ -"Keychain error" = "Kulcstartó hiba"; +"Keychain error" = "Kulcstartóhiba"; /* No comment provided by engineer. */ "Large file!" = "Nagy fájl!"; @@ -95,7 +95,7 @@ "Slow network?" = "Lassú internetkapcsolat?"; /* No comment provided by engineer. */ -"Unknown database error: %@" = "Ismeretlen adatbázis hiba: %@"; +"Unknown database error: %@" = "Ismeretlen adatbázishiba: %@"; /* No comment provided by engineer. */ "Unsupported format" = "Nem támogatott formátum"; @@ -104,8 +104,8 @@ "Wait" = "Várjon"; /* No comment provided by engineer. */ -"Wrong database passphrase" = "Hibás adatbázis jelmondat"; +"Wrong database passphrase" = "Hibás adatbázis-jelmondat"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX zár menüben engedélyezheti."; +"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti."; diff --git a/apps/ios/SimpleX SE/nl.lproj/Localizable.strings b/apps/ios/SimpleX SE/nl.lproj/Localizable.strings index 8412c88ea6..e5d2487b54 100644 --- a/apps/ios/SimpleX SE/nl.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/nl.lproj/Localizable.strings @@ -32,7 +32,7 @@ "Database passphrase is different from saved in the keychain." = "Het wachtwoord van de database verschilt van het wachtwoord die in de keychain is opgeslagen."; /* No comment provided by engineer. */ -"Database passphrase is required to open chat." = "Database wachtwoord is vereist om je gesprekken te openen."; +"Database passphrase is required to open chat." = "Database wachtwoord is vereist om je chats te openen."; /* No comment provided by engineer. */ "Database upgrade required" = "Database upgrade vereist"; diff --git a/apps/ios/SimpleX SE/pl.lproj/InfoPlist.strings b/apps/ios/SimpleX SE/pl.lproj/InfoPlist.strings index 388ac01f7f..81283a3f02 100644 --- a/apps/ios/SimpleX SE/pl.lproj/InfoPlist.strings +++ b/apps/ios/SimpleX SE/pl.lproj/InfoPlist.strings @@ -1,7 +1,9 @@ -/* - InfoPlist.strings - SimpleX +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX SE"; + +/* Bundle name */ +"CFBundleName" = "SimpleX SE"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 SimpleX Chat. Wszelkie prawa zastrzeżone."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/pl.lproj/Localizable.strings b/apps/ios/SimpleX SE/pl.lproj/Localizable.strings index 5ef592ec70..c563431c28 100644 --- a/apps/ios/SimpleX SE/pl.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/pl.lproj/Localizable.strings @@ -1,7 +1,111 @@ -/* - Localizable.strings - SimpleX +/* No comment provided by engineer. */ +"%@" = "%@"; + +/* No comment provided by engineer. */ +"App is locked!" = "Aplikacja zablokowana!"; + +/* No comment provided by engineer. */ +"Cancel" = "Anuluj"; + +/* No comment provided by engineer. */ +"Cannot access keychain to save database password" = "Nie można uzyskać dostępu do pęku kluczy aby zapisać hasło do bazy danych"; + +/* No comment provided by engineer. */ +"Cannot forward message" = "Nie można przekazać wiadomości"; + +/* No comment provided by engineer. */ +"Comment" = "Komentarz"; + +/* No comment provided by engineer. */ +"Currently maximum supported file size is %@." = "Obecnie maksymalny obsługiwany rozmiar pliku to %@."; + +/* No comment provided by engineer. */ +"Database downgrade required" = "Wymagane obniżenie wersji bazy danych"; + +/* No comment provided by engineer. */ +"Database encrypted!" = "Baza danych zaszyfrowana!"; + +/* No comment provided by engineer. */ +"Database error" = "Błąd bazy danych"; + +/* No comment provided by engineer. */ +"Database passphrase is different from saved in the keychain." = "Hasło bazy danych jest inne niż zapisane w pęku kluczy."; + +/* No comment provided by engineer. */ +"Database passphrase is required to open chat." = "Hasło do bazy danych jest wymagane do otwarcia czatu."; + +/* No comment provided by engineer. */ +"Database upgrade required" = "Wymagana aktualizacja bazy danych"; + +/* No comment provided by engineer. */ +"Error preparing file" = "Błąd przygotowania pliku"; + +/* No comment provided by engineer. */ +"Error preparing message" = "Błąd przygotowania wiadomości"; + +/* No comment provided by engineer. */ +"Error: %@" = "Błąd: %@"; + +/* No comment provided by engineer. */ +"File error" = "Błąd pliku"; + +/* No comment provided by engineer. */ +"Incompatible database version" = "Niekompatybilna wersja bazy danych"; + +/* No comment provided by engineer. */ +"Invalid migration confirmation" = "Nieprawidłowe potwierdzenie migracji"; + +/* No comment provided by engineer. */ +"Keychain error" = "Błąd pęku kluczy"; + +/* No comment provided by engineer. */ +"Large file!" = "Duży plik!"; + +/* No comment provided by engineer. */ +"No active profile" = "Brak aktywnego profilu"; + +/* No comment provided by engineer. */ +"Ok" = "Ok"; + +/* No comment provided by engineer. */ +"Open the app to downgrade the database." = "Otwórz aplikację aby obniżyć wersję bazy danych."; + +/* No comment provided by engineer. */ +"Open the app to upgrade the database." = "Otwórz aplikację aby zaktualizować bazę danych."; + +/* No comment provided by engineer. */ +"Passphrase" = "Hasło"; + +/* No comment provided by engineer. */ +"Please create a profile in the SimpleX app" = "Proszę utworzyć profil w aplikacji SimpleX"; + +/* No comment provided by engineer. */ +"Selected chat preferences prohibit this message." = "Wybrane preferencje czatu zabraniają tej wiadomości."; + +/* No comment provided by engineer. */ +"Sending a message takes longer than expected." = "Wysłanie wiadomości trwa dłużej niż oczekiwano."; + +/* No comment provided by engineer. */ +"Sending message…" = "Wysyłanie wiadomości…"; + +/* No comment provided by engineer. */ +"Share" = "Udostępnij"; + +/* No comment provided by engineer. */ +"Slow network?" = "Wolna sieć?"; + +/* No comment provided by engineer. */ +"Unknown database error: %@" = "Nieznany błąd bazy danych: %@"; + +/* No comment provided by engineer. */ +"Unsupported format" = "Niewspierany format"; + +/* No comment provided by engineer. */ +"Wait" = "Czekaj"; + +/* No comment provided by engineer. */ +"Wrong database passphrase" = "Nieprawidłowe hasło bazy danych"; + +/* No comment provided by engineer. */ +"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Możesz zezwolić na udostępnianie w ustawieniach Prywatność i bezpieczeństwo / Blokada SimpleX."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/tr.lproj/InfoPlist.strings b/apps/ios/SimpleX SE/tr.lproj/InfoPlist.strings index 388ac01f7f..cf1ca31f53 100644 --- a/apps/ios/SimpleX SE/tr.lproj/InfoPlist.strings +++ b/apps/ios/SimpleX SE/tr.lproj/InfoPlist.strings @@ -1,7 +1,9 @@ -/* - InfoPlist.strings - SimpleX +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX SE"; + +/* Bundle name */ +"CFBundleName" = "SimpleX SE"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Telif Hakkı © 2024 SimpleX Chat. Tüm hakları saklıdır."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/tr.lproj/Localizable.strings b/apps/ios/SimpleX SE/tr.lproj/Localizable.strings index 5ef592ec70..baef71c127 100644 --- a/apps/ios/SimpleX SE/tr.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/tr.lproj/Localizable.strings @@ -1,7 +1,111 @@ -/* - Localizable.strings - SimpleX +/* No comment provided by engineer. */ +"%@" = "%@"; + +/* No comment provided by engineer. */ +"App is locked!" = "Uygulama kilitlendi!"; + +/* No comment provided by engineer. */ +"Cancel" = "İptal et"; + +/* No comment provided by engineer. */ +"Cannot access keychain to save database password" = "Veritabanı şifresini kaydetmek için Anahtar Zinciri'ne erişilemiyor"; + +/* No comment provided by engineer. */ +"Cannot forward message" = "Mesaj iletilemiyor"; + +/* No comment provided by engineer. */ +"Comment" = "Yorum"; + +/* No comment provided by engineer. */ +"Currently maximum supported file size is %@." = "Şu anki maksimum desteklenen dosya boyutu %@ kadardır."; + +/* No comment provided by engineer. */ +"Database downgrade required" = "Veritabanı sürüm düşürme gerekli"; + +/* No comment provided by engineer. */ +"Database encrypted!" = "Veritabanı şifrelendi!"; + +/* No comment provided by engineer. */ +"Database error" = "Veritabanı hatası"; + +/* No comment provided by engineer. */ +"Database passphrase is different from saved in the keychain." = "Veritabanı parolası Anahtar Zinciri'nde kayıtlı olandan farklıdır."; + +/* No comment provided by engineer. */ +"Database passphrase is required to open chat." = "Konuşmayı açmak için veri tabanı parolası gerekli."; + +/* No comment provided by engineer. */ +"Database upgrade required" = "Veritabanı yükseltmesi gerekli"; + +/* No comment provided by engineer. */ +"Error preparing file" = "Dosya hazırlanırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error preparing message" = "Mesaj hazırlanırken hata oluştu"; + +/* No comment provided by engineer. */ +"Error: %@" = "Hata: %@"; + +/* No comment provided by engineer. */ +"File error" = "Dosya hatası"; + +/* No comment provided by engineer. */ +"Incompatible database version" = "Uyumsuz veritabanı sürümü"; + +/* No comment provided by engineer. */ +"Invalid migration confirmation" = "Geçerli olmayan taşıma onayı"; + +/* No comment provided by engineer. */ +"Keychain error" = "Anahtarlık hatası"; + +/* No comment provided by engineer. */ +"Large file!" = "Büyük dosya!"; + +/* No comment provided by engineer. */ +"No active profile" = "Aktif profil yok"; + +/* No comment provided by engineer. */ +"Ok" = "Tamam"; + +/* No comment provided by engineer. */ +"Open the app to downgrade the database." = "Veritabanının sürümünü düşürmek için uygulamayı açın."; + +/* No comment provided by engineer. */ +"Open the app to upgrade the database." = "Veritabanını güncellemek için uygulamayı açın."; + +/* No comment provided by engineer. */ +"Passphrase" = "Parola"; + +/* No comment provided by engineer. */ +"Please create a profile in the SimpleX app" = "Lütfen SimpleX uygulamasında bir profil oluşturun"; + +/* No comment provided by engineer. */ +"Selected chat preferences prohibit this message." = "Seçilen sohbet tercihleri bu mesajı yasakladı."; + +/* No comment provided by engineer. */ +"Sending a message takes longer than expected." = "Mesaj göndermek beklenenden daha uzun sürüyor."; + +/* No comment provided by engineer. */ +"Sending message…" = "Mesaj gönderiliyor…"; + +/* No comment provided by engineer. */ +"Share" = "Paylaş"; + +/* No comment provided by engineer. */ +"Slow network?" = "Ağ yavaş mı?"; + +/* No comment provided by engineer. */ +"Unknown database error: %@" = "Bilinmeyen veritabanı hatası: %@"; + +/* No comment provided by engineer. */ +"Unsupported format" = "Desteklenmeyen format"; + +/* No comment provided by engineer. */ +"Wait" = "Bekleyin"; + +/* No comment provided by engineer. */ +"Wrong database passphrase" = "Yanlış veritabanı parolası"; + +/* No comment provided by engineer. */ +"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Gizlilik ve Güvenlik / SimpleX Lock ayarlarından paylaşıma izin verebilirsiniz."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/uk.lproj/InfoPlist.strings b/apps/ios/SimpleX SE/uk.lproj/InfoPlist.strings index 388ac01f7f..18c4d5e8a5 100644 --- a/apps/ios/SimpleX SE/uk.lproj/InfoPlist.strings +++ b/apps/ios/SimpleX SE/uk.lproj/InfoPlist.strings @@ -1,7 +1,9 @@ -/* - InfoPlist.strings - SimpleX +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX SE"; + +/* Bundle name */ +"CFBundleName" = "SimpleX SE"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 SimpleX Chat. Всі права захищені."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/uk.lproj/Localizable.strings b/apps/ios/SimpleX SE/uk.lproj/Localizable.strings index 5ef592ec70..a6da81185e 100644 --- a/apps/ios/SimpleX SE/uk.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/uk.lproj/Localizable.strings @@ -1,7 +1,111 @@ -/* - Localizable.strings - SimpleX +/* No comment provided by engineer. */ +"%@" = "%@"; + +/* No comment provided by engineer. */ +"App is locked!" = "Додаток заблоковано!"; + +/* No comment provided by engineer. */ +"Cancel" = "Скасувати"; + +/* No comment provided by engineer. */ +"Cannot access keychain to save database password" = "Не вдається отримати доступ до зв'язки ключів для збереження пароля до бази даних"; + +/* No comment provided by engineer. */ +"Cannot forward message" = "Неможливо переслати повідомлення"; + +/* No comment provided by engineer. */ +"Comment" = "Коментар"; + +/* No comment provided by engineer. */ +"Currently maximum supported file size is %@." = "Наразі максимальний підтримуваний розмір файлу - %@."; + +/* No comment provided by engineer. */ +"Database downgrade required" = "Потрібне оновлення бази даних"; + +/* No comment provided by engineer. */ +"Database encrypted!" = "База даних зашифрована!"; + +/* No comment provided by engineer. */ +"Database error" = "Помилка в базі даних"; + +/* No comment provided by engineer. */ +"Database passphrase is different from saved in the keychain." = "Парольна фраза бази даних відрізняється від збереженої у в’язці ключів."; + +/* No comment provided by engineer. */ +"Database passphrase is required to open chat." = "Для відкриття чату потрібно ввести пароль до бази даних."; + +/* No comment provided by engineer. */ +"Database upgrade required" = "Потрібне оновлення бази даних"; + +/* No comment provided by engineer. */ +"Error preparing file" = "Помилка підготовки файлу"; + +/* No comment provided by engineer. */ +"Error preparing message" = "Повідомлення про підготовку до помилки"; + +/* No comment provided by engineer. */ +"Error: %@" = "Помилка: %@"; + +/* No comment provided by engineer. */ +"File error" = "Помилка файлу"; + +/* No comment provided by engineer. */ +"Incompatible database version" = "Несумісна версія бази даних"; + +/* No comment provided by engineer. */ +"Invalid migration confirmation" = "Недійсне підтвердження міграції"; + +/* No comment provided by engineer. */ +"Keychain error" = "Помилка зв'язки ключів"; + +/* No comment provided by engineer. */ +"Large file!" = "Великий файл!"; + +/* No comment provided by engineer. */ +"No active profile" = "Немає активного профілю"; + +/* No comment provided by engineer. */ +"Ok" = "Гаразд"; + +/* No comment provided by engineer. */ +"Open the app to downgrade the database." = "Відкрийте програму, щоб знизити версію бази даних."; + +/* No comment provided by engineer. */ +"Open the app to upgrade the database." = "Відкрийте програму, щоб оновити базу даних."; + +/* No comment provided by engineer. */ +"Passphrase" = "Парольна фраза"; + +/* No comment provided by engineer. */ +"Please create a profile in the SimpleX app" = "Будь ласка, створіть профіль у додатку SimpleX"; + +/* No comment provided by engineer. */ +"Selected chat preferences prohibit this message." = "Вибрані налаштування чату забороняють це повідомлення."; + +/* No comment provided by engineer. */ +"Sending a message takes longer than expected." = "Надсилання повідомлення займає більше часу, ніж очікувалося."; + +/* No comment provided by engineer. */ +"Sending message…" = "Надсилаю повідомлення…"; + +/* No comment provided by engineer. */ +"Share" = "Поділіться"; + +/* No comment provided by engineer. */ +"Slow network?" = "Повільна мережа?"; + +/* No comment provided by engineer. */ +"Unknown database error: %@" = "Невідома помилка бази даних: %@"; + +/* No comment provided by engineer. */ +"Unsupported format" = "Непідтримуваний формат"; + +/* No comment provided by engineer. */ +"Wait" = "Зачекай"; + +/* No comment provided by engineer. */ +"Wrong database passphrase" = "Неправильна ключова фраза до бази даних"; + +/* No comment provided by engineer. */ +"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Ви можете дозволити спільний доступ у налаштуваннях Конфіденційність і безпека / SimpleX Lock."; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/zh-Hans.lproj/InfoPlist.strings b/apps/ios/SimpleX SE/zh-Hans.lproj/InfoPlist.strings index 388ac01f7f..760be62885 100644 --- a/apps/ios/SimpleX SE/zh-Hans.lproj/InfoPlist.strings +++ b/apps/ios/SimpleX SE/zh-Hans.lproj/InfoPlist.strings @@ -1,7 +1,9 @@ -/* - InfoPlist.strings - SimpleX +/* Bundle display name */ +"CFBundleDisplayName" = "SimpleX SE"; + +/* Bundle name */ +"CFBundleName" = "SimpleX SE"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "版权所有 © 2024 SimpleX Chat。保留所有权利。"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings b/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings index 5ef592ec70..362e2edb74 100644 --- a/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings @@ -1,7 +1,111 @@ -/* - Localizable.strings - SimpleX +/* No comment provided by engineer. */ +"%@" = "%@"; + +/* No comment provided by engineer. */ +"App is locked!" = "应用程序已锁定!"; + +/* No comment provided by engineer. */ +"Cancel" = "取消"; + +/* No comment provided by engineer. */ +"Cannot access keychain to save database password" = "无法访问钥匙串以保存数据库密码"; + +/* No comment provided by engineer. */ +"Cannot forward message" = "无法转发消息"; + +/* No comment provided by engineer. */ +"Comment" = "评论"; + +/* No comment provided by engineer. */ +"Currently maximum supported file size is %@." = "当前支持的最大文件大小为 %@。"; + +/* No comment provided by engineer. */ +"Database downgrade required" = "需要数据库降级"; + +/* No comment provided by engineer. */ +"Database encrypted!" = "数据库已加密!"; + +/* No comment provided by engineer. */ +"Database error" = "数据库错误"; + +/* No comment provided by engineer. */ +"Database passphrase is different from saved in the keychain." = "数据库密码与保存在钥匙串中的密码不同。"; + +/* No comment provided by engineer. */ +"Database passphrase is required to open chat." = "需要数据库密码才能打开聊天。"; + +/* No comment provided by engineer. */ +"Database upgrade required" = "需要升级数据库"; + +/* No comment provided by engineer. */ +"Error preparing file" = "准备文件时出错"; + +/* No comment provided by engineer. */ +"Error preparing message" = "准备消息时出错"; + +/* No comment provided by engineer. */ +"Error: %@" = "错误:%@"; + +/* No comment provided by engineer. */ +"File error" = "文件错误"; + +/* No comment provided by engineer. */ +"Incompatible database version" = "不兼容的数据库版本"; + +/* No comment provided by engineer. */ +"Invalid migration confirmation" = "无效的迁移确认"; + +/* No comment provided by engineer. */ +"Keychain error" = "钥匙串错误"; + +/* No comment provided by engineer. */ +"Large file!" = "大文件!"; + +/* No comment provided by engineer. */ +"No active profile" = "无活动配置文件"; + +/* No comment provided by engineer. */ +"Ok" = "好的"; + +/* No comment provided by engineer. */ +"Open the app to downgrade the database." = "打开应用程序以降级数据库。"; + +/* No comment provided by engineer. */ +"Open the app to upgrade the database." = "打开应用程序以升级数据库。"; + +/* No comment provided by engineer. */ +"Passphrase" = "密码"; + +/* No comment provided by engineer. */ +"Please create a profile in the SimpleX app" = "请在 SimpleX 应用程序中创建配置文件"; + +/* No comment provided by engineer. */ +"Selected chat preferences prohibit this message." = "选定的聊天首选项禁止此消息。"; + +/* No comment provided by engineer. */ +"Sending a message takes longer than expected." = "发送消息所需的时间比预期的要长。"; + +/* No comment provided by engineer. */ +"Sending message…" = "正在发送消息…"; + +/* No comment provided by engineer. */ +"Share" = "共享"; + +/* No comment provided by engineer. */ +"Slow network?" = "网络速度慢?"; + +/* No comment provided by engineer. */ +"Unknown database error: %@" = "未知数据库错误: %@"; + +/* No comment provided by engineer. */ +"Unsupported format" = "不支持的格式"; + +/* No comment provided by engineer. */ +"Wait" = "等待"; + +/* No comment provided by engineer. */ +"Wrong database passphrase" = "数据库密码错误"; + +/* No comment provided by engineer. */ +"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "您可以在 \"隐私与安全\"/\"SimpleX Lock \"设置中允许共享。"; - Created by EP on 30/07/2024. - Copyright © 2024 SimpleX Chat. All rights reserved. -*/ diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 4157ad3e5f..30b9a27e0e 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -135,25 +135,25 @@ 5CE4407927ADB701007B033A /* EmojiItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CE4407827ADB701007B033A /* EmojiItemView.swift */; }; 5CEACCE327DE9246000BD591 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCE227DE9246000BD591 /* ComposeView.swift */; }; 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; }; - 5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; }; 5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; }; 5CF937202B24DE8C00E1D781 /* SharedFileSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */; }; 5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF937212B25034A00E1D781 /* NSESubscriber.swift */; }; 5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; }; - 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 */; }; + 640743612CD360E600158442 /* ChooseServerOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640743602CD360E600158442 /* ChooseServerOperators.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 */; }; + 642BA82D2CE50495005E9412 /* NewServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 642BA82C2CE50495005E9412 /* NewServerView.swift */; }; 6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; }; + 643B3B4E2CCFD6400083A2CF /* OperatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 643B3B4D2CCFD6400083A2CF /* OperatorView.swift */; }; 6440CA00288857A10062C672 /* CIEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440C9FF288857A10062C672 /* CIEventView.swift */; }; 6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */; }; 6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */; }; 6442E0BE2880182D00CEC0F9 /* GroupChatInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6442E0BD2880182D00CEC0F9 /* GroupChatInfoView.swift */; }; - 64466DC829FC2B3B00E3D48D /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */; }; 64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DCB29FFE3E800E3D48D /* MailView.swift */; }; 6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */; }; 644EFFDE292BCD9D00525D5B /* ComposeVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */; }; @@ -166,6 +166,11 @@ 647F090E288EA27B00644C40 /* GroupMemberInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647F090D288EA27B00644C40 /* GroupMemberInfoView.swift */; }; 648010AB281ADD15009009B9 /* CIFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648010AA281ADD15009009B9 /* CIFileView.swift */; }; 648679AB2BC96A74006456E7 /* ChatItemForwardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */; }; + 649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D82CFE07CF00536B68 /* libffi.a */; }; + 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */; }; + 649B28DF2CFE07CF00536B68 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DA2CFE07CF00536B68 /* libgmpxx.a */; }; + 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */; }; + 649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 649B28DC2CFE07CF00536B68 /* libgmp.a */; }; 649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; }; 649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; }; 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */; }; @@ -178,6 +183,8 @@ 64E972072881BB22008DBC02 /* CIGroupInvitationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */; }; 64EEB0F72C353F1C00972D62 /* ServersSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EEB0F62C353F1C00972D62 /* ServersSummaryView.swift */; }; 64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */; }; + 8C01E9C12C8EFC33008A4B0A /* objc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C01E9C02C8EFC33008A4B0A /* objc.m */; }; + 8C01E9C22C8EFF8F008A4B0A /* objc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C01E9BF2C8EFBB6008A4B0A /* objc.h */; }; 8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C69FE7C2B8C7D2700267E38 /* AppSettings.swift */; }; 8C74C3E52C1B900600039E77 /* ThemeTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C7E3CE32C0DEAC400BFF63A /* ThemeTypes.swift */; }; 8C74C3E72C1B901900039E77 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C852B072C1086D100BA61E8 /* Color.swift */; }; @@ -191,10 +198,15 @@ 8C8118722C220B5B00E6FC94 /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = 8C8118712C220B5B00E6FC94 /* Yams */; }; 8C81482C2BD91CD4002CBEC3 /* AudioDevicePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C81482B2BD91CD4002CBEC3 /* AudioDevicePicker.swift */; }; 8C9BC2652C240D5200875A27 /* ThemeModeEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */; }; + 8CB3476C2CF5CFFA006787A5 /* Ink in Frameworks */ = {isa = PBXBuildFile; productRef = 8CB3476B2CF5CFFA006787A5 /* Ink */; }; + 8CB3476E2CF5F58B006787A5 /* ConditionsWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB3476D2CF5F58B006787A5 /* ConditionsWebView.swift */; }; 8CC4ED902BD7B8530078AEE8 /* CallAudioDeviceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */; }; 8CC956EE2BC0041000412A11 /* NetworkObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */; }; 8CE848A32C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */; }; + B73EFE532CE5FA3500C778EA /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73EFE522CE5FA3500C778EA /* CreateSimpleXAddress.swift */; }; B76E6C312C5C41D900EC11AA /* ContactListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */; }; + B79ADAFF2CE4EF930083DFFD /* AddressCreationCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = B79ADAFE2CE4EF930083DFFD /* AddressCreationCard.swift */; }; + CE176F202C87014C00145DBC /* InvertedForegroundStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */; }; CE1EB0E42C459A660099D896 /* ShareAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1EB0E32C459A660099D896 /* ShareAPI.swift */; }; CE2AD9CE2C452A4D00E844E3 /* ChatUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */; }; CE3097FB2C4C0C9F00180898 /* ErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */; }; @@ -202,12 +214,15 @@ CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = CE38A29B2C3FCD72005ED185 /* SwiftyGif */; }; CE75480A2C622630009579B7 /* SwipeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7548092C622630009579B7 /* SwipeLabel.swift */; }; CE984D4B2C36C5D500E3AEFF /* ChatItemClipShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */; }; + CEA6E91C2CBD21B0002B5DB4 /* UserDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */; }; + CEDB245B2C9CD71800FBC5F6 /* StickyScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */; }; CEDE70222C48FD9500233B1F /* SEChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDE70212C48FD9500233B1F /* SEChatState.swift */; }; CEE723AA2C3BD3D70009AE93 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */; }; CEE723B12C3BD3D70009AE93 /* SimpleX SE.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; CEE723F02C3D25C70009AE93 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723EF2C3D25C70009AE93 /* ShareView.swift */; }; CEE723F22C3D25ED0009AE93 /* ShareModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE723F12C3D25ED0009AE93 /* ShareModel.swift */; }; CEEA861D2C2ABCB50084E1EA /* ReverseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */; }; + CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */; }; D7197A1829AE89660055C05A /* WebRTC in Frameworks */ = {isa = PBXBuildFile; productRef = D7197A1729AE89660055C05A /* WebRTC */; }; D72A9088294BD7A70047C86D /* NativeTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A9087294BD7A70047C86D /* NativeTextEditor.swift */; }; D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547729AF89AF0022400A /* StoreKit.framework */; }; @@ -219,11 +234,6 @@ E5DCF9712C590272007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF96F2C590272007928CC /* Localizable.strings */; }; E5DCF9842C5902CE007928CC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF9822C5902CE007928CC /* Localizable.strings */; }; E5DCF9982C5906FF007928CC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E5DCF9962C5906FF007928CC /* InfoPlist.strings */; }; - E5E218492C6813750013B4C6 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E218442C6813750013B4C6 /* libgmpxx.a */; }; - E5E2184A2C6813750013B4C6 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E218452C6813750013B4C6 /* libffi.a */; }; - E5E2184B2C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E218462C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a */; }; - E5E2184C2C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E218472C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a */; }; - E5E2184D2C6813750013B4C6 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E218482C6813750013B4C6 /* libgmp.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -431,7 +441,7 @@ 5CB634AC29E46CF70066AD6B /* LocalAuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthView.swift; sourceTree = ""; }; 5CB634AE29E4BB7D0066AD6B /* SetAppPasscodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetAppPasscodeView.swift; sourceTree = ""; }; 5CB634B029E5EFEA0066AD6B /* PasscodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasscodeView.swift; sourceTree = ""; }; - 5CB924D627A8563F00ACCCDD /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + 5CB924D627A8563F00ACCCDD /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; wrapsLines = 0; }; 5CB924E027A867BA00ACCCDD /* UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfile.swift; sourceTree = ""; }; 5CB9250C27A9432000ACCCDD /* ChatListNavLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListNavLink.swift; sourceTree = ""; }; 5CBD285529565CAE00EC2CF4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; @@ -474,24 +484,24 @@ 5CE6C7B42AAB1527007F345C /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; 5CEACCE227DE9246000BD591 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = ""; }; 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = ""; }; - 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = ""; }; 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = ""; }; 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedFileSubscriber.swift; sourceTree = ""; }; 5CF937212B25034A00E1D781 /* NSESubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESubscriber.swift; sourceTree = ""; }; 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = ""; }; - 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatArchiveView.swift; sourceTree = ""; }; 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 = ""; }; 640417CC2B29B8C200CCB412 /* NewChatView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewChatView.swift; sourceTree = ""; }; + 640743602CD360E600158442 /* ChooseServerOperators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooseServerOperators.swift; sourceTree = ""; }; 6407BA82295DA85D0082BA18 /* CIInvalidJSONView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIInvalidJSONView.swift; sourceTree = ""; }; 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = ""; }; 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = ""; }; + 642BA82C2CE50495005E9412 /* NewServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewServerView.swift; sourceTree = ""; }; 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = ""; }; + 643B3B4D2CCFD6400083A2CF /* OperatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperatorView.swift; sourceTree = ""; }; 6440C9FF288857A10062C672 /* CIEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIEventView.swift; sourceTree = ""; }; 6440CA02288AECA70062C672 /* AddGroupMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupMembersView.swift; sourceTree = ""; }; 6442E0B9287F169300CEC0F9 /* AddGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupView.swift; sourceTree = ""; }; 6442E0BD2880182D00CEC0F9 /* GroupChatInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatInfoView.swift; sourceTree = ""; }; - 64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSimpleXAddress.swift; sourceTree = ""; }; 64466DCB29FFE3E800E3D48D /* MailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailView.swift; sourceTree = ""; }; 6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupLinkView.swift; sourceTree = ""; }; 644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeVoiceView.swift; sourceTree = ""; }; @@ -505,6 +515,11 @@ 648010AA281ADD15009009B9 /* CIFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIFileView.swift; sourceTree = ""; }; 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemForwardingView.swift; sourceTree = ""; }; 6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 649B28D82CFE07CF00536B68 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a"; sourceTree = ""; }; + 649B28DA2CFE07CF00536B68 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a"; sourceTree = ""; }; + 649B28DC2CFE07CF00536B68 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = ""; }; 649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = ""; }; 64AA1C6827EE10C800AC7277 /* ContextItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextItemView.swift; sourceTree = ""; }; @@ -518,6 +533,8 @@ 64E972062881BB22008DBC02 /* CIGroupInvitationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIGroupInvitationView.swift; sourceTree = ""; }; 64EEB0F62C353F1C00972D62 /* ServersSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServersSummaryView.swift; sourceTree = ""; }; 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoHelp.swift; sourceTree = ""; }; + 8C01E9BF2C8EFBB6008A4B0A /* objc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = objc.h; sourceTree = ""; }; + 8C01E9C02C8EFC33008A4B0A /* objc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = objc.m; sourceTree = ""; }; 8C69FE7C2B8C7D2700267E38 /* AppSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettings.swift; sourceTree = ""; }; 8C74C3EB2C1B92A900039E77 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; 8C74C3ED2C1B942300039E77 /* ChatWallpaper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatWallpaper.swift; sourceTree = ""; }; @@ -530,15 +547,21 @@ 8C852B072C1086D100BA61E8 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; 8C86EBE42C0DAE4F00E12243 /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = ""; }; 8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeModeEditor.swift; sourceTree = ""; }; + 8CB3476D2CF5F58B006787A5 /* ConditionsWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionsWebView.swift; sourceTree = ""; }; 8CC4ED8F2BD7B8530078AEE8 /* CallAudioDeviceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallAudioDeviceManager.swift; sourceTree = ""; }; 8CC956ED2BC0041000412A11 /* NetworkObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkObserver.swift; sourceTree = ""; }; 8CE848A22C5A0FA000D5C7C8 /* SelectableChatItemToolbars.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectableChatItemToolbars.swift; sourceTree = ""; }; + B73EFE522CE5FA3500C778EA /* CreateSimpleXAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateSimpleXAddress.swift; sourceTree = ""; }; B76E6C302C5C41D900EC11AA /* ContactListNavLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactListNavLink.swift; sourceTree = ""; }; + B79ADAFE2CE4EF930083DFFD /* AddressCreationCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCreationCard.swift; sourceTree = ""; }; + CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvertedForegroundStyle.swift; sourceTree = ""; }; CE1EB0E32C459A660099D896 /* ShareAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAPI.swift; sourceTree = ""; }; CE2AD9CD2C452A4D00E844E3 /* ChatUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatUtils.swift; sourceTree = ""; }; CE3097FA2C4C0C9F00180898 /* ErrorAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorAlert.swift; sourceTree = ""; }; CE7548092C622630009579B7 /* SwipeLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeLabel.swift; sourceTree = ""; }; CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemClipShape.swift; sourceTree = ""; }; + CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefault.swift; sourceTree = ""; }; + CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyScrollView.swift; sourceTree = ""; }; CEDE70212C48FD9500233B1F /* SEChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SEChatState.swift; sourceTree = ""; }; CEE723A72C3BD3D70009AE93 /* SimpleX SE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX SE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; CEE723A92C3BD3D70009AE93 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; @@ -547,6 +570,7 @@ CEE723EF2C3D25C70009AE93 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = ""; }; CEE723F12C3D25ED0009AE93 /* ShareModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareModel.swift; sourceTree = ""; }; CEEA861C2C2ABCB50084E1EA /* ReverseList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseList.swift; sourceTree = ""; }; + CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetRepresentable.swift; sourceTree = ""; }; D72A9087294BD7A70047C86D /* NativeTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTextEditor.swift; sourceTree = ""; }; D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; }; D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; }; @@ -604,11 +628,6 @@ E5DCF9A62C590731007928CC /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/InfoPlist.strings; sourceTree = ""; }; E5DCF9A72C590732007928CC /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = ""; }; E5DCF9A82C590732007928CC /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = ""; }; - E5E218442C6813750013B4C6 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - E5E218452C6813750013B4C6 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - E5E218462C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a"; sourceTree = ""; }; - E5E218472C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a"; sourceTree = ""; }; - E5E218482C6813750013B4C6 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -618,6 +637,7 @@ files = ( 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */, 8C8118722C220B5B00E6FC94 /* Yams in Frameworks */, + 8CB3476C2CF5CFFA006787A5 /* Ink in Frameworks */, D741547829AF89AF0022400A /* StoreKit.framework in Frameworks */, D7197A1829AE89660055C05A /* WebRTC in Frameworks */, D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */, @@ -647,14 +667,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E5E218492C6813750013B4C6 /* libgmpxx.a in Frameworks */, + 649B28DF2CFE07CF00536B68 /* libgmpxx.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - E5E2184D2C6813750013B4C6 /* libgmp.a in Frameworks */, - E5E2184C2C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a in Frameworks */, + 649B28E12CFE07CF00536B68 /* libgmp.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - E5E2184B2C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a in Frameworks */, - E5E2184A2C6813750013B4C6 /* libffi.a in Frameworks */, + 649B28E02CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a in Frameworks */, CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */, + 649B28DE2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a in Frameworks */, + 649B28DD2CFE07CF00536B68 /* libffi.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -731,11 +751,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - E5E218452C6813750013B4C6 /* libffi.a */, - E5E218482C6813750013B4C6 /* libgmp.a */, - E5E218442C6813750013B4C6 /* libgmpxx.a */, - E5E218462C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf-ghc9.6.3.a */, - E5E218472C6813750013B4C6 /* libHSsimplex-chat-6.0.0.7-JAEd2ymO3CfCyjlINhbKkf.a */, + 649B28D82CFE07CF00536B68 /* libffi.a */, + 649B28DC2CFE07CF00536B68 /* libgmp.a */, + 649B28DA2CFE07CF00536B68 /* libgmpxx.a */, + 649B28D92CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E-ghc9.6.3.a */, + 649B28DB2CFE07CF00536B68 /* libHSsimplex-chat-6.2.0.7-3p784Fmu4gOAiEiFcsHj1E.a */, ); path = Libraries; sourceTree = ""; @@ -786,12 +806,15 @@ 18415DAAAD1ADBEDB0EDA852 /* VideoPlayerView.swift */, 64466DCB29FFE3E800E3D48D /* MailView.swift */, 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */, - 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */, 8C7F8F0D2C19C0C100D16888 /* ViewModifiers.swift */, 8C74C3ED2C1B942300039E77 /* ChatWallpaper.swift */, 8C9BC2642C240D5100875A27 /* ThemeModeEditor.swift */, CE984D4A2C36C5D500E3AEFF /* ChatItemClipShape.swift */, CE7548092C622630009579B7 /* SwipeLabel.swift */, + CE176F1F2C87014C00145DBC /* InvertedForegroundStyle.swift */, + CEDB245A2C9CD71800FBC5F6 /* StickyScrollView.swift */, + CEFB2EDE2CA1BCC7004B1ECE /* SheetRepresentable.swift */, + CEA6E91B2CBD21B0002B5DB4 /* UserDefault.swift */, ); path = Helpers; sourceTree = ""; @@ -862,13 +885,15 @@ 5CB0BA8C282711BC00B3292C /* Onboarding */ = { isa = PBXGroup; children = ( + B73EFE522CE5FA3500C778EA /* CreateSimpleXAddress.swift */, 5CB0BA8D2827126500B3292C /* OnboardingView.swift */, 5CB0BA8F282713D900B3292C /* SimpleXInfo.swift */, 5CB0BA992827FD8800B3292C /* HowItWorks.swift */, 5CB0BA91282713FD00B3292C /* CreateProfile.swift */, - 64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */, 5C9A5BDA2871E05400A5B906 /* SetNotificationsMode.swift */, 5CBD285B29575B8E00EC2CF4 /* WhatsNewView.swift */, + 640743602CD360E600158442 /* ChooseServerOperators.swift */, + B79ADAFE2CE4EF930083DFFD /* AddressCreationCard.swift */, ); path = Onboarding; sourceTree = ""; @@ -899,10 +924,9 @@ 5CB924DF27A8678B00ACCCDD /* UserSettings */ = { isa = PBXGroup; children = ( + 643B3B4C2CCFD34B0083A2CF /* NetworkAndServers */, 5CB924D627A8563F00ACCCDD /* SettingsView.swift */, 5CB346E62868D76D001FD2EF /* NotificationsView.swift */, - 5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */, - 5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */, 5CADE79929211BB900072E13 /* PreferencesView.swift */, 5C5DB70D289ABDD200730FFF /* AppearanceSettings.swift */, 5C05DF522840AA1D00C683F9 /* CallSettings.swift */, @@ -910,9 +934,6 @@ 5CC036DF29C488D500C0EF20 /* HiddenProfileView.swift */, 5C577F7C27C83AA10006112D /* MarkdownHelp.swift */, 5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */, - 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */, - 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */, - 5C9329402929248A0090FFF9 /* ScanProtocolServer.swift */, 5CB2084E28DA4B4800D024EC /* RTCServers.swift */, 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */, 18415845648CA4F5A8BCA272 /* UserProfilesView.swift */, @@ -979,6 +1000,8 @@ 5CE2BA96284537A800EC33A6 /* dummy.m */, 5CD67B8D2B0E858A00C510B1 /* hs_init.h */, 5CD67B8E2B0E858A00C510B1 /* hs_init.c */, + 8C01E9BF2C8EFBB6008A4B0A /* objc.h */, + 8C01E9C02C8EFC33008A4B0A /* objc.m */, ); path = SimpleXChat; sourceTree = ""; @@ -1033,7 +1056,6 @@ isa = PBXGroup; children = ( 5C4B3B09285FB130003915F2 /* DatabaseView.swift */, - 5CFA59CF286477B400863A68 /* ChatArchiveView.swift */, 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */, 5C9CC7A828C532AB00BEF955 /* DatabaseErrorView.swift */, 5C9CC7AC28C55D7800BEF955 /* DatabaseEncryptionView.swift */, @@ -1041,6 +1063,21 @@ path = Database; sourceTree = ""; }; + 643B3B4C2CCFD34B0083A2CF /* NetworkAndServers */ = { + isa = PBXGroup; + children = ( + 5C9329402929248A0090FFF9 /* ScanProtocolServer.swift */, + 642BA82C2CE50495005E9412 /* NewServerView.swift */, + 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */, + 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */, + 643B3B4D2CCFD6400083A2CF /* OperatorView.swift */, + 5C9C2DA6289957AE00CC63B1 /* AdvancedNetworkSettings.swift */, + 5C9C2DA82899DA6F00CC63B1 /* NetworkAndServers.swift */, + 8CB3476D2CF5F58B006787A5 /* ConditionsWebView.swift */, + ); + path = NetworkAndServers; + sourceTree = ""; + }; 6440CA01288AEC770062C672 /* Group */ = { isa = PBXGroup; children = ( @@ -1116,6 +1153,7 @@ files = ( 5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */, 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */, + 8C01E9C22C8EFF8F008A4B0A /* objc.h in Headers */, 5CE2BA952845354B00EC33A6 /* SimpleX.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1147,6 +1185,7 @@ D7F0E33829964E7E0068AF69 /* LZString */, D7197A1729AE89660055C05A /* WebRTC */, 8C8118712C220B5B00E6FC94 /* Yams */, + 8CB3476B2CF5CFFA006787A5 /* Ink */, ); productName = "SimpleX (iOS)"; productReference = 5CA059CA279559F40002BEB4 /* SimpleX.app */; @@ -1290,6 +1329,7 @@ D7F0E33729964E7D0068AF69 /* XCRemoteSwiftPackageReference "lzstring-swift" */, D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */, 8C73C1162C21E17B00892670 /* XCRemoteSwiftPackageReference "Yams" */, + 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */, ); productRefGroup = 5CA059CB279559F40002BEB4 /* Products */; projectDirPath = ""; @@ -1359,10 +1399,12 @@ 64C06EB52A0A4A7C00792D4D /* ChatItemInfoView.swift in Sources */, 640417CE2B29B8C200CCB412 /* NewChatView.swift in Sources */, 6440CA03288AECA70062C672 /* AddGroupMembersView.swift in Sources */, + 640743612CD360E600158442 /* ChooseServerOperators.swift in Sources */, 5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */, 5C55A923283CEDE600C4E99E /* SoundPlayer.swift in Sources */, 5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */, 5CB924D727A8563F00ACCCDD /* SettingsView.swift in Sources */, + B79ADAFF2CE4EF930083DFFD /* AddressCreationCard.swift in Sources */, 5CEACCE327DE9246000BD591 /* ComposeView.swift in Sources */, E51CC1E62C62085600DB91FE /* OneHandUICard.swift in Sources */, 5C65DAF929D0CC20003CEE45 /* DeveloperView.swift in Sources */, @@ -1389,12 +1431,12 @@ 644EFFE2292D089800525D5B /* FramedCIVoiceView.swift in Sources */, 5C4B3B0A285FB130003915F2 /* DatabaseView.swift in Sources */, 5CB2084F28DA4B4800D024EC /* RTCServers.swift in Sources */, + B73EFE532CE5FA3500C778EA /* CreateSimpleXAddress.swift in Sources */, 5CB634AF29E4BB7D0066AD6B /* SetAppPasscodeView.swift in Sources */, 5C10D88828EED12E00E58BF0 /* ContactConnectionInfo.swift in Sources */, 5CBE6C12294487F7002D9531 /* VerifyCodeView.swift in Sources */, 3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */, 648679AB2BC96A74006456E7 /* ChatItemForwardingView.swift in Sources */, - 64466DC829FC2B3B00E3D48D /* CreateSimpleXAddress.swift in Sources */, 3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */, 5C7505A827B6D34800BE3227 /* ChatInfoToolbar.swift in Sources */, B76E6C312C5C41D900EC11AA /* ContactListNavLink.swift in Sources */, @@ -1435,11 +1477,11 @@ 646BB38E283FDB6D001CE359 /* LocalAuthenticationUtils.swift in Sources */, 8C74C3EA2C1B90AF00039E77 /* ThemeManager.swift in Sources */, 5C7505A227B65FDB00BE3227 /* CIMetaView.swift in Sources */, - 5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */, 5C35CFC827B2782E00FB6C6D /* BGManager.swift in Sources */, 5CB634B129E5EFEA0066AD6B /* PasscodeView.swift in Sources */, 8C69FE7D2B8C7D2700267E38 /* AppSettings.swift in Sources */, 5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */, + CEFB2EDF2CA1BCC7004B1ECE /* SheetRepresentable.swift in Sources */, 5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */, 6442E0BA287F169300CEC0F9 /* AddGroupView.swift in Sources */, 5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */, @@ -1466,9 +1508,9 @@ 8C9BC2652C240D5200875A27 /* ThemeModeEditor.swift in Sources */, 5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */, 5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */, - 5CFA59D12864782E00863A68 /* ChatArchiveView.swift in Sources */, 649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */, 5CADE79C292131E900072E13 /* ContactPreferencesView.swift in Sources */, + CEA6E91C2CBD21B0002B5DB4 /* UserDefault.swift in Sources */, 5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */, 5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */, 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */, @@ -1477,6 +1519,7 @@ 5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */, 5C971E1D27AEBEF600C8A3CE /* ChatInfoView.swift in Sources */, 5CBD285C29575B8E00EC2CF4 /* WhatsNewView.swift in Sources */, + 8CB3476E2CF5F58B006787A5 /* ConditionsWebView.swift in Sources */, 5CC1C99527A6CF7F000D9FF6 /* ShareSheet.swift in Sources */, 5C5E5D3B2824468B00B0488A /* ActiveCallView.swift in Sources */, 5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */, @@ -1490,9 +1533,11 @@ 5C93293F2928E0FD0090FFF9 /* AudioRecPlay.swift in Sources */, 5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */, 5CE4407227ADB1D0007B033A /* Emoji.swift in Sources */, + CEDB245B2C9CD71800FBC5F6 /* StickyScrollView.swift in Sources */, 5C9CC7A928C532AB00BEF955 /* DatabaseErrorView.swift in Sources */, 5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */, 64AA1C6927EE10C800AC7277 /* ContextItemView.swift in Sources */, + CE176F202C87014C00145DBC /* InvertedForegroundStyle.swift in Sources */, 5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */, 5C9C2DA7289957AE00CC63B1 /* AdvancedNetworkSettings.swift in Sources */, 5CADE79A29211BB900072E13 /* PreferencesView.swift in Sources */, @@ -1509,7 +1554,9 @@ 5CB634AD29E46CF70066AD6B /* LocalAuthView.swift in Sources */, 18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */, 18415F9A2D551F9757DA4654 /* CIVideoView.swift in Sources */, + 642BA82D2CE50495005E9412 /* NewServerView.swift in Sources */, 184158C131FDB829D8A117EA /* VideoPlayerView.swift in Sources */, + 643B3B4E2CCFD6400083A2CF /* OperatorView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1543,6 +1590,7 @@ 8C74C3E72C1B901900039E77 /* Color.swift in Sources */, 5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */, 5CE2BA91284533A300EC33A6 /* Notifications.swift in Sources */, + 8C01E9C12C8EFC33008A4B0A /* objc.m in Sources */, 5CE2BA79284530CC00EC33A6 /* SimpleXChat.docc in Sources */, 5CE2BA90284533A300EC33A6 /* JSON.swift in Sources */, 5CE2BA8B284533A300EC33A6 /* ChatTypes.swift in Sources */, @@ -1883,7 +1931,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1908,7 +1956,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES_THIN; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1932,7 +1980,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1957,7 +2005,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1973,11 +2021,11 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -1993,11 +2041,11 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.Tests-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -2018,7 +2066,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -2033,7 +2081,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2055,7 +2103,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -2070,7 +2118,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2092,7 +2140,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -2118,7 +2166,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -2143,7 +2191,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -2169,7 +2217,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -2194,7 +2242,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2209,7 +2257,7 @@ "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -2228,7 +2276,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 232; + CURRENT_PROJECT_VERSION = 254; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2243,7 +2291,7 @@ "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 6.0; + MARKETING_VERSION = 6.2; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-SE"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; @@ -2320,7 +2368,7 @@ repositoryURL = "https://github.com/twostraws/CodeScanner"; requirement = { kind = exactVersion; - version = 2.1.1; + version = 2.5.0; }; }; 8C73C1162C21E17B00892670 /* XCRemoteSwiftPackageReference "Yams" */ = { @@ -2331,6 +2379,14 @@ version = 5.1.2; }; }; + 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/johnsundell/ink"; + requirement = { + kind = exactVersion; + version = 0.6.0; + }; + }; D7197A1629AE89660055C05A /* XCRemoteSwiftPackageReference "WebRTC" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/simplex-chat/WebRTC.git"; @@ -2368,6 +2424,11 @@ package = 8C73C1162C21E17B00892670 /* XCRemoteSwiftPackageReference "Yams" */; productName = Yams; }; + 8CB3476B2CF5CFFA006787A5 /* Ink */ = { + isa = XCSwiftPackageProductDependency; + package = 8CB3476A2CF5CFFA006787A5 /* XCRemoteSwiftPackageReference "ink" */; + productName = Ink; + }; CE38A29B2C3FCD72005ED185 /* SwiftyGif */ = { isa = XCSwiftPackageProductDependency; package = D77B92DA2952372200A5A1CC /* XCRemoteSwiftPackageReference "SwiftyGif" */; diff --git a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d3e61c88f9..7fdbff38af 100644 --- a/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/apps/ios/SimpleX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,22 @@ { - "originHash" : "e2611d1e91fd8071abc106776ba14ee2e395d2ad08a78e073381294abc10f115", + "originHash" : "33afc44be5f4225325b3cb940ed71b6cbf3ef97290d348d7b6803697bcd0637d", "pins" : [ { "identity" : "codescanner", "kind" : "remoteSourceControl", "location" : "https://github.com/twostraws/CodeScanner", "state" : { - "revision" : "c27a66149b7483fe42e2ec6aad61d5c3fffe522d", - "version" : "2.1.1" + "revision" : "34da57fb63b47add20de8a85da58191523ccce57", + "version" : "2.5.0" + } + }, + { + "identity" : "ink", + "kind" : "remoteSourceControl", + "location" : "https://github.com/johnsundell/ink", + "state" : { + "revision" : "bcc9f219900a62c4210e6db726035d7f03ae757b", + "version" : "0.6.0" } }, { @@ -23,7 +32,6 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kirualex/SwiftyGif", "state" : { - "branch" : "master", "revision" : "5e8619335d394901379c9add5c4c1c2f420b3800" } }, diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index a6409dec2f..884993f542 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -8,6 +8,7 @@ import Foundation import SwiftUI +import Network public let jsonDecoder = getJSONDecoder() public let jsonEncoder = getJSONEncoder() @@ -42,18 +43,21 @@ public enum ChatCommand { case apiGetChats(userId: Int64) 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 apiSendMessages(type: ChatType, id: Int64, live: Bool, ttl: Int?, composedMessages: [ComposedMessage]) + case apiCreateChatItems(noteFolderId: Int64, composedMessages: [ComposedMessage]) case apiUpdateChatItem(type: ChatType, id: Int64, itemId: Int64, msg: MsgContent, live: Bool) case apiDeleteChatItem(type: ChatType, id: Int64, itemIds: [Int64], mode: CIDeleteMode) case apiDeleteMemberChatItem(groupId: Int64, itemIds: [Int64]) case apiChatItemReaction(type: ChatType, id: Int64, itemId: Int64, add: Bool, reaction: MsgReaction) - case apiForwardChatItem(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemId: Int64, ttl: Int?) + case apiGetReactionMembers(userId: Int64, groupId: Int64, itemId: Int64, reaction: MsgReaction) + case apiPlanForwardChatItems(toChatType: ChatType, toChatId: Int64, itemIds: [Int64]) + case apiForwardChatItems(toChatType: ChatType, toChatId: Int64, fromChatType: ChatType, fromChatId: Int64, itemIds: [Int64], ttl: Int?) case apiGetNtfToken case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode) case apiVerifyToken(token: DeviceToken, nonce: String, code: String) case apiDeleteToken(token: DeviceToken) - case apiGetNtfMessage(nonce: String, encNtfInfo: String) + case apiGetNtfConns(nonce: String, encNtfInfo: String) + case apiGetConnNtfMessages(connIds: [String]) case apiNewGroup(userId: Int64, incognito: Bool, groupProfile: GroupProfile) case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole) case apiJoinGroup(groupId: Int64) @@ -69,9 +73,15 @@ public enum ChatCommand { case apiGetGroupLink(groupId: Int64) case apiCreateMemberContact(groupId: Int64, groupMemberId: Int64) case apiSendMemberContactInvitation(contactId: Int64, msg: MsgContent) - case apiGetUserProtoServers(userId: Int64, serverProtocol: ServerProtocol) - case apiSetUserProtoServers(userId: Int64, serverProtocol: ServerProtocol, servers: [ServerCfg]) case apiTestProtoServer(userId: Int64, server: String) + case apiGetServerOperators + case apiSetServerOperators(operators: [ServerOperator]) + case apiGetUserServers(userId: Int64) + case apiSetUserServers(userId: Int64, userServers: [UserOperatorServers]) + case apiValidateServers(userId: Int64, userServers: [UserOperatorServers]) + case apiGetUsageConditions + case apiSetConditionsNotified(conditionsId: Int64) + case apiAcceptConditions(conditionsId: Int64, operatorIds: [Int64]) case apiSetChatItemTTL(userId: Int64, seconds: Int64?) case apiGetChatItemTTL(userId: Int64) case apiSetNetworkConfig(networkConfig: NetCfg) @@ -97,6 +107,7 @@ public enum ChatCommand { case apiVerifyGroupMember(groupId: Int64, groupMemberId: Int64, connectionCode: String?) case apiAddContact(userId: Int64, incognito: Bool) case apiSetConnectionIncognito(connId: Int64, incognito: Bool) + case apiChangeConnectionUser(connId: Int64, userId: Int64) case apiConnectPlan(userId: Int64, connReq: String) case apiConnect(userId: Int64, incognito: Bool, connReq: String) case apiConnectContactViaAddress(userId: Int64, incognito: Bool, contactId: Int64) @@ -127,7 +138,8 @@ public enum ChatCommand { case apiCallStatus(contact: Contact, callStatus: WebRTCCallStatus) // WebRTC calls / case apiGetNetworkStatuses - case apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64)) + case apiChatRead(type: ChatType, id: Int64) + case apiChatItemsRead(type: ChatType, id: Int64, itemIds: [Int64]) case apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) case receiveFile(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool?, inline: Bool?) case setFileToReceive(fileId: Int64, userApprovedRelays: Bool, encrypted: Bool?) @@ -190,25 +202,28 @@ public enum ChatCommand { case let .apiGetChat(type, id, pagination, search): return "/_get chat \(ref(type, id)) \(pagination.cmdString)" + (search == "" ? "" : " search=\(search)") case let .apiGetChatItemInfo(type, id, itemId): return "/_get item info \(ref(type, id)) \(itemId)" - case let .apiSendMessage(type, id, file, quotedItemId, mc, live, ttl): - let msg = encodeJSON(ComposedMessage(fileSource: file, quotedItemId: quotedItemId, msgContent: mc)) + case let .apiSendMessages(type, id, live, ttl, composedMessages): + let msgs = encodeJSON(composedMessages) 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)" + return "/_send \(ref(type, id)) live=\(onOff(live)) ttl=\(ttlStr) json \(msgs)" + case let .apiCreateChatItems(noteFolderId, composedMessages): + let msgs = encodeJSON(composedMessages) + return "/_create *\(noteFolderId) json \(msgs)" 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, itemIds, mode): return "/_delete item \(ref(type, id)) \(itemIds.map({ "\($0)" }).joined(separator: ",")) \(mode.rawValue)" case let .apiDeleteMemberChatItem(groupId, itemIds): return "/_delete member item #\(groupId) \(itemIds.map({ "\($0)" }).joined(separator: ","))" case let .apiChatItemReaction(type, id, itemId, add, reaction): return "/_reaction \(ref(type, id)) \(itemId) \(onOff(add)) \(encodeJSON(reaction))" - case let .apiForwardChatItem(toChatType, toChatId, fromChatType, fromChatId, itemId, ttl): + case let .apiGetReactionMembers(userId, groupId, itemId, reaction): return "/_reaction members \(userId) #\(groupId) \(itemId) \(encodeJSON(reaction))" + case let .apiPlanForwardChatItems(type, id, itemIds): return "/_forward plan \(ref(type, id)) \(itemIds.map({ "\($0)" }).joined(separator: ","))" + case let .apiForwardChatItems(toChatType, toChatId, fromChatType, fromChatId, itemIds, ttl): let ttlStr = ttl != nil ? "\(ttl!)" : "default" - return "/_forward \(ref(toChatType, toChatId)) \(ref(fromChatType, fromChatId)) \(itemId) ttl=\(ttlStr)" + return "/_forward \(ref(toChatType, toChatId)) \(ref(fromChatType, fromChatId)) \(itemIds.map({ "\($0)" }).joined(separator: ",")) ttl=\(ttlStr)" case .apiGetNtfToken: return "/_ntf get " case let .apiRegisterToken(token, notificationMode): return "/_ntf register \(token.cmdString) \(notificationMode.rawValue)" case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)" case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)" - case let .apiGetNtfMessage(nonce, encNtfInfo): return "/_ntf message \(nonce) \(encNtfInfo)" + case let .apiGetNtfConns(nonce, encNtfInfo): return "/_ntf conns \(nonce) \(encNtfInfo)" + case let .apiGetConnNtfMessages(connIds): return "/_ntf conn messages \(connIds.joined(separator: ","))" case let .apiNewGroup(userId, incognito, groupProfile): return "/_group \(userId) incognito=\(onOff(incognito)) \(encodeJSON(groupProfile))" case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)" case let .apiJoinGroup(groupId): return "/_join #\(groupId)" @@ -224,9 +239,15 @@ public enum ChatCommand { case let .apiGetGroupLink(groupId): return "/_get link #\(groupId)" case let .apiCreateMemberContact(groupId, groupMemberId): return "/_create member contact #\(groupId) \(groupMemberId)" case let .apiSendMemberContactInvitation(contactId, mc): return "/_invite member contact @\(contactId) \(mc.cmdString)" - case let .apiGetUserProtoServers(userId, serverProtocol): return "/_servers \(userId) \(serverProtocol)" - case let .apiSetUserProtoServers(userId, serverProtocol, servers): return "/_servers \(userId) \(serverProtocol) \(protoServersStr(servers))" case let .apiTestProtoServer(userId, server): return "/_server test \(userId) \(server)" + case .apiGetServerOperators: return "/_operators" + case let .apiSetServerOperators(operators): return "/_operators \(encodeJSON(operators))" + case let .apiGetUserServers(userId): return "/_servers \(userId)" + case let .apiSetUserServers(userId, userServers): return "/_servers \(userId) \(encodeJSON(userServers))" + case let .apiValidateServers(userId, userServers): return "/_validate_servers \(userId) \(encodeJSON(userServers))" + case .apiGetUsageConditions: return "/_conditions" + case let .apiSetConditionsNotified(conditionsId): return "/_conditions_notified \(conditionsId)" + case let .apiAcceptConditions(conditionsId, operatorIds): return "/_accept_conditions \(conditionsId) \(joinedIds(operatorIds))" case let .apiSetChatItemTTL(userId, seconds): return "/_ttl \(userId) \(chatItemTTLStr(seconds: seconds))" case let .apiGetChatItemTTL(userId): return "/_ttl \(userId)" case let .apiSetNetworkConfig(networkConfig): return "/_network \(encodeJSON(networkConfig))" @@ -262,6 +283,7 @@ public enum ChatCommand { case let .apiVerifyGroupMember(groupId, groupMemberId, .none): return "/_verify code #\(groupId) \(groupMemberId)" case let .apiAddContact(userId, incognito): return "/_connect \(userId) incognito=\(onOff(incognito))" case let .apiSetConnectionIncognito(connId, incognito): return "/_set incognito :\(connId) \(onOff(incognito))" + case let .apiChangeConnectionUser(connId, userId): return "/_set conn user :\(connId) \(userId)" case let .apiConnectPlan(userId, connReq): return "/_connect plan \(userId) \(connReq)" case let .apiConnect(userId, incognito, connReq): return "/_connect \(userId) incognito=\(onOff(incognito)) \(connReq)" case let .apiConnectContactViaAddress(userId, incognito, contactId): return "/_connect contact \(userId) incognito=\(onOff(incognito)) \(contactId)" @@ -290,7 +312,8 @@ public enum ChatCommand { case .apiGetCallInvitations: return "/_call get" case let .apiCallStatus(contact, callStatus): return "/_call status @\(contact.apiId) \(callStatus.rawValue)" case .apiGetNetworkStatuses: return "/_network_statuses" - case let .apiChatRead(type, id, itemRange: (from, to)): return "/_read chat \(ref(type, id)) from=\(from) to=\(to)" + case let .apiChatRead(type, id): return "/_read chat \(ref(type, id))" + case let .apiChatItemsRead(type, id, itemIds): return "/_read chat items \(ref(type, id)) \(joinedIds(itemIds))" case let .apiChatUnread(type, id, unreadChat): return "/_unread chat \(ref(type, id)) \(onOff(unreadChat))" case let .receiveFile(fileId, userApprovedRelays, encrypt, inline): return "/freceive \(fileId)\(onOffParam("approved_relays", userApprovedRelays))\(onOffParam("encrypt", encrypt))\(onOffParam("inline", inline))" case let .setFileToReceive(fileId, userApprovedRelays, encrypt): return "/_set_file_to_receive \(fileId)\(onOffParam("approved_relays", userApprovedRelays))\(onOffParam("encrypt", encrypt))" @@ -347,19 +370,22 @@ public enum ChatCommand { case .apiGetChats: return "apiGetChats" case .apiGetChat: return "apiGetChat" case .apiGetChatItemInfo: return "apiGetChatItemInfo" - case .apiSendMessage: return "apiSendMessage" - case .apiCreateChatItem: return "apiCreateChatItem" + case .apiSendMessages: return "apiSendMessages" + case .apiCreateChatItems: return "apiCreateChatItems" case .apiUpdateChatItem: return "apiUpdateChatItem" case .apiDeleteChatItem: return "apiDeleteChatItem" case .apiConnectContactViaAddress: return "apiConnectContactViaAddress" case .apiDeleteMemberChatItem: return "apiDeleteMemberChatItem" case .apiChatItemReaction: return "apiChatItemReaction" - case .apiForwardChatItem: return "apiForwardChatItem" + case .apiGetReactionMembers: return "apiGetReactionMembers" + case .apiPlanForwardChatItems: return "apiPlanForwardChatItems" + case .apiForwardChatItems: return "apiForwardChatItems" case .apiGetNtfToken: return "apiGetNtfToken" case .apiRegisterToken: return "apiRegisterToken" case .apiVerifyToken: return "apiVerifyToken" case .apiDeleteToken: return "apiDeleteToken" - case .apiGetNtfMessage: return "apiGetNtfMessage" + case .apiGetNtfConns: return "apiGetNtfConns" + case .apiGetConnNtfMessages: return "apiGetConnNtfMessages" case .apiNewGroup: return "apiNewGroup" case .apiAddMember: return "apiAddMember" case .apiJoinGroup: return "apiJoinGroup" @@ -375,9 +401,15 @@ public enum ChatCommand { case .apiGetGroupLink: return "apiGetGroupLink" case .apiCreateMemberContact: return "apiCreateMemberContact" case .apiSendMemberContactInvitation: return "apiSendMemberContactInvitation" - case .apiGetUserProtoServers: return "apiGetUserProtoServers" - case .apiSetUserProtoServers: return "apiSetUserProtoServers" case .apiTestProtoServer: return "apiTestProtoServer" + case .apiGetServerOperators: return "apiGetServerOperators" + case .apiSetServerOperators: return "apiSetServerOperators" + case .apiGetUserServers: return "apiGetUserServers" + case .apiSetUserServers: return "apiSetUserServers" + case .apiValidateServers: return "apiValidateServers" + case .apiGetUsageConditions: return "apiGetUsageConditions" + case .apiSetConditionsNotified: return "apiSetConditionsNotified" + case .apiAcceptConditions: return "apiAcceptConditions" case .apiSetChatItemTTL: return "apiSetChatItemTTL" case .apiGetChatItemTTL: return "apiGetChatItemTTL" case .apiSetNetworkConfig: return "apiSetNetworkConfig" @@ -403,6 +435,7 @@ public enum ChatCommand { case .apiVerifyGroupMember: return "apiVerifyGroupMember" case .apiAddContact: return "apiAddContact" case .apiSetConnectionIncognito: return "apiSetConnectionIncognito" + case .apiChangeConnectionUser: return "apiChangeConnectionUser" case .apiConnectPlan: return "apiConnectPlan" case .apiConnect: return "apiConnect" case .apiDeleteChat: return "apiDeleteChat" @@ -431,6 +464,7 @@ public enum ChatCommand { case .apiCallStatus: return "apiCallStatus" case .apiGetNetworkStatuses: return "apiGetNetworkStatuses" case .apiChatRead: return "apiChatRead" + case .apiChatItemsRead: return "apiChatItemsRead" case .apiChatUnread: return "apiChatUnread" case .receiveFile: return "receiveFile" case .setFileToReceive: return "setFileToReceive" @@ -459,8 +493,8 @@ public enum ChatCommand { "\(type.rawValue)\(id)" } - func protoServersStr(_ servers: [ServerCfg]) -> String { - encodeJSON(ProtoServersConfig(servers: servers)) + func joinedIds(_ ids: [Int64]) -> String { + ids.map { "\($0)" }.joined(separator: ",") } func chatItemTTLStr(seconds: Int64?) -> String { @@ -531,13 +565,16 @@ public enum ChatResponse: Decodable, Error { case apiChats(user: UserRef, chats: [ChatData]) case apiChat(user: UserRef, chat: ChatData) case chatItemInfo(user: UserRef, chatItem: AChatItem, chatItemInfo: ChatItemInfo) - case userProtoServers(user: UserRef, servers: UserProtoServers) case serverTestResult(user: UserRef, testServer: String, testFailure: ProtocolTestFailure?) + case serverOperatorConditions(conditions: ServerOperatorConditions) + case userServers(user: UserRef, userServers: [UserOperatorServers]) + case userServersValidation(user: UserRef, serverErrors: [UserServersError]) + case usageConditions(usageConditions: UsageConditions, conditionsText: String, acceptedConditions: UsageConditions?) case chatItemTTL(user: UserRef, chatItemTTL: Int64?) case networkConfig(networkConfig: NetCfg) case contactInfo(user: UserRef, contact: Contact, connectionStats_: ConnectionStats?, customUserProfile: Profile?) case groupMemberInfo(user: UserRef, groupInfo: GroupInfo, member: GroupMember, connectionStats_: ConnectionStats?) - case queueInfo(user: UserRef, rcvMsgInfo: RcvMsgInfo?, queueInfo: QueueInfo) + case queueInfo(user: UserRef, rcvMsgInfo: RcvMsgInfo?, queueInfo: ServerQueueInfo) case contactSwitchStarted(user: UserRef, contact: Contact, connectionStats: ConnectionStats) case groupMemberSwitchStarted(user: UserRef, groupInfo: GroupInfo, member: GroupMember, connectionStats: ConnectionStats) case contactSwitchAborted(user: UserRef, contact: Contact, connectionStats: ConnectionStats) @@ -555,12 +592,12 @@ public enum ChatResponse: Decodable, Error { case connectionVerified(user: UserRef, verified: Bool, expectedCode: String) case invitation(user: UserRef, connReqInvitation: String, connection: PendingContactConnection) case connectionIncognitoUpdated(user: UserRef, toConnection: PendingContactConnection) + case connectionUserChanged(user: UserRef, fromConnection: PendingContactConnection, toConnection: PendingContactConnection, newUser: UserRef) case connectionPlan(user: UserRef, connectionPlan: ConnectionPlan) case sentConfirmation(user: UserRef, connection: PendingContactConnection) case sentInvitation(user: UserRef, connection: PendingContactConnection) case sentInvitationToContact(user: UserRef, contact: Contact, customUserProfile: Profile?) case contactAlreadyExists(user: UserRef, contact: Contact) - case contactRequestAlreadyAccepted(user: UserRef, contact: Contact) case contactDeleted(user: UserRef, contact: Contact) case contactDeletedByContact(user: UserRef, contact: Contact) case chatCleared(user: UserRef, chatInfo: ChatInfo) @@ -588,11 +625,13 @@ public enum ChatResponse: Decodable, Error { case memberSubErrors(user: UserRef, memberSubErrors: [MemberSubError]) case groupEmpty(user: UserRef, groupInfo: GroupInfo) case userContactLinkSubscribed - case newChatItem(user: UserRef, chatItem: AChatItem) - case chatItemStatusUpdated(user: UserRef, chatItem: AChatItem) + case newChatItems(user: UserRef, chatItems: [AChatItem]) + case forwardPlan(user: UserRef, chatItemIds: [Int64], forwardConfirmation: ForwardConfirmation?) + case chatItemsStatusesUpdated(user: UserRef, chatItems: [AChatItem]) case chatItemUpdated(user: UserRef, chatItem: AChatItem) case chatItemNotChanged(user: UserRef, chatItem: AChatItem) case chatItemReaction(user: UserRef, added: Bool, reaction: ACIReaction) + case reactionMembers(user: UserRef, memberReactions: [MemberReaction]) case chatItemsDeleted(user: UserRef, chatItemDeletions: [ChatItemDeletion], byUser: Bool) case contactsList(user: UserRef, contacts: [Contact]) // group events @@ -600,6 +639,7 @@ public enum ChatResponse: Decodable, Error { case sentGroupInvitation(user: UserRef, groupInfo: GroupInfo, contact: Contact, member: GroupMember) case userAcceptedGroupSent(user: UserRef, groupInfo: GroupInfo, hostContact: Contact?) case groupLinkConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember) + case businessLinkConnecting(user: UserRef, groupInfo: GroupInfo, hostMember: GroupMember, fromContact: Contact) case userDeletedMember(user: UserRef, groupInfo: GroupInfo, member: GroupMember) case leftMemberUser(user: UserRef, groupInfo: GroupInfo) case groupMembers(user: UserRef, group: Group) @@ -663,8 +703,9 @@ public enum ChatResponse: Decodable, Error { case callInvitations(callInvitations: [RcvCallInvitation]) case ntfTokenStatus(status: NtfTknStatus) case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode, ntfServer: String) - case ntfMessages(user_: User?, connEntity_: ConnectionEntity?, msgTs: Date?, ntfMessage_: NtfMsgInfo?) - case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgInfo) + case ntfConns(ntfConns: [NtfConn]) + case connNtfMessages(receivedMsgs: [NtfMsgInfo?]) + case ntfMessage(user: UserRef, connEntity: ConnectionEntity, ntfMessage: NtfMsgAckInfo) case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection) case contactDisabled(user: UserRef, contact: Contact) // remote desktop responses/events @@ -701,8 +742,11 @@ public enum ChatResponse: Decodable, Error { case .apiChats: return "apiChats" case .apiChat: return "apiChat" case .chatItemInfo: return "chatItemInfo" - case .userProtoServers: return "userProtoServers" case .serverTestResult: return "serverTestResult" + case .serverOperatorConditions: return "serverOperators" + case .userServers: return "userServers" + case .userServersValidation: return "userServersValidation" + case .usageConditions: return "usageConditions" case .chatItemTTL: return "chatItemTTL" case .networkConfig: return "networkConfig" case .contactInfo: return "contactInfo" @@ -725,12 +769,12 @@ public enum ChatResponse: Decodable, Error { case .connectionVerified: return "connectionVerified" case .invitation: return "invitation" case .connectionIncognitoUpdated: return "connectionIncognitoUpdated" + case .connectionUserChanged: return "connectionUserChanged" case .connectionPlan: return "connectionPlan" case .sentConfirmation: return "sentConfirmation" case .sentInvitation: return "sentInvitation" case .sentInvitationToContact: return "sentInvitationToContact" case .contactAlreadyExists: return "contactAlreadyExists" - case .contactRequestAlreadyAccepted: return "contactRequestAlreadyAccepted" case .contactDeleted: return "contactDeleted" case .contactDeletedByContact: return "contactDeletedByContact" case .chatCleared: return "chatCleared" @@ -758,17 +802,20 @@ public enum ChatResponse: Decodable, Error { case .memberSubErrors: return "memberSubErrors" case .groupEmpty: return "groupEmpty" case .userContactLinkSubscribed: return "userContactLinkSubscribed" - case .newChatItem: return "newChatItem" - case .chatItemStatusUpdated: return "chatItemStatusUpdated" + case .newChatItems: return "newChatItems" + case .forwardPlan: return "forwardPlan" + case .chatItemsStatusesUpdated: return "chatItemsStatusesUpdated" case .chatItemUpdated: return "chatItemUpdated" case .chatItemNotChanged: return "chatItemNotChanged" case .chatItemReaction: return "chatItemReaction" + case .reactionMembers: return "reactionMembers" case .chatItemsDeleted: return "chatItemsDeleted" case .contactsList: return "contactsList" case .groupCreated: return "groupCreated" case .sentGroupInvitation: return "sentGroupInvitation" case .userAcceptedGroupSent: return "userAcceptedGroupSent" case .groupLinkConnecting: return "groupLinkConnecting" + case .businessLinkConnecting: return "businessLinkConnecting" case .userDeletedMember: return "userDeletedMember" case .leftMemberUser: return "leftMemberUser" case .groupMembers: return "groupMembers" @@ -829,7 +876,8 @@ public enum ChatResponse: Decodable, Error { case .callInvitations: return "callInvitations" case .ntfTokenStatus: return "ntfTokenStatus" case .ntfToken: return "ntfToken" - case .ntfMessages: return "ntfMessages" + case .ntfConns: return "ntfConns" + case .connNtfMessages: return "connNtfMessages" case .ntfMessage: return "ntfMessage" case .contactConnectionDeleted: return "contactConnectionDeleted" case .contactDisabled: return "contactDisabled" @@ -867,8 +915,11 @@ public enum ChatResponse: Decodable, Error { case let .apiChats(u, chats): return withUser(u, String(describing: chats)) case let .apiChat(u, chat): return withUser(u, String(describing: chat)) case let .chatItemInfo(u, chatItem, chatItemInfo): return withUser(u, "chatItem: \(String(describing: chatItem))\nchatItemInfo: \(String(describing: chatItemInfo))") - case let .userProtoServers(u, servers): return withUser(u, "servers: \(String(describing: servers))") case let .serverTestResult(u, server, testFailure): return withUser(u, "server: \(server)\nresult: \(String(describing: testFailure))") + case let .serverOperatorConditions(conditions): return "conditions: \(String(describing: conditions))" + case let .userServers(u, userServers): return withUser(u, "userServers: \(String(describing: userServers))") + case let .userServersValidation(u, serverErrors): return withUser(u, "serverErrors: \(String(describing: serverErrors))") + case let .usageConditions(usageConditions, _, acceptedConditions): return "usageConditions: \(String(describing: usageConditions))\nacceptedConditions: \(String(describing: acceptedConditions))" case let .chatItemTTL(u, chatItemTTL): return withUser(u, String(describing: chatItemTTL)) case let .networkConfig(networkConfig): return String(describing: networkConfig) case let .contactInfo(u, contact, connectionStats_, customUserProfile): return withUser(u, "contact: \(String(describing: contact))\nconnectionStats_: \(String(describing: connectionStats_))\ncustomUserProfile: \(String(describing: customUserProfile))") @@ -893,12 +944,12 @@ public enum ChatResponse: Decodable, Error { case let .connectionVerified(u, verified, expectedCode): return withUser(u, "verified: \(verified)\nconnectionCode: \(expectedCode)") case let .invitation(u, connReqInvitation, connection): return withUser(u, "connReqInvitation: \(connReqInvitation)\nconnection: \(connection)") case let .connectionIncognitoUpdated(u, toConnection): return withUser(u, String(describing: toConnection)) + case let .connectionUserChanged(u, fromConnection, toConnection, newUser): return withUser(u, "fromConnection: \(String(describing: fromConnection))\ntoConnection: \(String(describing: toConnection))\newUserId: \(String(describing: newUser.userId))") case let .connectionPlan(u, connectionPlan): return withUser(u, String(describing: connectionPlan)) case let .sentConfirmation(u, connection): return withUser(u, String(describing: connection)) case let .sentInvitation(u, connection): return withUser(u, String(describing: connection)) case let .sentInvitationToContact(u, contact, _): return withUser(u, String(describing: contact)) case let .contactAlreadyExists(u, contact): return withUser(u, String(describing: contact)) - case let .contactRequestAlreadyAccepted(u, contact): return withUser(u, String(describing: contact)) case let .contactDeleted(u, contact): return withUser(u, String(describing: contact)) case let .contactDeletedByContact(u, contact): return withUser(u, String(describing: contact)) case let .chatCleared(u, chatInfo): return withUser(u, String(describing: chatInfo)) @@ -926,11 +977,17 @@ public enum ChatResponse: Decodable, Error { case let .memberSubErrors(u, memberSubErrors): return withUser(u, String(describing: memberSubErrors)) case let .groupEmpty(u, groupInfo): return withUser(u, String(describing: groupInfo)) case .userContactLinkSubscribed: return noDetails - case let .newChatItem(u, chatItem): return withUser(u, String(describing: chatItem)) - case let .chatItemStatusUpdated(u, chatItem): return withUser(u, String(describing: chatItem)) + case let .newChatItems(u, chatItems): + let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n") + return withUser(u, itemsString) + case let .forwardPlan(u, chatItemIds, forwardConfirmation): return withUser(u, "items: \(chatItemIds) forwardConfirmation: \(String(describing: forwardConfirmation))") + case let .chatItemsStatusesUpdated(u, chatItems): + let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n") + return withUser(u, itemsString) case let .chatItemUpdated(u, chatItem): return withUser(u, String(describing: chatItem)) case let .chatItemNotChanged(u, chatItem): return withUser(u, String(describing: chatItem)) case let .chatItemReaction(u, added, reaction): return withUser(u, "added: \(added)\n\(String(describing: reaction))") + case let .reactionMembers(u, reaction): return withUser(u, "memberReactions: \(String(describing: reaction))") case let .chatItemsDeleted(u, items, byUser): let itemsString = items.map { item in "deletedChatItem:\n\(String(describing: item.deletedChatItem))\ntoChatItem:\n\(String(describing: item.toChatItem))" }.joined(separator: "\n") @@ -940,6 +997,7 @@ public enum ChatResponse: Decodable, Error { case let .sentGroupInvitation(u, groupInfo, contact, member): return withUser(u, "groupInfo: \(groupInfo)\ncontact: \(contact)\nmember: \(member)") case let .userAcceptedGroupSent(u, groupInfo, hostContact): return withUser(u, "groupInfo: \(groupInfo)\nhostContact: \(String(describing: hostContact))") case let .groupLinkConnecting(u, groupInfo, hostMember): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(String(describing: hostMember))") + case let .businessLinkConnecting(u, groupInfo, hostMember, fromContact): return withUser(u, "groupInfo: \(groupInfo)\nhostMember: \(String(describing: hostMember))\nfromContact: \(String(describing: fromContact))") case let .userDeletedMember(u, groupInfo, member): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)") case let .leftMemberUser(u, groupInfo): return withUser(u, String(describing: groupInfo)) case let .groupMembers(u, group): return withUser(u, String(describing: group)) @@ -1000,7 +1058,8 @@ public enum ChatResponse: Decodable, Error { case let .callInvitations(invs): return String(describing: invs) case let .ntfTokenStatus(status): return String(describing: status) case let .ntfToken(token, status, ntfMode, ntfServer): return "token: \(token)\nstatus: \(status.rawValue)\nntfMode: \(ntfMode.rawValue)\nntfServer: \(ntfServer)" - case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))") + case let .ntfConns(ntfConns): return String(describing: ntfConns) + case let .connNtfMessages(receivedMsgs): return "receivedMsgs: \(String(describing: receivedMsgs))" case let .ntfMessage(u, connEntity, ntfMessage): return withUser(u, "connEntity: \(String(describing: connEntity))\nntfMessage: \(String(describing: ntfMessage))") case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection)) case let .contactDisabled(u, contact): return withUser(u, String(describing: contact)) @@ -1094,12 +1153,12 @@ public enum GroupLinkPlan: Decodable, Hashable { case known(groupInfo: GroupInfo) } -struct NewUser: Encodable, Hashable { +struct NewUser: Encodable { var profile: Profile? var pastTimestamp: Bool } -public enum ChatPagination: Hashable { +public enum ChatPagination { case last(count: Int) case after(chatItemId: Int64, count: Int) case before(chatItemId: Int64, count: Int) @@ -1113,10 +1172,16 @@ public enum ChatPagination: Hashable { } } -struct ComposedMessage: Encodable { - var fileSource: CryptoFile? +public struct ComposedMessage: Encodable { + public var fileSource: CryptoFile? var quotedItemId: Int64? - var msgContent: MsgContent + public var msgContent: MsgContent + + public init(fileSource: CryptoFile? = nil, quotedItemId: Int64? = nil, msgContent: MsgContent) { + self.fileSource = fileSource + self.quotedItemId = quotedItemId + self.msgContent = msgContent + } } public struct ArchiveConfig: Encodable { @@ -1139,86 +1204,389 @@ public struct DBEncryptionConfig: Codable { public var newKey: String } -struct SMPServersConfig: Encodable { - var smpServers: [ServerCfg] -} - public enum ServerProtocol: String, Decodable { case smp case xftp } -public struct ProtoServersConfig: Codable { - public var servers: [ServerCfg] +public enum OperatorTag: String, Codable { + case simplex = "simplex" + case flux = "flux" } -public struct UserProtoServers: Decodable { - public var serverProtocol: ServerProtocol - public var protoServers: [ServerCfg] - public var presetServers: [ServerCfg] +public struct ServerOperatorInfo { + public var description: [String] + public var website: URL + public var selfhost: (text: String, link: URL)? = nil + public var logo: String + public var largeLogo: String + public var logoDarkMode: String + public var largeLogoDarkMode: String } -public struct ServerCfg: Identifiable, Equatable, Codable, Hashable { +public let operatorsInfo: Dictionary = [ + .simplex: ServerOperatorInfo( + description: [ + "SimpleX Chat is the first communication network that has no user profile IDs of any kind, not even random numbers or identity keys.", + "SimpleX Chat Ltd develops the communication software for SimpleX network." + ], + website: URL(string: "https://simplex.chat")!, + logo: "decentralized", + largeLogo: "logo", + logoDarkMode: "decentralized-light", + largeLogoDarkMode: "logo-light" + ), + .flux: ServerOperatorInfo( + description: [ + "Flux is the largest decentralized cloud, based on a global network of user-operated nodes.", + "Flux offers a powerful, scalable, and affordable cutting edge technology platform for all.", + "Flux operates servers in SimpleX network to improve its privacy and decentralization." + ], + website: URL(string: "https://runonflux.com")!, + selfhost: (text: "Self-host SimpleX servers on Flux", link: URL(string: "https://home.runonflux.io/apps/marketplace?q=simplex")!), + logo: "flux_logo_symbol", + largeLogo: "flux_logo", + logoDarkMode: "flux_logo_symbol", + largeLogoDarkMode: "flux_logo-light" + ), +] + +public struct UsageConditions: Decodable { + public var conditionsId: Int64 + public var conditionsCommit: String + public var notifiedAt: Date? + public var createdAt: Date + + public static var sampleData = UsageConditions( + conditionsId: 1, + conditionsCommit: "11a44dc1fd461a93079f897048b46998db55da5c", + notifiedAt: nil, + createdAt: Date.now + ) +} + +public enum UsageConditionsAction: Decodable { + case review(operators: [ServerOperator], deadline: Date?, showNotice: Bool) + case accepted(operators: [ServerOperator]) + + public var showNotice: Bool { + switch self { + case let .review(_, _, showNotice): showNotice + case .accepted: false + } + } +} + +public struct ServerOperatorConditions: Decodable { + public var serverOperators: [ServerOperator] + public var currentConditions: UsageConditions + public var conditionsAction: UsageConditionsAction? + + public static var empty = ServerOperatorConditions( + serverOperators: [], + currentConditions: UsageConditions(conditionsId: 0, conditionsCommit: "empty", notifiedAt: nil, createdAt: .now), + conditionsAction: nil + ) +} + +public enum ConditionsAcceptance: Equatable, Codable, Hashable { + case accepted(acceptedAt: Date?) + // If deadline is present, it means there's a grace period to review and accept conditions during which user can continue to use the operator. + // No deadline indicates it's required to accept conditions for the operator to start using it. + case required(deadline: Date?) + + public var conditionsAccepted: Bool { + switch self { + case .accepted: true + case .required: false + } + } + + public var usageAllowed: Bool { + switch self { + case .accepted: true + case let .required(deadline): deadline != nil + } + } +} + +public struct ServerOperator: Identifiable, Equatable, Codable { + public var operatorId: Int64 + public var operatorTag: OperatorTag? + public var tradeName: String + public var legalName: String? + public var serverDomains: [String] + public var conditionsAcceptance: ConditionsAcceptance + public var enabled: Bool + public var smpRoles: ServerRoles + public var xftpRoles: ServerRoles + + public var id: Int64 { operatorId } + + public static func == (l: ServerOperator, r: ServerOperator) -> Bool { + l.operatorId == r.operatorId && l.operatorTag == r.operatorTag && l.tradeName == r.tradeName && l.legalName == r.legalName && + l.serverDomains == r.serverDomains && l.conditionsAcceptance == r.conditionsAcceptance && l.enabled == r.enabled && + l.smpRoles == r.smpRoles && l.xftpRoles == r.xftpRoles + } + + public var legalName_: String { + legalName ?? tradeName + } + + public var info: ServerOperatorInfo { + return if let operatorTag = operatorTag { + operatorsInfo[operatorTag] ?? ServerOperator.dummyOperatorInfo + } else { + ServerOperator.dummyOperatorInfo + } + } + + public static let dummyOperatorInfo = ServerOperatorInfo( + description: ["Default"], + website: URL(string: "https://simplex.chat")!, + logo: "decentralized", + largeLogo: "logo", + logoDarkMode: "decentralized-light", + largeLogoDarkMode: "logo-light" + ) + + public func logo(_ colorScheme: ColorScheme) -> String { + colorScheme == .light ? info.logo : info.logoDarkMode + } + + public func largeLogo(_ colorScheme: ColorScheme) -> String { + colorScheme == .light ? info.largeLogo : info.largeLogoDarkMode + } + + public static var sampleData1 = ServerOperator( + operatorId: 1, + operatorTag: .simplex, + tradeName: "SimpleX Chat", + legalName: "SimpleX Chat Ltd", + serverDomains: ["simplex.im"], + conditionsAcceptance: .accepted(acceptedAt: nil), + enabled: true, + smpRoles: ServerRoles(storage: true, proxy: true), + xftpRoles: ServerRoles(storage: true, proxy: true) + ) +} + +public struct ServerRoles: Equatable, Codable { + public var storage: Bool + public var proxy: Bool +} + +public struct UserOperatorServers: Identifiable, Equatable, Codable { + public var `operator`: ServerOperator? + public var smpServers: [UserServer] + public var xftpServers: [UserServer] + + public var id: String { + if let op = self.operator { + "\(op.operatorId)" + } else { + "nil operator" + } + } + + public var operator_: ServerOperator { + get { + self.operator ?? ServerOperator( + operatorId: 0, + operatorTag: nil, + tradeName: "", + legalName: "", + serverDomains: [], + conditionsAcceptance: .accepted(acceptedAt: nil), + enabled: false, + smpRoles: ServerRoles(storage: true, proxy: true), + xftpRoles: ServerRoles(storage: true, proxy: true) + ) + } + set { `operator` = newValue } + } + + public static var sampleData1 = UserOperatorServers( + operator: ServerOperator.sampleData1, + smpServers: [UserServer.sampleData.preset], + xftpServers: [UserServer.sampleData.xftpPreset] + ) + + public static var sampleDataNilOperator = UserOperatorServers( + operator: nil, + smpServers: [UserServer.sampleData.preset], + xftpServers: [UserServer.sampleData.xftpPreset] + ) +} + +public enum UserServersError: Decodable { + case noServers(protocol: ServerProtocol, user: UserRef?) + case storageMissing(protocol: ServerProtocol, user: UserRef?) + case proxyMissing(protocol: ServerProtocol, user: UserRef?) + case duplicateServer(protocol: ServerProtocol, duplicateServer: String, duplicateHost: String) + + public var globalError: String? { + switch self { + case let .noServers(`protocol`, _): + switch `protocol` { + case .smp: return globalSMPError + case .xftp: return globalXFTPError + } + case let .storageMissing(`protocol`, _): + switch `protocol` { + case .smp: return globalSMPError + case .xftp: return globalXFTPError + } + case let .proxyMissing(`protocol`, _): + switch `protocol` { + case .smp: return globalSMPError + case .xftp: return globalXFTPError + } + default: return nil + } + } + + public var globalSMPError: String? { + switch self { + case let .noServers(.smp, user): + let text = NSLocalizedString("No message servers.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + case let .storageMissing(.smp, user): + let text = NSLocalizedString("No servers to receive messages.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + case let .proxyMissing(.smp, user): + let text = NSLocalizedString("No servers for private message routing.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + default: + return nil + } + } + + public var globalXFTPError: String? { + switch self { + case let .noServers(.xftp, user): + let text = NSLocalizedString("No media & file servers.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + case let .storageMissing(.xftp, user): + let text = NSLocalizedString("No servers to send files.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + case let .proxyMissing(.xftp, user): + let text = NSLocalizedString("No servers to receive files.", comment: "servers error") + if let user = user { + return userStr(user) + " " + text + } else { + return text + } + default: + return nil + } + } + + private func userStr(_ user: UserRef) -> String { + String.localizedStringWithFormat(NSLocalizedString("For chat profile %@:", comment: "servers error"), user.localDisplayName) + } +} + +public struct UserServer: Identifiable, Equatable, Codable, Hashable { + public var serverId: Int64? public var server: String public var preset: Bool public var tested: Bool? public var enabled: Bool + public var deleted: Bool var createdAt = Date() -// public var sendEnabled: Bool // can we potentially want to prevent sending on the servers we use to receive? -// Even if we don't see the use case, it's probably better to allow it in the model -// In any case, "trusted/known" servers are out of scope of this change - public init(server: String, preset: Bool, tested: Bool?, enabled: Bool) { + public init(serverId: Int64?, server: String, preset: Bool, tested: Bool?, enabled: Bool, deleted: Bool) { + self.serverId = serverId self.server = server self.preset = preset self.tested = tested self.enabled = enabled + self.deleted = deleted } - public static func == (l: ServerCfg, r: ServerCfg) -> Bool { - l.server == r.server && l.preset == r.preset && l.tested == r.tested && l.enabled == r.enabled + public static func == (l: UserServer, r: UserServer) -> Bool { + l.serverId == r.serverId && l.server == r.server && l.preset == r.preset && l.tested == r.tested && + l.enabled == r.enabled && l.deleted == r.deleted } public var id: String { "\(server) \(createdAt)" } - public static var empty = ServerCfg(server: "", preset: false, tested: nil, enabled: false) + public static var empty = UserServer(serverId: nil, server: "", preset: false, tested: nil, enabled: false, deleted: false) public var isEmpty: Bool { server.trimmingCharacters(in: .whitespaces) == "" } public struct SampleData { - public var preset: ServerCfg - public var custom: ServerCfg - public var untested: ServerCfg + public var preset: UserServer + public var custom: UserServer + public var untested: UserServer + public var xftpPreset: UserServer } public static var sampleData = SampleData( - preset: ServerCfg( + preset: UserServer( + serverId: 1, server: "smp://abcd@smp8.simplex.im", preset: true, tested: true, - enabled: true + enabled: true, + deleted: false ), - custom: ServerCfg( + custom: UserServer( + serverId: 2, server: "smp://abcd@smp9.simplex.im", preset: false, tested: false, - enabled: false + enabled: false, + deleted: false ), - untested: ServerCfg( + untested: UserServer( + serverId: 3, server: "smp://abcd@smp10.simplex.im", preset: false, tested: nil, - enabled: true + enabled: true, + deleted: false + ), + xftpPreset: UserServer( + serverId: 4, + server: "xftp://abcd@xftp8.simplex.im", + preset: true, + tested: true, + enabled: true, + deleted: false ) ) enum CodingKeys: CodingKey { + case serverId case server case preset case tested case enabled + case deleted } } @@ -1315,14 +1683,15 @@ public struct ServerAddress: Decodable { ) } -public struct NetCfg: Codable, Equatable, Hashable { +public struct NetCfg: Codable, Equatable { public var socksProxy: String? = nil var socksMode: SocksMode = .always public var hostMode: HostMode = .publicHost public var requiredHostMode = true public var sessionMode = TransportSessionMode.user - public var smpProxyMode: SMPProxyMode = .unknown + public var smpProxyMode: SMPProxyMode = .always public var smpProxyFallback: SMPProxyFallback = .allowProtected + public var smpWebPort = false public var tcpConnectTimeout: Int // microseconds public var tcpTimeout: Int // microseconds public var tcpTimeoutPerKb: Int // microseconds @@ -1369,18 +1738,18 @@ public struct NetCfg: Codable, Equatable, Hashable { public var enableKeepAlive: Bool { tcpKeepAlive != nil } } -public enum HostMode: String, Codable, Hashable { +public enum HostMode: String, Codable { case onionViaSocks case onionHost = "onion" case publicHost = "public" } -public enum SocksMode: String, Codable, Hashable { +public enum SocksMode: String, Codable { case always = "always" case onion = "onion" } -public enum SMPProxyMode: String, Codable, Hashable, SelectableItem { +public enum SMPProxyMode: String, Codable, SelectableItem { case always = "always" case unknown = "unknown" case unprotected = "unprotected" @@ -1400,7 +1769,7 @@ public enum SMPProxyMode: String, Codable, Hashable, SelectableItem { public static let values: [SMPProxyMode] = [.always, .unknown, .unprotected, .never] } -public enum SMPProxyFallback: String, Codable, Hashable, SelectableItem { +public enum SMPProxyFallback: String, Codable, SelectableItem { case allow = "allow" case allowProtected = "allowProtected" case prohibit = "prohibit" @@ -1418,7 +1787,7 @@ public enum SMPProxyFallback: String, Codable, Hashable, SelectableItem { public static let values: [SMPProxyFallback] = [.allow, .allowProtected, .prohibit] } -public enum OnionHosts: String, Identifiable, Hashable { +public enum OnionHosts: String, Identifiable { case no case prefer case require @@ -1452,23 +1821,27 @@ public enum OnionHosts: String, Identifiable, Hashable { public static let values: [OnionHosts] = [.no, .prefer, .require] } -public enum TransportSessionMode: String, Codable, Identifiable, Hashable { +public enum TransportSessionMode: String, Codable, Identifiable { case user + case session + case server case entity public var text: LocalizedStringKey { switch self { - case .user: return "User profile" + case .user: return "Chat profile" + case .session: return "App session" + case .server: return "Server" case .entity: return "Connection" } } public var id: TransportSessionMode { self } - public static let values: [TransportSessionMode] = [.user, .entity] + public static let values: [TransportSessionMode] = [.user, .session, .server, .entity] } -public struct KeepAliveOpts: Codable, Equatable, Hashable { +public struct KeepAliveOpts: Codable, Equatable { public var keepIdle: Int // seconds public var keepIntvl: Int // seconds public var keepCnt: Int // times @@ -1476,7 +1849,64 @@ public struct KeepAliveOpts: Codable, Equatable, Hashable { public static let defaults: KeepAliveOpts = KeepAliveOpts(keepIdle: 30, keepIntvl: 15, keepCnt: 4) } -public enum NetworkStatus: Decodable, Equatable, Hashable { +public struct NetworkProxy: Equatable, Codable { + public var host: String = "" + public var port: Int = 0 + public var auth: NetworkProxyAuth = .username + public var username: String = "" + public var password: String = "" + + public static var def: NetworkProxy { + NetworkProxy() + } + + public var valid: Bool { + let hostOk = switch NWEndpoint.Host(host) { + case .ipv4: true + case .ipv6: true + default: false + } + return hostOk && + port > 0 && port <= 65535 && + NetworkProxy.validCredential(username) && NetworkProxy.validCredential(password) + } + + public static func validCredential(_ s: String) -> Bool { + !s.contains(":") && !s.contains("@") + } + + public func toProxyString() -> String? { + if !valid { return nil } + var res = "" + switch auth { + case .username: + let usernameTrimmed = username.trimmingCharacters(in: .whitespaces) + let passwordTrimmed = password.trimmingCharacters(in: .whitespaces) + if usernameTrimmed != "" || passwordTrimmed != "" { + res += usernameTrimmed + ":" + passwordTrimmed + "@" + } else { + res += "@" + } + case .isolate: () + } + if host != "" { + if host.contains(":") { + res += "[\(host.trimmingCharacters(in: [" ", "[", "]"]))]" + } else { + res += host.trimmingCharacters(in: .whitespaces) + } + } + res += ":\(port)" + return res + } +} + +public enum NetworkProxyAuth: String, Codable { + case username + case isolate +} + +public enum NetworkStatus: Decodable, Equatable { case unknown case connected case disconnected @@ -1514,7 +1944,14 @@ public enum NetworkStatus: Decodable, Equatable, Hashable { } } -public struct ConnNetworkStatus: Decodable, Hashable { +public enum ForwardConfirmation: Decodable, Hashable { + case filesNotAccepted(fileIds: [Int64]) + case filesInProgress(filesCount: Int) + case filesMissing(filesCount: Int) + case filesFailed(filesCount: Int) +} + +public struct ConnNetworkStatus: Decodable { public var agentConnId: String public var networkStatus: NetworkStatus } @@ -1539,7 +1976,7 @@ public enum MsgFilter: String, Codable, Hashable { case mentions } -public struct UserMsgReceiptSettings: Codable, Hashable { +public struct UserMsgReceiptSettings: Codable { public var enable: Bool public var clearOverrides: Bool @@ -1588,7 +2025,7 @@ public enum SndSwitchStatus: String, Codable, Hashable { case sendingQTEST = "sending_qtest" } -public enum QueueDirection: String, Decodable, Hashable { +public enum QueueDirection: String, Decodable { case rcv case snd } @@ -1627,28 +2064,35 @@ public struct UserContactLink: Decodable, Hashable { } public struct AutoAccept: Codable, Hashable { + public var businessAddress: Bool public var acceptIncognito: Bool public var autoReply: MsgContent? - public init(acceptIncognito: Bool, autoReply: MsgContent? = nil) { + public init(businessAddress: Bool, acceptIncognito: Bool, autoReply: MsgContent? = nil) { + self.businessAddress = businessAddress self.acceptIncognito = acceptIncognito self.autoReply = autoReply } static func cmdString(_ autoAccept: AutoAccept?) -> String { guard let autoAccept = autoAccept else { return "off" } - let s = "on" + (autoAccept.acceptIncognito ? " incognito=on" : "") + var s = "on" + if autoAccept.acceptIncognito { + s += " incognito=on" + } else if autoAccept.businessAddress { + s += " business" + } guard let msg = autoAccept.autoReply else { return s } return s + " " + msg.cmdString } } -public protocol SelectableItem: Hashable, Identifiable { +public protocol SelectableItem: Identifiable, Equatable { var label: LocalizedStringKey { get } static var values: [Self] { get } } -public struct DeviceToken: Decodable, Hashable { +public struct DeviceToken: Decodable { var pushProvider: PushProvider var token: String @@ -1662,12 +2106,12 @@ public struct DeviceToken: Decodable, Hashable { } } -public enum PushEnvironment: String, Hashable { +public enum PushEnvironment: String { case development case production } -public enum PushProvider: String, Decodable, Hashable { +public enum PushProvider: String, Decodable { case apns_dev case apns_prod @@ -1681,16 +2125,24 @@ public enum PushProvider: String, Decodable, Hashable { // This notification mode is for app core, UI uses AppNotificationsMode.off to mean completely disable, // and .local for periodic background checks -public enum NotificationsMode: String, Decodable, SelectableItem, Hashable { +public enum NotificationsMode: String, Decodable, SelectableItem { case off = "OFF" case periodic = "PERIODIC" case instant = "INSTANT" public var label: LocalizedStringKey { switch self { - case .off: "Local" - case .periodic: "Periodically" - case .instant: "Instantly" + case .off: "No push server" + case .periodic: "Periodic" + case .instant: "Instant" + } + } + + public var icon: String { + switch self { + case .off: return "arrow.clockwise" + case .periodic: return "timer" + case .instant: return "bolt" } } @@ -1699,7 +2151,7 @@ public enum NotificationsMode: String, Decodable, SelectableItem, Hashable { public static var values: [NotificationsMode] = [.instant, .periodic, .off] } -public enum NotificationPreviewMode: String, SelectableItem, Codable, Hashable { +public enum NotificationPreviewMode: String, SelectableItem, Codable { case hidden case contact case message @@ -1717,7 +2169,7 @@ public enum NotificationPreviewMode: String, SelectableItem, Codable, Hashable { public static var values: [NotificationPreviewMode] = [.message, .contact, .hidden] } -public struct RemoteCtrlInfo: Decodable, Hashable { +public struct RemoteCtrlInfo: Decodable { public var remoteCtrlId: Int64 public var ctrlDeviceName: String public var sessionState: RemoteCtrlSessionState? @@ -1727,7 +2179,7 @@ public struct RemoteCtrlInfo: Decodable, Hashable { } } -public enum RemoteCtrlSessionState: Decodable, Hashable { +public enum RemoteCtrlSessionState: Decodable { case starting case searching case connecting @@ -1742,17 +2194,17 @@ public enum RemoteCtrlStopReason: Decodable { case disconnected } -public struct CtrlAppInfo: Decodable, Hashable { +public struct CtrlAppInfo: Decodable { public var appVersionRange: AppVersionRange public var deviceName: String } -public struct AppVersionRange: Decodable, Hashable { +public struct AppVersionRange: Decodable { public var minVersion: String public var maxVersion: String } -public struct CoreVersionInfo: Decodable, Hashable { +public struct CoreVersionInfo: Decodable { public var version: String public var simplexmqVersion: String public var simplexmqCommit: String @@ -1842,7 +2294,6 @@ public enum ChatErrorType: Decodable, Hashable { case inlineFileProhibited(fileId: Int64) case invalidQuote case invalidForward - case forwardNoFile case invalidChatItemUpdate case invalidChatItemDelete case hasCurrentCall @@ -1857,6 +2308,7 @@ public enum ChatErrorType: Decodable, Hashable { case agentCommandError(message: String) case invalidFileDescription(message: String) case connectionIncognitoChangeProhibited + case connectionUserChangeProhibited case peerChatVRangeIncompatible case internalError(message: String) case exception(message: String) @@ -1936,7 +2388,7 @@ public enum SQLiteError: Decodable, Hashable { } public enum AgentErrorType: Decodable, Hashable { - case CMD(cmdErr: CommandErrorType) + case CMD(cmdErr: CommandErrorType, errContext: String) case CONN(connErr: ConnectionErrorType) case SMP(serverAddress: String, smpErr: ProtocolErrorType) case NTF(ntfErr: ProtocolErrorType) @@ -1983,6 +2435,7 @@ public enum ProtocolErrorType: Decodable, Hashable { case AUTH case CRYPTO case QUOTA + case STORE(storeErr: String) case NO_MSG case LARGE_MSG case EXPIRED @@ -2090,20 +2543,22 @@ public enum RemoteCtrlError: Decodable, Hashable { case protocolError } -public struct MigrationFileLinkData: Codable, Hashable { +public struct MigrationFileLinkData: Codable { let networkConfig: NetworkConfig? public init(networkConfig: NetworkConfig) { self.networkConfig = networkConfig } - public struct NetworkConfig: Codable, Hashable { + public struct NetworkConfig: Codable { let socksProxy: String? + let networkProxy: NetworkProxy? let hostMode: HostMode? let requiredHostMode: Bool? - public init(socksProxy: String?, hostMode: HostMode?, requiredHostMode: Bool?) { + public init(socksProxy: String?, networkProxy: NetworkProxy?, hostMode: HostMode?, requiredHostMode: Bool?) { self.socksProxy = socksProxy + self.networkProxy = networkProxy self.hostMode = hostMode self.requiredHostMode = requiredHostMode } @@ -2112,6 +2567,7 @@ public struct MigrationFileLinkData: Codable, Hashable { return if let hostMode, let requiredHostMode { NetworkConfig( socksProxy: nil, + networkProxy: nil, hostMode: hostMode == .onionViaSocks ? .onionHost : hostMode, requiredHostMode: requiredHostMode ) @@ -2129,8 +2585,9 @@ public struct MigrationFileLinkData: Codable, Hashable { } } -public struct AppSettings: Codable, Equatable, Hashable { +public struct AppSettings: Codable, Equatable { public var networkConfig: NetCfg? = nil + public var networkProxy: NetworkProxy? = nil public var privacyEncryptLocalFiles: Bool? = nil public var privacyAskToApproveRelays: Bool? = nil public var privacyAcceptImages: Bool? = nil @@ -2152,16 +2609,20 @@ public struct AppSettings: Codable, Equatable, Hashable { public var iosCallKitEnabled: Bool? = nil public var iosCallKitCallsInRecents: Bool? = nil public var uiProfileImageCornerRadius: Double? = nil + public var uiChatItemRoundness: Double? = nil + public var uiChatItemTail: Bool? = nil public var uiColorScheme: String? = nil public var uiDarkColorScheme: String? = nil public var uiCurrentThemeIds: [String: String]? = nil public var uiThemes: [ThemeOverrides]? = nil public var oneHandUI: Bool? = nil + public var chatBottomBar: Bool? = nil public func prepareForExport() -> AppSettings { var empty = AppSettings() let def = AppSettings.defaults if networkConfig != def.networkConfig { empty.networkConfig = networkConfig } + if networkProxy != def.networkProxy { empty.networkProxy = networkProxy } if privacyEncryptLocalFiles != def.privacyEncryptLocalFiles { empty.privacyEncryptLocalFiles = privacyEncryptLocalFiles } if privacyAskToApproveRelays != def.privacyAskToApproveRelays { empty.privacyAskToApproveRelays = privacyAskToApproveRelays } if privacyAcceptImages != def.privacyAcceptImages { empty.privacyAcceptImages = privacyAcceptImages } @@ -2183,17 +2644,21 @@ public struct AppSettings: Codable, Equatable, Hashable { if iosCallKitEnabled != def.iosCallKitEnabled { empty.iosCallKitEnabled = iosCallKitEnabled } if iosCallKitCallsInRecents != def.iosCallKitCallsInRecents { empty.iosCallKitCallsInRecents = iosCallKitCallsInRecents } if uiProfileImageCornerRadius != def.uiProfileImageCornerRadius { empty.uiProfileImageCornerRadius = uiProfileImageCornerRadius } + if uiChatItemRoundness != def.uiChatItemRoundness { empty.uiChatItemRoundness = uiChatItemRoundness } + if uiChatItemTail != def.uiChatItemTail { empty.uiChatItemTail = uiChatItemTail } if uiColorScheme != def.uiColorScheme { empty.uiColorScheme = uiColorScheme } if uiDarkColorScheme != def.uiDarkColorScheme { empty.uiDarkColorScheme = uiDarkColorScheme } if uiCurrentThemeIds != def.uiCurrentThemeIds { empty.uiCurrentThemeIds = uiCurrentThemeIds } if uiThemes != def.uiThemes { empty.uiThemes = uiThemes } if oneHandUI != def.oneHandUI { empty.oneHandUI = oneHandUI } + if chatBottomBar != def.chatBottomBar { empty.chatBottomBar = chatBottomBar } return empty } public static var defaults: AppSettings { AppSettings ( networkConfig: NetCfg.defaults, + networkProxy: NetworkProxy.def, privacyEncryptLocalFiles: true, privacyAskToApproveRelays: true, privacyAcceptImages: true, @@ -2215,16 +2680,19 @@ public struct AppSettings: Codable, Equatable, Hashable { iosCallKitEnabled: true, iosCallKitCallsInRecents: false, uiProfileImageCornerRadius: 22.5, + uiChatItemRoundness: 0.75, + uiChatItemTail: true, uiColorScheme: DefaultTheme.SYSTEM_THEME_NAME, uiDarkColorScheme: DefaultTheme.SIMPLEX.themeName, uiCurrentThemeIds: nil as [String: String]?, uiThemes: nil as [ThemeOverrides]?, - oneHandUI: false + oneHandUI: true, + chatBottomBar: true ) } } -public enum AppSettingsNotificationMode: String, Codable, Hashable { +public enum AppSettingsNotificationMode: String, Codable { case off case periodic case instant @@ -2252,13 +2720,13 @@ public enum AppSettingsNotificationMode: String, Codable, Hashable { // case message //} -public enum AppSettingsLockScreenCalls: String, Codable, Hashable { +public enum AppSettingsLockScreenCalls: String, Codable { case disable case show case accept } -public struct UserNetworkInfo: Codable, Equatable, Hashable { +public struct UserNetworkInfo: Codable, Equatable { public let networkType: UserNetworkType public let online: Bool @@ -2268,7 +2736,7 @@ public struct UserNetworkInfo: Codable, Equatable, Hashable { } } -public enum UserNetworkType: String, Codable, Hashable { +public enum UserNetworkType: String, Codable { case none case cellular case wifi @@ -2286,7 +2754,7 @@ public enum UserNetworkType: String, Codable, Hashable { } } -public struct RcvMsgInfo: Codable, Hashable { +public struct RcvMsgInfo: Codable { var msgId: Int64 var msgDeliveryId: Int64 var msgDeliveryStatus: String @@ -2294,7 +2762,16 @@ public struct RcvMsgInfo: Codable, Hashable { var agentMsgMeta: String } -public struct QueueInfo: Codable, Hashable { +public struct ServerQueueInfo: Codable { + var server: String + var rcvId: String + var sndId: String + var ntfId: String? + var status: String + var info: QueueInfo +} + +public struct QueueInfo: Codable { var qiSnd: Bool var qiNtf: Bool var qiSub: QSub? @@ -2302,25 +2779,25 @@ public struct QueueInfo: Codable, Hashable { var qiMsg: MsgInfo? } -public struct QSub: Codable, Hashable { +public struct QSub: Codable { var qSubThread: QSubThread var qDelivered: String? } -public enum QSubThread: String, Codable, Hashable { +public enum QSubThread: String, Codable { case noSub case subPending case subThread case prohibitSub } -public struct MsgInfo: Codable, Hashable { +public struct MsgInfo: Codable { var msgId: String var msgTs: Date var msgType: MsgType } -public enum MsgType: String, Codable, Hashable { +public enum MsgType: String, Codable { case message case quota } diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index bd38f3568c..c754f0740d 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -35,6 +35,7 @@ public let GROUP_DEFAULT_PRIVACY_ASK_TO_APPROVE_RELAYS = "privacyAskToApproveRel // replaces DEFAULT_PROFILE_IMAGE_CORNER_RADIUS public let GROUP_DEFAULT_PROFILE_IMAGE_CORNER_RADIUS = "profileImageCornerRadius" let GROUP_DEFAULT_NTF_BADGE_COUNT = "ntgBadgeCount" +public let GROUP_DEFAULT_NETWORK_SOCKS_PROXY = "networkSocksProxy" let GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS = "networkUseOnionHosts" let GROUP_DEFAULT_NETWORK_SESSION_MODE = "networkSessionMode" let GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE = "networkSMPProxyMode" @@ -56,6 +57,7 @@ public let GROUP_DEFAULT_CONFIRM_DB_UPGRADES = "confirmDBUpgrades" public let GROUP_DEFAULT_CALL_KIT_ENABLED = "callKitEnabled" public let GROUP_DEFAULT_PQ_EXPERIMENTAL_ENABLED = "pqExperimentalEnabled" // no longer used public let GROUP_DEFAULT_ONE_HAND_UI = "oneHandUI" +public let GROUP_DEFAULT_CHAT_BOTTOM_BAR = "chatBottomBar" public let APP_GROUP_NAME = "group.chat.simplex.app" @@ -66,7 +68,7 @@ public func registerGroupDefaults() { GROUP_DEFAULT_NTF_ENABLE_LOCAL: false, GROUP_DEFAULT_NTF_ENABLE_PERIODIC: false, GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS: OnionHosts.no.rawValue, - GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.user.rawValue, + GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.session.rawValue, GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE: SMPProxyMode.unknown.rawValue, GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK: SMPProxyFallback.allowProtected.rawValue, GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout, @@ -84,7 +86,7 @@ public func registerGroupDefaults() { GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE: false, GROUP_DEFAULT_APP_LOCAL_AUTH_ENABLED: true, GROUP_DEFAULT_ALLOW_SHARE_EXTENSION: false, - GROUP_DEFAULT_PRIVACY_LINK_PREVIEWS: false, + GROUP_DEFAULT_PRIVACY_LINK_PREVIEWS: true, GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES: true, GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE: false, GROUP_DEFAULT_PRIVACY_ENCRYPT_LOCAL_FILES: true, @@ -93,7 +95,8 @@ public func registerGroupDefaults() { GROUP_DEFAULT_CONFIRM_DB_UPGRADES: false, GROUP_DEFAULT_CALL_KIT_ENABLED: true, GROUP_DEFAULT_PQ_EXPERIMENTAL_ENABLED: false, - GROUP_DEFAULT_ONE_HAND_UI: true + GROUP_DEFAULT_ONE_HAND_UI: true, + GROUP_DEFAULT_CHAT_BOTTOM_BAR: true ]) } @@ -231,7 +234,7 @@ public let networkUseOnionHostsGroupDefault = EnumDefault( public let networkSessionModeGroupDefault = EnumDefault( defaults: groupDefaults, forKey: GROUP_DEFAULT_NETWORK_SESSION_MODE, - withDefault: .user + withDefault: .session ) public let networkSMPProxyModeGroupDefault = EnumDefault( @@ -327,6 +330,7 @@ public class Default { } public func getNetCfg() -> NetCfg { + let socksProxy = groupDefaults.string(forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) let onionHosts = networkUseOnionHostsGroupDefault.get() let (hostMode, requiredHostMode) = onionHosts.hostMode let sessionMode = networkSessionModeGroupDefault.get() @@ -349,11 +353,13 @@ public func getNetCfg() -> NetCfg { tcpKeepAlive = nil } return NetCfg( + socksProxy: socksProxy, hostMode: hostMode, requiredHostMode: requiredHostMode, sessionMode: sessionMode, smpProxyMode: smpProxyMode, smpProxyFallback: smpProxyFallback, + smpWebPort: false, tcpConnectTimeout: tcpConnectTimeout, tcpTimeout: tcpTimeout, tcpTimeoutPerKb: tcpTimeoutPerKb, @@ -365,11 +371,13 @@ public func getNetCfg() -> NetCfg { ) } -public func setNetCfg(_ cfg: NetCfg) { +public func setNetCfg(_ cfg: NetCfg, networkProxy: NetworkProxy?) { networkUseOnionHostsGroupDefault.set(OnionHosts(netCfg: cfg)) networkSessionModeGroupDefault.set(cfg.sessionMode) networkSMPProxyModeGroupDefault.set(cfg.smpProxyMode) networkSMPProxyFallbackGroupDefault.set(cfg.smpProxyFallback) + let socksProxy = networkProxy?.toProxyString() + groupDefaults.set(socksProxy, forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY) groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT) groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT) groupDefaults.set(cfg.tcpTimeoutPerKb, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB) diff --git a/apps/ios/SimpleXChat/CallTypes.swift b/apps/ios/SimpleXChat/CallTypes.swift index 227a1fbda5..da1720c134 100644 --- a/apps/ios/SimpleXChat/CallTypes.swift +++ b/apps/ios/SimpleXChat/CallTypes.swift @@ -42,6 +42,7 @@ public struct RcvCallInvitation: Decodable { public var contact: Contact public var callType: CallType public var sharedKey: String? + public var callUUID: String? public var callTs: Date public var callTypeText: LocalizedStringKey { get { @@ -52,10 +53,8 @@ public struct RcvCallInvitation: Decodable { } } - public var callkitUUID: UUID? = UUID() - private enum CodingKeys: String, CodingKey { - case user, contact, callType, sharedKey, callTs + case user, contact, callType, sharedKey, callUUID, callTs } public static let sampleData = RcvCallInvitation( @@ -81,6 +80,14 @@ public enum CallMediaType: String, Codable, Equatable { case audio = "audio" } +public enum CallMediaSource: String, Codable, Equatable { + case mic = "mic" + case camera = "camera" + case screenAudio = "screenAudio" + case screenVideo = "screenVideo" + case unknown = "unknown" +} + public enum VideoCamera: String, Codable, Equatable { case user = "user" case environment = "environment" diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 233f4c19ee..da1ce24b73 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -17,6 +17,7 @@ public struct User: Identifiable, Decodable, UserLike, NamedChat, Hashable { public var profile: LocalProfile public var fullPreferences: FullPreferences public var activeUser: Bool + public var activeOrder: Int64 public var displayName: String { get { profile.displayName } } public var fullName: String { get { profile.fullName } } @@ -49,6 +50,7 @@ public struct User: Identifiable, Decodable, UserLike, NamedChat, Hashable { profile: LocalProfile.sampleData, fullPreferences: FullPreferences.sampleData, activeUser: true, + activeOrder: 0, showNtfs: true, sendRcptsContacts: true, sendRcptsSmallGroups: false @@ -819,38 +821,38 @@ public enum GroupFeature: String, Decodable, Feature, Hashable { switch self { case .timedMessages: switch enabled { - case .on: return "Group members can send disappearing messages." - case .off: return "Disappearing messages are prohibited in this group." + case .on: return "Members can send disappearing messages." + case .off: return "Disappearing messages are prohibited." } case .directMessages: switch enabled { - case .on: return "Group members can send direct messages." - case .off: return "Direct messages between members are prohibited in this group." + case .on: return "Members can send direct messages." + case .off: return "Direct messages between members are prohibited." } case .fullDelete: switch enabled { - case .on: return "Group members can irreversibly delete sent messages. (24 hours)" - case .off: return "Irreversible message deletion is prohibited in this group." + case .on: return "Members can irreversibly delete sent messages. (24 hours)" + case .off: return "Irreversible message deletion is prohibited." } case .reactions: switch enabled { - case .on: return "Group members can add message reactions." - case .off: return "Message reactions are prohibited in this group." + case .on: return "Members can add message reactions." + case .off: return "Message reactions are prohibited." } case .voice: switch enabled { - case .on: return "Group members can send voice messages." - case .off: return "Voice messages are prohibited in this group." + case .on: return "Members can send voice messages." + case .off: return "Voice messages are prohibited." } case .files: switch enabled { - case .on: return "Group members can send files and media." - case .off: return "Files and media are prohibited in this group." + case .on: return "Members can send files and media." + case .off: return "Files and media are prohibited." } case .simplexLinks: switch enabled { - case .on: return "Group members can send SimpleX links." - case .off: return "SimpleX links are prohibited in this group." + case .on: return "Members can send SimpleX links." + case .off: return "SimpleX links are prohibited." } case .history: switch enabled { @@ -1500,6 +1502,12 @@ public struct ChatData: Decodable, Identifiable, Hashable, ChatLike { public var id: ChatId { get { chatInfo.id } } + public init(chatInfo: ChatInfo, chatItems: [ChatItem], chatStats: ChatStats = ChatStats()) { + self.chatInfo = chatInfo + self.chatItems = chatItems + self.chatStats = chatStats + } + public static func invalidJSON(_ json: String) -> ChatData { ChatData( chatInfo: .invalidJSON(json: json), @@ -1774,9 +1782,11 @@ public struct PendingContactConnection: Decodable, NamedChat, Hashable { public var displayName: String { get { if let initiated = pccConnStatus.initiated { - return initiated && !viaContactUri + return viaContactUri + ? NSLocalizedString("requested to connect", comment: "chat list item title") + : initiated ? NSLocalizedString("invited to connect", comment: "chat list item title") - : NSLocalizedString("connecting…", comment: "chat list item title") + : NSLocalizedString("accepted invitation", comment: "chat list item title") } else { // this should not be in the list return NSLocalizedString("connection established", comment: "chat list item title (it should not be shown") @@ -1844,6 +1854,7 @@ public struct PendingContactConnection: Decodable, NamedChat, Hashable { public enum ConnStatus: String, Decodable, Hashable { case new = "new" + case prepared = "prepared" case joined = "joined" case requested = "requested" case accepted = "accepted" @@ -1855,6 +1866,7 @@ public enum ConnStatus: String, Decodable, Hashable { get { switch self { case .new: return true + case .prepared: return false case .joined: return false case .requested: return true case .accepted: return true @@ -1880,6 +1892,7 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable { public var groupId: Int64 var localDisplayName: GroupName public var groupProfile: GroupProfile + public var businessChat: BusinessChatInfo? public var fullGroupPreferences: FullGroupPreferences public var membership: GroupMember public var hostConnCustomUserProfileId: Int64? @@ -1898,7 +1911,7 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable { public var image: String? { get { groupProfile.image } } public var localAlias: String { "" } - public var canEdit: Bool { + public var isOwner: Bool { return membership.memberRole == .owner && membership.memberCurrent } @@ -1950,6 +1963,17 @@ public struct GroupProfile: Codable, NamedChat, Hashable { ) } +public struct BusinessChatInfo: Decodable, Hashable { + public var chatType: BusinessChatType + public var businessId: String + public var customerId: String +} + +public enum BusinessChatType: String, Codable, Hashable { + case business + case customer +} + public struct GroupMember: Identifiable, Decodable, Hashable { public var groupMemberId: Int64 public var groupId: Int64 @@ -2232,41 +2256,53 @@ public struct MemberSubError: Decodable, Hashable { } public enum ConnectionEntity: Decodable, Hashable { - case rcvDirectMsgConnection(contact: Contact?) - case rcvGroupMsgConnection(groupInfo: GroupInfo, groupMember: GroupMember) - case sndFileConnection(sndFileTransfer: SndFileTransfer) - case rcvFileConnection(rcvFileTransfer: RcvFileTransfer) - case userContactConnection(userContact: UserContact) + case rcvDirectMsgConnection(entityConnection: Connection, contact: Contact?) + case rcvGroupMsgConnection(entityConnection: Connection, groupInfo: GroupInfo, groupMember: GroupMember) + case sndFileConnection(entityConnection: Connection, sndFileTransfer: SndFileTransfer) + case rcvFileConnection(entityConnection: Connection, rcvFileTransfer: RcvFileTransfer) + case userContactConnection(entityConnection: Connection, userContact: UserContact) public var id: String? { switch self { - case let .rcvDirectMsgConnection(contact): + case let .rcvDirectMsgConnection(_, contact): return contact?.id - case let .rcvGroupMsgConnection(_, groupMember): + case let .rcvGroupMsgConnection(_, _, groupMember): return groupMember.id - case let .userContactConnection(userContact): + case let .userContactConnection(_, userContact): return userContact.id default: return nil } } - public var ntfsEnabled: Bool { + public var conn: Connection { switch self { - case let .rcvDirectMsgConnection(contact): return contact?.chatSettings.enableNtfs == .all - case let .rcvGroupMsgConnection(groupInfo, _): return groupInfo.chatSettings.enableNtfs == .all - case .sndFileConnection: return false - case .rcvFileConnection: return false - case let .userContactConnection(userContact): return userContact.groupId == nil + case let .rcvDirectMsgConnection(entityConnection, _): entityConnection + case let .rcvGroupMsgConnection(entityConnection, _, _): entityConnection + case let .sndFileConnection(entityConnection, _): entityConnection + case let .rcvFileConnection(entityConnection, _): entityConnection + case let .userContactConnection(entityConnection, _): entityConnection } } } +public struct NtfConn: Decodable, Hashable { + public var user_: User? + public var connEntity_: ConnectionEntity? + public var expectedMsg_: NtfMsgInfo? + +} + public struct NtfMsgInfo: Decodable, Hashable { public var msgId: String public var msgTs: Date } +public struct NtfMsgAckInfo: Decodable, Hashable { + public var msgId: String + public var msgTs_: Date? +} + public struct ChatItemDeletion: Decodable, Hashable { public var deletedChatItem: AChatItem public var toChatItem: AChatItem? = nil @@ -2289,6 +2325,11 @@ public struct ACIReaction: Decodable, Hashable { public var chatReaction: CIReaction } +public struct MemberReaction: Decodable, Hashable { + public var groupMember: GroupMember + public var reactionTs: Date +} + public struct CIReaction: Decodable, Hashable { public var chatDir: CIDirection public var chatItem: ChatItem @@ -2682,6 +2723,13 @@ public enum CIDirection: Decodable, Hashable { } } } + + public func sameDirection(_ dir: CIDirection) -> Bool { + switch (self, dir) { + case let (.groupRcv(m1), .groupRcv(m2)): m1.groupMemberId == m2.groupMemberId + default: sent == dir.sent + } + } } public struct CIMeta: Decodable, Hashable { @@ -2700,7 +2748,7 @@ public struct CIMeta: Decodable, Hashable { public var deletable: Bool public var editable: Bool - public var timestampText: Text { get { formatTimestampText(itemTs) } } + public var timestampText: Text { Text(formatTimestampMeta(itemTs)) } public var recent: Bool { updatedAt + 10 > .now } public var isLive: Bool { itemLive == true } public var disappearing: Bool { !isRcvNew && itemTimed?.deleteAt != nil } @@ -2710,10 +2758,6 @@ public struct CIMeta: Decodable, Hashable { return false } - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color)? { - itemStatus.statusIcon(metaColor, primaryColor) - } - public static func getSample(_ id: Int64, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, itemDeleted: CIDeleted? = nil, itemEdited: Bool = false, itemLive: Bool = false, deletable: Bool = true, editable: Bool = true) -> CIMeta { CIMeta( itemId: id, @@ -2754,9 +2798,20 @@ public struct CITimed: Decodable, Hashable { let msgTimeFormat = Date.FormatStyle.dateTime.hour().minute() let msgDateFormat = Date.FormatStyle.dateTime.day(.twoDigits).month(.twoDigits) +let msgDateYearFormat = Date.FormatStyle.dateTime.day(.twoDigits).month(.twoDigits).year(.twoDigits) public func formatTimestampText(_ date: Date) -> Text { - return Text(date, format: recent(date) ? msgTimeFormat : msgDateFormat) + Text(verbatim: date.formatted( + recent(date) + ? msgTimeFormat + : Calendar.current.isDate(date, equalTo: .now, toGranularity: .year) + ? msgDateFormat + : msgDateYearFormat + )) +} + +public func formatTimestampMeta(_ date: Date) -> String { + date.formatted(date: .omitted, time: .shortened) } private func recent(_ date: Date) -> Bool { @@ -2798,22 +2853,37 @@ public enum CIStatus: Decodable, Hashable { case .invalid: return "invalid" } } - - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color)? { + + public var sent: Bool { switch self { - case .sndNew: return nil - case .sndSent: return ("checkmark", metaColor) - case let .sndRcvd(msgRcptStatus, _): + case .sndNew: true + case .sndSent: true + case .sndRcvd: true + case .sndErrorAuth: true + case .sndError: true + case .sndWarning: true + case .rcvNew: false + case .rcvRead: false + case .invalid: false + } + } + + public func statusIcon(_ metaColor: Color, _ paleMetaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color)? { + switch self { + case .sndNew: nil + case let .sndSent(sndProgress): + (Image("checkmark.wide"), sndProgress == .partial ? paleMetaColor : metaColor) + case let .sndRcvd(msgRcptStatus, sndProgress): switch msgRcptStatus { - case .ok: return ("checkmark", metaColor) - case .badMsgHash: return ("checkmark", .red) + case .ok: (Image("checkmark.2"), sndProgress == .partial ? paleMetaColor : metaColor) + case .badMsgHash: (Image("checkmark.2"), .red) } - case .sndErrorAuth: return ("multiply", .red) - case .sndError: return ("multiply", .red) - case .sndWarning: return ("exclamationmark.triangle.fill", .orange) - case .rcvNew: return ("circlebadge.fill", primaryColor) - case .rcvRead: return nil - case .invalid: return ("questionmark", metaColor) + case .sndErrorAuth: (Image(systemName: "multiply"), .red) + case .sndError: (Image(systemName: "multiply"), .red) + case .sndWarning: (Image(systemName: "exclamationmark.triangle.fill"), .orange) + case .rcvNew: (Image(systemName: "circlebadge.fill"), primaryColor) + case .rcvRead: nil + case .invalid: (Image(systemName: "questionmark"), metaColor) } } @@ -2842,6 +2912,13 @@ public enum CIStatus: Decodable, Hashable { ) } } + + public var isSndRcvd: Bool { + switch self { + case .sndRcvd: return true + default: return false + } + } } public enum SndError: Decodable, Hashable { @@ -2908,20 +2985,20 @@ public enum GroupSndStatus: Decodable, Hashable { case warning(agentError: SndError) case invalid(text: String) - public func statusIcon(_ metaColor: Color/* = .secondary*/, _ primaryColor: Color = .accentColor) -> (String, Color) { + public func statusIcon(_ metaColor: Color, _ primaryColor: Color = .accentColor) -> (Image, Color) { switch self { - case .new: return ("ellipsis", metaColor) - case .forwarded: return ("chevron.forward.2", metaColor) - case .inactive: return ("person.badge.minus", metaColor) - case .sent: return ("checkmark", metaColor) + case .new: (Image(systemName: "ellipsis"), metaColor) + case .forwarded: (Image(systemName: "chevron.forward.2"), metaColor) + case .inactive: (Image(systemName: "person.badge.minus"), metaColor) + case .sent: (Image("checkmark.wide"), metaColor) case let .rcvd(msgRcptStatus): switch msgRcptStatus { - case .ok: return ("checkmark", metaColor) - case .badMsgHash: return ("checkmark", .red) + case .ok: (Image("checkmark.2"), metaColor) + case .badMsgHash: (Image("checkmark.2"), .red) } - case .error: return ("multiply", .red) - case .warning: return ("exclamationmark.triangle.fill", .orange) - case .invalid: return ("questionmark", metaColor) + case .error: (Image(systemName: "multiply"), .red) + case .warning: (Image(systemName: "exclamationmark.triangle.fill"), .orange) + case .invalid: (Image(systemName: "questionmark"), metaColor) } } @@ -3138,6 +3215,13 @@ public enum CIContent: Decodable, ItemContent, Hashable { default: return false } } + + public var isSndCall: Bool { + switch self { + case .sndCall: return true + default: return false + } + } } public enum MsgDecryptError: String, Decodable, Hashable { diff --git a/apps/ios/SimpleXChat/ChatUtils.swift b/apps/ios/SimpleXChat/ChatUtils.swift index 5f56180918..2bf861f437 100644 --- a/apps/ios/SimpleXChat/ChatUtils.swift +++ b/apps/ios/SimpleXChat/ChatUtils.swift @@ -93,7 +93,12 @@ private func canForwardToChat(_ cInfo: ChatInfo) -> Bool { public func chatIconName(_ cInfo: ChatInfo) -> String { switch cInfo { case .direct: "person.crop.circle.fill" - case .group: "person.2.circle.fill" + case let .group(groupInfo): + switch groupInfo.businessChat?.chatType { + case .none: "person.2.circle.fill" + case .business: "briefcase.circle.fill" + case .customer: "person.crop.circle.fill" + } case .local: "folder.circle.fill" case .contactRequest: "person.crop.circle.fill" default: "circle.fill" diff --git a/apps/ios/SimpleXChat/ImageUtils.swift b/apps/ios/SimpleXChat/ImageUtils.swift index 67218a781e..89cc45c4f5 100644 --- a/apps/ios/SimpleXChat/ImageUtils.swift +++ b/apps/ios/SimpleXChat/ImageUtils.swift @@ -100,7 +100,7 @@ public func resizeImageToDataSize(_ image: UIImage, maxDataSize: Int64, hasAlpha return data } -public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String? { +public func resizeImageToStrSizeSync(_ image: UIImage, maxDataSize: Int64) -> String? { var img = image let hasAlpha = imageHasAlpha(image) var str = compressImageStr(img, hasAlpha: hasAlpha) @@ -116,7 +116,15 @@ public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) -> String return str } +public func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int64) async -> String? { + resizeImageToStrSizeSync(image, maxDataSize: maxDataSize) +} + public func compressImageStr(_ image: UIImage, _ compressionQuality: CGFloat = 0.85, hasAlpha: Bool) -> String? { +// // Heavy workload to verify if UI gets blocked by the call +// for i in 0..<100 { +// print(image.jpegData(compressionQuality: Double(i) / 100)?.count ?? 0, terminator: ", ") +// } let ext = hasAlpha ? "png" : "jpg" if let data = hasAlpha ? image.pngData() : image.jpegData(compressionQuality: compressionQuality) { return "data:image/\(ext);base64,\(data.base64EncodedString())" @@ -130,7 +138,7 @@ private func reduceSize(_ image: UIImage, ratio: CGFloat, hasAlpha: Bool) -> UII return resizeImage(image, newBounds: bounds, drawIn: bounds, hasAlpha: hasAlpha) } -private func resizeImage(_ image: UIImage, newBounds: CGRect, drawIn: CGRect, hasAlpha: Bool) -> UIImage { +public func resizeImage(_ image: UIImage, newBounds: CGRect, drawIn: CGRect, hasAlpha: Bool) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1.0 format.opaque = !hasAlpha @@ -383,16 +391,34 @@ extension UIImage { } return self } +} - public convenience init?(base64Encoded: String?) { - if let base64Encoded, let data = Data(base64Encoded: dropImagePrefix(base64Encoded)) { - self.init(data: data) +public func imageFromBase64(_ base64Encoded: String?) -> UIImage? { + if let base64Encoded { + if let img = imageCache.object(forKey: base64Encoded as NSString) { + return img + } else if let data = Data(base64Encoded: dropImagePrefix(base64Encoded)), + let img = UIImage(data: data) { + imageCacheQueue.async { + imageCache.setObject(img, forKey: base64Encoded as NSString) + } + return img } else { return nil } + } else { + return nil } } +private let imageCacheQueue = DispatchQueue.global(qos: .background) + +private var imageCache: NSCache = { + var cache = NSCache() + cache.countLimit = 1000 + return cache +}() + public func getLinkPreview(url: URL, cb: @escaping (LinkPreview?) -> Void) { logger.debug("getLinkMetadata: fetching URL preview") LPMetadataProvider().startFetchingMetadata(for: url){ metadata, error in @@ -408,7 +434,7 @@ public func getLinkPreview(url: URL, cb: @escaping (LinkPreview?) -> Void) { logger.error("Couldn't load image preview from link metadata with error: \(error.localizedDescription)") } else { if let image = object as? UIImage, - let resized = resizeImageToStrSize(image, maxDataSize: 14000), + let resized = resizeImageToStrSizeSync(image, maxDataSize: 14000), let title = metadata.title, let uri = metadata.originalURL { linkPreview = LinkPreview(uri: uri, title: title, image: resized) diff --git a/apps/ios/SimpleXChat/Notifications.swift b/apps/ios/SimpleXChat/Notifications.swift index 4b43595372..a922e3a816 100644 --- a/apps/ios/SimpleXChat/Notifications.swift +++ b/apps/ios/SimpleXChat/Notifications.swift @@ -15,13 +15,14 @@ public let ntfCategoryContactConnected = "NTF_CAT_CONTACT_CONNECTED" public let ntfCategoryMessageReceived = "NTF_CAT_MESSAGE_RECEIVED" public let ntfCategoryCallInvitation = "NTF_CAT_CALL_INVITATION" public let ntfCategoryConnectionEvent = "NTF_CAT_CONNECTION_EVENT" +public let ntfCategoryManyEvents = "NTF_CAT_MANY_EVENTS" public let ntfCategoryCheckMessage = "NTF_CAT_CHECK_MESSAGE" public let appNotificationId = "chat.simplex.app.notification" let contactHidden = NSLocalizedString("Contact hidden:", comment: "notification") -public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: UserContactRequest) -> UNMutableNotificationContent { +public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: UserContactRequest, _ badgeCount: Int) -> UNMutableNotificationContent { let hideContent = ntfPreviewModeGroupDefault.get() == .hidden return createNotification( categoryIdentifier: ntfCategoryContactRequest, @@ -34,11 +35,12 @@ public func createContactRequestNtf(_ user: any UserLike, _ contactRequest: User hideContent ? NSLocalizedString("this contact", comment: "notification title") : contactRequest.chatViewName ), targetContentIdentifier: nil, - userInfo: ["chatId": contactRequest.id, "contactRequestId": contactRequest.apiId, "userId": user.userId] + userInfo: ["chatId": contactRequest.id, "contactRequestId": contactRequest.apiId, "userId": user.userId], + badgeCount: badgeCount ) } -public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact) -> UNMutableNotificationContent { +public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact, _ badgeCount: Int) -> UNMutableNotificationContent { let hideContent = ntfPreviewModeGroupDefault.get() == .hidden return createNotification( categoryIdentifier: ntfCategoryContactConnected, @@ -51,12 +53,13 @@ public func createContactConnectedNtf(_ user: any UserLike, _ contact: Contact) hideContent ? NSLocalizedString("this contact", comment: "notification title") : contact.chatViewName ), targetContentIdentifier: contact.id, - userInfo: ["userId": user.userId] + userInfo: ["userId": user.userId], // userInfo: ["chatId": contact.id, "contactId": contact.apiId] + badgeCount: badgeCount ) } -public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem) -> UNMutableNotificationContent { +public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _ cItem: ChatItem, _ badgeCount: Int) -> UNMutableNotificationContent { let previewMode = ntfPreviewModeGroupDefault.get() var title: String if case let .group(groupInfo) = cInfo, case let .groupRcv(groupMember) = cItem.chatDir { @@ -69,12 +72,13 @@ public func createMessageReceivedNtf(_ user: any UserLike, _ cInfo: ChatInfo, _ title: title, body: previewMode == .message ? hideSecrets(cItem) : NSLocalizedString("new message", comment: "notification"), targetContentIdentifier: cInfo.id, - userInfo: ["userId": user.userId] + userInfo: ["userId": user.userId], // userInfo: ["chatId": cInfo.id, "chatItemId": cItem.id] + badgeCount: badgeCount ) } -public func createCallInvitationNtf(_ invitation: RcvCallInvitation) -> UNMutableNotificationContent { +public func createCallInvitationNtf(_ invitation: RcvCallInvitation, _ badgeCount: Int) -> UNMutableNotificationContent { let text = invitation.callType.media == .video ? NSLocalizedString("Incoming video call", comment: "notification") : NSLocalizedString("Incoming audio call", comment: "notification") @@ -84,17 +88,18 @@ public func createCallInvitationNtf(_ invitation: RcvCallInvitation) -> UNMutabl title: hideContent ? contactHidden : "\(invitation.contact.chatViewName):", body: text, targetContentIdentifier: nil, - userInfo: ["chatId": invitation.contact.id, "userId": invitation.user.userId] + userInfo: ["chatId": invitation.contact.id, "userId": invitation.user.userId], + badgeCount: badgeCount ) } -public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntity) -> UNMutableNotificationContent { +public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntity, _ badgeCount: Int) -> UNMutableNotificationContent { let hideContent = ntfPreviewModeGroupDefault.get() == .hidden var title: String var body: String? = nil var targetContentIdentifier: String? = nil switch connEntity { - case let .rcvDirectMsgConnection(contact): + case let .rcvDirectMsgConnection(_, contact): if let contact = contact { title = hideContent ? contactHidden : "\(contact.chatViewName):" targetContentIdentifier = contact.id @@ -102,7 +107,7 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit title = NSLocalizedString("New contact:", comment: "notification") } body = NSLocalizedString("message received", comment: "notification") - case let .rcvGroupMsgConnection(groupInfo, groupMember): + case let .rcvGroupMsgConnection(_, groupInfo, groupMember): title = groupMsgNtfTitle(groupInfo, groupMember, hideContent: hideContent) body = NSLocalizedString("message received", comment: "notification") targetContentIdentifier = groupInfo.id @@ -118,11 +123,12 @@ public func createConnectionEventNtf(_ user: User, _ connEntity: ConnectionEntit title: title, body: body, targetContentIdentifier: targetContentIdentifier, - userInfo: ["userId": user.userId] + userInfo: ["userId": user.userId], + badgeCount: badgeCount ) } -public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificationContent { +public func createErrorNtf(_ dbStatus: DBMigrationResult, _ badgeCount: Int) -> UNMutableNotificationContent { var title: String switch dbStatus { case .errorNotADatabase: @@ -142,14 +148,16 @@ public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificati } return createNotification( categoryIdentifier: ntfCategoryConnectionEvent, - title: title + title: title, + badgeCount: badgeCount ) } -public func createAppStoppedNtf() -> UNMutableNotificationContent { +public func createAppStoppedNtf(_ badgeCount: Int) -> UNMutableNotificationContent { return createNotification( categoryIdentifier: ntfCategoryConnectionEvent, - title: NSLocalizedString("Encrypted message: app is stopped", comment: "notification") + title: NSLocalizedString("Encrypted message: app is stopped", comment: "notification"), + badgeCount: badgeCount ) } @@ -159,8 +167,15 @@ private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember : "#\(groupInfo.displayName) \(groupMember.chatViewName):" } -public func createNotification(categoryIdentifier: String, title: String, subtitle: String? = nil, body: String? = nil, - targetContentIdentifier: String? = nil, userInfo: [AnyHashable : Any] = [:]) -> UNMutableNotificationContent { +public func createNotification( + categoryIdentifier: String, + title: String, + subtitle: String? = nil, + body: String? = nil, + targetContentIdentifier: String? = nil, + userInfo: [AnyHashable : Any] = [:], + badgeCount: Int +) -> UNMutableNotificationContent { let content = UNMutableNotificationContent() content.categoryIdentifier = categoryIdentifier content.title = title @@ -170,6 +185,7 @@ public func createNotification(categoryIdentifier: String, title: String, subtit content.userInfo = userInfo // TODO move logic of adding sound here, so it applies to background notifications too content.sound = .default + content.badge = badgeCount as NSNumber // content.interruptionLevel = .active // content.relevanceScore = 0.5 // 0-1 return content diff --git a/apps/ios/SimpleXChat/SimpleX.h b/apps/ios/SimpleXChat/SimpleX.h index 153365424e..92dfafca21 100644 --- a/apps/ios/SimpleXChat/SimpleX.h +++ b/apps/ios/SimpleXChat/SimpleX.h @@ -10,6 +10,7 @@ #define SimpleX_h #include "hs_init.h" +#include "objc.h" extern void hs_init(int argc, char **argv[]); diff --git a/apps/ios/SimpleXChat/Theme/Color.swift b/apps/ios/SimpleXChat/Theme/Color.swift index 3e8fe1b6e7..f307eaa5aa 100644 --- a/apps/ios/SimpleXChat/Theme/Color.swift +++ b/apps/ios/SimpleXChat/Theme/Color.swift @@ -63,6 +63,23 @@ extension Color { ) } + public func toHTMLHex() -> String { + let uiColor: UIColor = .init(self) + var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0) + uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) + // Can be negative values and more than 1. Extended color range, making it normal + r = min(1, max(0, r)) + g = min(1, max(0, g)) + b = min(1, max(0, b)) + a = min(1, max(0, a)) + return String(format: "#%02x%02x%02x%02x", + Int((r * 255).rounded()), + Int((g * 255).rounded()), + Int((b * 255).rounded()), + Int((a * 255).rounded()) + ) + } + public func darker(_ factor: CGFloat = 0.1) -> Color { var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0) UIColor(self).getRed(&r, green: &g, blue: &b, alpha: &a) diff --git a/apps/ios/SimpleXChat/objc.h b/apps/ios/SimpleXChat/objc.h new file mode 100644 index 0000000000..a75a6dc5e4 --- /dev/null +++ b/apps/ios/SimpleXChat/objc.h @@ -0,0 +1,20 @@ +// +// objc.h +// SimpleX (iOS) +// +// Created by Stanislav Dmitrenko on 09.09.2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +#ifndef objc_h +#define objc_h + +#import + +@interface ObjC : NSObject + ++ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error; + +@end + +#endif /* objc_h */ diff --git a/apps/ios/SimpleXChat/objc.m b/apps/ios/SimpleXChat/objc.m new file mode 100644 index 0000000000..c6952578ab --- /dev/null +++ b/apps/ios/SimpleXChat/objc.m @@ -0,0 +1,25 @@ +// +// objc.m +// SimpleXChat +// +// Created by Stanislav Dmitrenko on 09.09.2024. +// Copyright © 2024 SimpleX Chat. All rights reserved. +// + +#import "objc.h" + +@implementation ObjC + +// https://stackoverflow.com/a/36454808 ++ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error { + @try { + tryBlock(); + return YES; + } + @catch (NSException *exception) { + *error = [[NSError alloc] initWithDomain: exception.name code: 0 userInfo: exception.userInfo]; + return NO; + } +} + +@end diff --git a/apps/ios/bg.lproj/Localizable.strings b/apps/ios/bg.lproj/Localizable.strings index aa43902c81..f2059d5627 100644 --- a/apps/ios/bg.lproj/Localizable.strings +++ b/apps/ios/bg.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -65,10 +56,7 @@ "[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 код или линк за вашия контакт."; +"**Create 1-time link**: to create and share a new invitation link." = "**Добави контакт**: за създаване на нов линк."; /* No comment provided by engineer. */ "**Create group**: to create a new group." = "**Създай група**: за създаване на нова група."; @@ -80,10 +68,10 @@ "**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, но не и колко контакти или съобщения имате."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**По поверително**: проверявайте новите съобщения на всеки 20 минути. Токенът на устройството се споделя със сървъра за чат SimpleX, но не и колко контакти или съобщения имате."; /* 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, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app." = "**Най-поверително**: не използвайте сървъра за известия SimpleX Chat, периодично проверявайте съобщенията във фонов режим (зависи от това колко често използвате приложението)."; /* No comment provided by engineer. */ "**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Моля, обърнете внимание**: използването на една и съща база данни на две устройства ще наруши декриптирането на съобщенията от вашите връзки като защита на сигурността."; @@ -92,7 +80,7 @@ "**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, но не и съдържанието, размерът на съобщението или от кого е."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from." = "**Препоръчително**: токенът на устройството и известията се изпращат до сървъра за уведомяване на SimpleX Chat, но не и съдържанието, размерът на съобщението или от кого е."; /* No comment provided by engineer. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Внимание**: Незабавните push известия изискват парола, запазена в Keychain."; @@ -322,12 +310,6 @@ /* No comment provided by engineer. */ "Abort changing address?" = "Откажи смяна на адрес?"; -/* No comment provided by engineer. */ -"About SimpleX" = "За SimpleX"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "Повече за SimpleX адреса"; - /* No comment provided by engineer. */ "About SimpleX Chat" = "За SimpleX Chat"; @@ -355,12 +337,6 @@ /* 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" = "Добави предварително зададени сървъри"; - /* No comment provided by engineer. */ "Add profile" = "Добави профил"; @@ -517,6 +493,9 @@ /* No comment provided by engineer. */ "Answer call" = "Отговор на повикване"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "Протокол и код с отворен код – всеки може да оперира собствени сървъри."; + /* No comment provided by engineer. */ "App build: %@" = "Компилация на приложението: %@"; @@ -697,7 +676,8 @@ /* No comment provided by engineer. */ "Can't invite contacts!" = "Не може да поканят контактите!"; -/* No comment provided by engineer. */ +/* alert action + alert button */ "Cancel" = "Отказ"; /* No comment provided by engineer. */ @@ -709,7 +689,7 @@ /* No comment provided by engineer. */ "Cannot access keychain to save database password" = "Няма достъп до Keychain за запазване на паролата за базата данни"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "Файлът не може да бъде получен"; /* No comment provided by engineer. */ @@ -761,9 +741,6 @@ /* chat item text */ "changing address…" = "промяна на адреса…"; -/* No comment provided by engineer. */ -"Chat archive" = "Архив на чата"; - /* No comment provided by engineer. */ "Chat console" = "Конзола"; @@ -792,9 +769,12 @@ "Chat preferences" = "Чат настройки"; /* No comment provided by engineer. */ -"Chats" = "Чатове"; +"Chat profile" = "Потребителски профил"; /* No comment provided by engineer. */ +"Chats" = "Чатове"; + +/* alert title */ "Check server address and try again." = "Проверете адреса на сървъра и опитайте отново."; /* No comment provided by engineer. */ @@ -938,7 +918,7 @@ /* No comment provided by engineer. */ "Connecting to desktop" = "Свързване с настолно устройство"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "свързване…"; /* No comment provided by engineer. */ @@ -1016,9 +996,6 @@ /* 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" = "Създай файл"; @@ -1055,9 +1032,6 @@ /* copied message info */ "Created at: %@" = "Създаден на: %@"; -/* No comment provided by engineer. */ -"Created on %@" = "Създаден на %@"; - /* No comment provided by engineer. */ "Creating archive link" = "Създаване на архивен линк"; @@ -1160,7 +1134,8 @@ /* No comment provided by engineer. */ "default (yes)" = "по подразбиране (да)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Изтрий"; @@ -1182,12 +1157,6 @@ /* No comment provided by engineer. */ "Delete and notify contact" = "Изтрий и уведоми контакт"; -/* No comment provided by engineer. */ -"Delete archive" = "Изтрий архив"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "Изтриване на архива на чата?"; - /* No comment provided by engineer. */ "Delete chat profile" = "Изтрий чат профила"; @@ -1330,7 +1299,7 @@ "Direct messages" = "Лични съобщения"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Личните съобщения между членовете са забранени в тази група."; +"Direct messages between members are prohibited." = "Личните съобщения между членовете са забранени в тази група."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Деактивиране (запазване на промените)"; @@ -1354,7 +1323,7 @@ "Disappearing messages are prohibited in this chat." = "Изчезващите съобщения са забранени в този чат."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "Изчезващите съобщения са забранени в тази група."; +"Disappearing messages are prohibited." = "Изчезващите съобщения са забранени в тази група."; /* No comment provided by engineer. */ "Disappears at" = "Изчезва в"; @@ -1395,7 +1364,8 @@ /* No comment provided by engineer. */ "Downgrade and open chat" = "Понижи версията и отвори чата"; -/* chat item action */ +/* alert button + chat item action */ "Download" = "Изтегли"; /* No comment provided by engineer. */ @@ -1599,9 +1569,6 @@ /* No comment provided by engineer. */ "Error accepting contact request" = "Грешка при приемане на заявка за контакт"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Грешка при достъпа до файла с базата данни"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Грешка при добавяне на член(ове)"; @@ -1677,21 +1644,15 @@ /* No comment provided by engineer. */ "Error joining group" = "Грешка при присъединяване към група"; -/* No comment provided by engineer. */ -"Error loading %@ servers" = "Грешка при зареждане на %@ сървъри"; - /* No comment provided by engineer. */ "Error opening chat" = "Грешка при отваряне на чата"; -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Грешка при получаване на файл"; /* No comment provided by engineer. */ "Error removing member" = "Грешка при отстраняване на член"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Грешка при запазване на %@ сървъра"; - /* No comment provided by engineer. */ "Error saving group profile" = "Грешка при запазване на профила на групата"; @@ -1731,7 +1692,7 @@ /* No comment provided by engineer. */ "Error stopping chat" = "Грешка при спиране на чата"; -/* No comment provided by engineer. */ +/* alertTitle */ "Error switching profile!" = "Грешка при смяна на профил!"; /* No comment provided by engineer. */ @@ -1758,8 +1719,7 @@ /* No comment provided by engineer. */ "Error: " = "Грешка: "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Грешка: %@"; /* No comment provided by engineer. */ @@ -1826,7 +1786,7 @@ "Files and media" = "Файлове и медия"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "Файловете и медията са забранени в тази група."; +"Files and media are prohibited." = "Файловете и медията са забранени в тази група."; /* No comment provided by engineer. */ "Files and media not allowed" = "Файлове и медия не са разрешени"; @@ -1897,9 +1857,6 @@ /* No comment provided by engineer. */ "Full name (optional)" = "Пълно име (незадължително)"; -/* No comment provided by engineer. */ -"Full name:" = "Пълно име:"; - /* No comment provided by engineer. */ "Fully decentralized – visible only to members." = "Напълно децентрализирана – видима е само за членовете."; @@ -1948,27 +1905,6 @@ /* No comment provided by engineer. */ "Group links" = "Групови линкове"; -/* No comment provided by engineer. */ -"Group members can add message reactions." = "Членовете на групата могат да добавят реакции към съобщенията."; - -/* No comment provided by engineer. */ -"Group members can irreversibly delete sent messages. (24 hours)" = "Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)"; - -/* No comment provided by engineer. */ -"Group members can send direct messages." = "Членовете на групата могат да изпращат лични съобщения."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Членовете на групата могат да изпращат изчезващи съобщения."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Членовете на групата могат да изпращат файлове и медия."; - -/* No comment provided by engineer. */ -"Group members can send SimpleX links." = "Членовете на групата могат да изпращат SimpleX линкове."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Членовете на групата могат да изпращат гласови съобщения."; - /* notification */ "Group message:" = "Групово съобщение:"; @@ -2029,9 +1965,6 @@ /* time unit */ "hours" = "часове"; -/* No comment provided by engineer. */ -"How it works" = "Как работи"; - /* No comment provided by engineer. */ "How SimpleX works" = "Как работи SimpleX"; @@ -2075,7 +2008,7 @@ "Immediately" = "Веднага"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Защитен от спам и злоупотреби"; +"Immune to spam" = "Защитен от спам и злоупотреби"; /* No comment provided by engineer. */ "Import" = "Импортиране"; @@ -2165,10 +2098,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Инсталирайте [SimpleX Chat за терминал](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "Незабавните push известия ще бъдат скрити!\n"; +"Instant" = "Мигновено"; /* No comment provided by engineer. */ -"Instantly" = "Мигновено"; +"Instant push notifications will be hidden!\n" = "Незабавните push известия ще бъдат скрити!\n"; /* No comment provided by engineer. */ "Interface" = "Интерфейс"; @@ -2203,7 +2136,7 @@ /* No comment provided by engineer. */ "Invalid response" = "Невалиден отговор"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "Невалиден адрес на сървъра!"; /* item status text */ @@ -2249,7 +2182,7 @@ "Irreversible message deletion is prohibited in this chat." = "Необратимото изтриване на съобщения е забранено в този чат."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "Необратимото изтриване на съобщения е забранено в тази група."; +"Irreversible message deletion is prohibited." = "Необратимото изтриване на съобщения е забранено в тази група."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Позволява да имате много анонимни връзки без споделени данни между тях в един чат профил ."; @@ -2299,13 +2232,13 @@ /* No comment provided by engineer. */ "Joining group" = "Присъединяване към групата"; -/* No comment provided by engineer. */ +/* alert action */ "Keep" = "Запази"; /* No comment provided by engineer. */ "Keep the app open to use it from desktop" = "Дръжте приложението отворено, за да го използвате от настолното устройство"; -/* No comment provided by engineer. */ +/* alert title */ "Keep unused invitation?" = "Запази неизползваната покана за връзка?"; /* No comment provided by engineer. */ @@ -2362,9 +2295,6 @@ /* No comment provided by engineer. */ "Live messages" = "Съобщения на живо"; -/* No comment provided by engineer. */ -"Local" = "Локално"; - /* No comment provided by engineer. */ "Local name" = "Локално име"; @@ -2377,24 +2307,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Режим на заключване"; -/* No comment provided by engineer. */ -"Make a private connection" = "Добави поверителна връзка"; - /* No comment provided by engineer. */ "Make one message disappear" = "Накарайте едно съобщение да изчезне"; /* No comment provided by engineer. */ "Make profile private!" = "Направи профила поверителен!"; -/* No comment provided by engineer. */ -"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Уверете се, че %@ сървърните адреси са в правилен формат, разделени на редове и не се дублират (%@)."; - /* No comment provided by engineer. */ "Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Уверете се, че адресите на WebRTC ICE сървъра са в правилен формат, разделени на редове и не са дублирани."; -/* No comment provided by engineer. */ -"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Много хора попитаха: *ако SimpleX няма потребителски идентификатори, как може да доставя съобщения?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Маркирай като изтрито за всички"; @@ -2434,6 +2355,27 @@ /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "Членът ще бъде премахнат от групата - това не може да бъде отменено!"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Членовете на групата могат да добавят реакции към съобщенията."; + +/* No comment provided by engineer. */ +"Members can irreversibly delete sent messages. (24 hours)" = "Членовете на групата могат необратимо да изтриват изпратените съобщения. (24 часа)"; + +/* No comment provided by engineer. */ +"Members can send direct messages." = "Членовете на групата могат да изпращат лични съобщения."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Членовете на групата могат да изпращат изчезващи съобщения."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Членовете на групата могат да изпращат файлове и медия."; + +/* No comment provided by engineer. */ +"Members can send SimpleX links." = "Членовете на групата могат да изпращат SimpleX линкове."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Членовете на групата могат да изпращат гласови съобщения."; + /* item status text */ "Message delivery error" = "Грешка при доставката на съобщението"; @@ -2450,7 +2392,7 @@ "Message reactions are prohibited in this chat." = "Реакциите на съобщения са забранени в този чат."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Реакциите на съобщения са забранени в тази група."; +"Message reactions are prohibited." = "Реакциите на съобщения са забранени в тази група."; /* notification */ "message received" = "получено съобщение"; @@ -2513,7 +2455,7 @@ "Migration is completed" = "Миграцията е завършена"; /* No comment provided by engineer. */ -"Migrations: %@" = "Миграции: %@"; +"Migrations:" = "Миграции:"; /* time unit */ "minutes" = "минути"; @@ -2587,9 +2529,6 @@ /* notification */ "New contact:" = "Нов контакт:"; -/* No comment provided by engineer. */ -"New database archive" = "Нов архив на база данни"; - /* No comment provided by engineer. */ "New desktop app!" = "Ново настолно приложение!"; @@ -2653,12 +2592,18 @@ /* No comment provided by engineer. */ "No permission to record voice message" = "Няма разрешение за запис на гласово съобщение"; +/* No comment provided by engineer. */ +"No push server" = "Локално"; + /* No comment provided by engineer. */ "No received or sent files" = "Няма получени или изпратени файлове"; /* copied message info in history */ "no text" = "няма текст"; +/* No comment provided by engineer. */ +"No user identifiers." = "Първата платформа без никакви потребителски идентификатори – поверителна по дизайн."; + /* No comment provided by engineer. */ "Not compatible!" = "Несъвместим!"; @@ -2688,7 +2633,7 @@ /* feature offered item */ "offered %@: %@" = "предлага %1$@: %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ок"; /* No comment provided by engineer. */ @@ -2697,9 +2642,6 @@ /* No comment provided by engineer. */ "Old database" = "Стара база данни"; -/* No comment provided by engineer. */ -"Old database archive" = "Стар архив на база данни"; - /* group pref value */ "on" = "включено"; @@ -2716,7 +2658,7 @@ "Onion hosts will not be used." = "Няма се използват Onion хостове."; /* No comment provided by engineer. */ -"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Само потребителските устройства съхраняват потребителски профили, контакти, групи и съобщения, изпратени с **двуслойно криптиране от край до край**."; +"Only client devices store user profiles, contacts, groups, and messages." = "Само потребителските устройства съхраняват потребителски профили, контакти, групи и съобщения, изпратени с **двуслойно криптиране от край до край**."; /* No comment provided by engineer. */ "Only group owners can change group preferences." = "Само собствениците на групата могат да променят груповите настройки."; @@ -2775,12 +2717,6 @@ /* No comment provided by engineer. */ "Open Settings" = "Отвори настройки"; -/* authentication reason */ -"Open user profiles" = "Отвори потребителските профили"; - -/* No comment provided by engineer. */ -"Open-source protocol and code – anybody can run the servers." = "Протокол и код с отворен код – всеки може да оперира собствени сървъри."; - /* No comment provided by engineer. */ "Opening app…" = "Приложението се отваря…"; @@ -2842,10 +2778,7 @@ "peer-to-peer" = "peer-to-peer"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "Хората могат да се свържат с вас само чрез ликовете, които споделяте."; - -/* No comment provided by engineer. */ -"Periodically" = "Периодично"; +"Periodic" = "Периодично"; /* message decrypt error item */ "Permanent decryption error" = "Постоянна грешка при декриптиране"; @@ -2910,9 +2843,6 @@ /* No comment provided by engineer. */ "Preserve the last message draft, with attachments." = "Запазете последната чернова на съобщението с прикачени файлове."; -/* No comment provided by engineer. */ -"Preset server" = "Предварително зададен сървър"; - /* No comment provided by engineer. */ "Preset server address" = "Предварително зададен адрес на сървъра"; @@ -2940,16 +2870,10 @@ /* No comment provided by engineer. */ "Profile images" = "Профилни изображения"; -/* No comment provided by engineer. */ -"Profile name" = "Име на профила"; - -/* No comment provided by engineer. */ -"Profile name:" = "Име на профила:"; - /* No comment provided by engineer. */ "Profile password" = "Профилна парола"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "Актуализацията на профила ще бъде изпратена до вашите контакти."; /* No comment provided by engineer. */ @@ -3016,10 +2940,10 @@ "Read more" = "Прочетете още"; /* 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)."; +"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/chat-profiles.html#incognito-mode)." = "Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Прочетете повече в [Ръководство за потребителя](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)."; /* 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)."; @@ -3027,9 +2951,6 @@ /* No comment provided by engineer. */ "Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Прочетете повече в нашето [GitHub хранилище](https://github.com/simplex-chat/simplex-chat#readme)."; -/* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Прочетете повече в нашето хранилище в GitHub."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Потвърждениeто за доставка е деактивирано"; @@ -3211,13 +3132,14 @@ /* No comment provided by engineer. */ "Safer groups" = "По-безопасни групи"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Запази"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Запази (и уведоми контактите)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Запази и уведоми контакта"; /* No comment provided by engineer. */ @@ -3226,12 +3148,6 @@ /* No comment provided by engineer. */ "Save and update group profile" = "Запази и актуализирай профила на групата"; -/* No comment provided by engineer. */ -"Save archive" = "Запази архив"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Запази настройките за автоматично приемане"; - /* No comment provided by engineer. */ "Save group profile" = "Запази профила на групата"; @@ -3241,7 +3157,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Запази паролата в Keychain"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "Запази настройките?"; /* No comment provided by engineer. */ @@ -3250,12 +3166,9 @@ /* No comment provided by engineer. */ "Save servers" = "Запази сървърите"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "Запази сървърите?"; -/* No comment provided by engineer. */ -"Save settings?" = "Запази настройките?"; - /* No comment provided by engineer. */ "Save welcome message?" = "Запази съобщението при посрещане?"; @@ -3364,9 +3277,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Изпращай известия"; -/* No comment provided by engineer. */ -"Send notifications:" = "Изпратени известия:"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Изпращайте въпроси и идеи"; @@ -3379,7 +3289,7 @@ /* No comment provided by engineer. */ "Send up to 100 last messages to new members." = "Изпращане до последните 100 съобщения на нови членове."; -/* No comment provided by engineer. */ +/* alert message */ "Sender cancelled file transfer." = "Подателят отмени прехвърлянето на файла."; /* No comment provided by engineer. */ @@ -3478,7 +3388,8 @@ /* No comment provided by engineer. */ "Shape profile images" = "Променете формата на профилните изображения"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Сподели"; /* No comment provided by engineer. */ @@ -3487,7 +3398,7 @@ /* No comment provided by engineer. */ "Share address" = "Сподели адрес"; -/* No comment provided by engineer. */ +/* alert title */ "Share address with contacts?" = "Сподели адреса с контактите?"; /* No comment provided by engineer. */ @@ -3539,7 +3450,7 @@ "SimpleX links" = "SimpleX линкове"; /* No comment provided by engineer. */ -"SimpleX links are prohibited in this group." = "SimpleX линкове са забранени в тази група."; +"SimpleX links are prohibited." = "SimpleX линкове са забранени в тази група."; /* No comment provided by engineer. */ "SimpleX links not allowed" = "SimpleX линковете не са разрешени"; @@ -3601,9 +3512,6 @@ /* No comment provided by engineer. */ "Stop chat" = "Спри чата"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Спрете чата, за да активирате действията с базата данни"; - /* 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." = "Спрете чата, за да експортирате, импортирате или изтриете чат базата данни. Няма да можете да получавате и изпращате съобщения, докато чатът е спрян."; @@ -3619,10 +3527,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "Спри изпращането на файла?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Спри споделянето"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "Спри споделянето на адреса?"; /* authentication reason */ @@ -3691,7 +3599,7 @@ /* No comment provided by engineer. */ "Test servers" = "Тествай сървърите"; -/* No comment provided by engineer. */ +/* alert title */ "Tests failed!" = "Тестовете са неуспешни!"; /* No comment provided by engineer. */ @@ -3703,9 +3611,6 @@ /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Благодарение на потребителите – допринесете през Weblate!"; -/* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "Първата платформа без никакви потребителски идентификатори – поверителна по дизайн."; - /* No comment provided by engineer. */ "The app can notify you when you receive messages or contact requests - please open settings to enable." = "Приложението може да ви уведоми, когато получите съобщения или заявки за контакт - моля, отворете настройките, за да активирате."; @@ -3727,6 +3632,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Криптирането работи и новото споразумение за криптиране не е необходимо. Това може да доведе до грешки при свързване!"; +/* No comment provided by engineer. */ +"The future of messaging" = "Ново поколение поверителни съобщения"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "Хешът на предишното съобщение е различен."; @@ -3739,9 +3647,6 @@ /* No comment provided by engineer. */ "The message will be marked as moderated for all members." = "Съобщението ще бъде маркирано като модерирано за всички членове."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "Ново поколение поверителни съобщения"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "Старата база данни не бе премахната по време на миграцията, тя може да бъде изтрита."; @@ -3817,15 +3722,15 @@ /* No comment provided by engineer. */ "To make a new connection" = "За да направите нова връзка"; -/* 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." = "За да се защити поверителността, вместо потребителски идентификатори, използвани от всички други платформи, SimpleX има идентификатори за опашки от съобщения, отделни за всеки от вашите контакти."; - /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "За да не се разкрива часовата зона, файловете с изображения/глас използват 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." = "За да защитите информацията си, включете SimpleX заключване.\nЩе бъдете подканени да извършите идентификация, преди тази функция да бъде активирана."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "За да се защити поверителността, вместо потребителски идентификатори, използвани от всички други платформи, SimpleX има идентификатори за опашки от съобщения, отделни за всеки от вашите контакти."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "За да запишете гласово съобщение, моля, дайте разрешение за използване на микрофон."; @@ -4003,9 +3908,6 @@ /* No comment provided by engineer. */ "Use the app while in the call." = "Използвайте приложението по време на разговора."; -/* No comment provided by engineer. */ -"User profile" = "Потребителски профил"; - /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Използват се сървърите на SimpleX Chat."; @@ -4085,7 +3987,7 @@ "Voice messages are prohibited in this chat." = "Гласовите съобщения са забранени в този чат."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "Гласовите съобщения са забранени в тази група."; +"Voice messages are prohibited." = "Гласовите съобщения са забранени в тази група."; /* No comment provided by engineer. */ "Voice messages not allowed" = "Гласовите съобщения не са разрешени"; @@ -4144,9 +4046,6 @@ /* No comment provided by engineer. */ "When connecting audio and video calls." = "При свързване на аудио и видео разговори."; -/* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Когато хората искат да се свържат с вас, можете да ги приемете или отхвърлите."; - /* 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." = "Когато споделяте инкогнито профил с някого, този профил ще се използва за групите, в които той ви кани."; @@ -4180,9 +4079,6 @@ /* No comment provided by engineer. */ "you" = "вие"; -/* No comment provided by engineer. */ -"You" = "Вие"; - /* No comment provided by engineer. */ "You **must not** use the same database on two devices." = "**Не трябва** да използвате една и съща база данни на две устройства."; @@ -4267,9 +4163,6 @@ /* No comment provided by engineer. */ "You can share this address with your contacts to let them connect with **%@**." = "Можете да споделите този адрес с вашите контакти, за да им позволите да се свържат с **%@**."; -/* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Можете да споделите адреса си като линк или QR код - всеки може да се свърже с вас."; - /* No comment provided by engineer. */ "You can start chat via app Settings / Database or by restarting the app" = "Можете да започнете чат през Настройки на приложението / База данни или като рестартирате приложението"; @@ -4279,7 +4172,7 @@ /* No comment provided by engineer. */ "You can use markdown to format messages:" = "Можете да използвате markdown за форматиране на съобщенията:"; -/* No comment provided by engineer. */ +/* alert message */ "You can view invitation link again in connection details." = "Можете да видите отново линкът за покана в подробностите за връзката."; /* No comment provided by engineer. */ @@ -4298,10 +4191,10 @@ "you changed role of %@ to %@" = "променихте ролята на %1$@ на %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." = "Вие контролирате през кой сървър(и) **да получавате** съобщенията, вашите контакти – сървърите, които използвате, за да им изпращате съобщения."; +"You could not be verified; please try again." = "Не можахте да бъдете потвърдени; Моля, опитайте отново."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "Не можахте да бъдете потвърдени; Моля, опитайте отново."; +"You decide who can connect." = "Хората могат да се свържат с вас само чрез ликовете, които споделяте."; /* No comment provided by engineer. */ "You have already requested connection via this address!" = "Вече сте заявили връзка през този адрес!"; @@ -4384,9 +4277,6 @@ /* 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" = "Използвате инкогнито профил за тази група - за да се предотврати споделянето на основния ви профил, поканите на контакти не са разрешени"; -/* No comment provided by engineer. */ -"Your %@ servers" = "Вашите %@ сървъри"; - /* No comment provided by engineer. */ "Your calls" = "Вашите обаждания"; @@ -4430,7 +4320,7 @@ "Your profile **%@** will be shared." = "Вашият профил **%@** ще бъде споделен."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти.\nSimpleX сървърите не могат да видят вашия профил."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Вашият профил се съхранява на вашето устройство и се споделя само с вашите контакти. SimpleX сървърите не могат да видят вашия профил."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Вашият профил, контакти и доставени съобщения се съхраняват на вашето устройство."; @@ -4438,9 +4328,6 @@ /* No comment provided by engineer. */ "Your random profile" = "Вашият автоматично генериран профил"; -/* No comment provided by engineer. */ -"Your server" = "Вашият сървър"; - /* No comment provided by engineer. */ "Your server address" = "Вашият адрес на сървъра"; @@ -4453,6 +4340,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "Вашите SMP сървъри"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "Вашите XFTP сървъри"; - diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings index 220550c682..837e76ebbf 100644 --- a/apps/ios/cs.lproj/Localizable.strings +++ b/apps/ios/cs.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -55,9 +46,6 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Hvězda na GitHubu](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." = "**Přidat nový kontakt**: pro vytvoření jednorázového QR kódu nebo odkazu pro váš kontakt."; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e šifrovaný** audio hovor"; @@ -65,16 +53,16 @@ "**e2e encrypted** video call" = "**e2e šifrovaný** videohovor"; /* 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." = "**Soukromější**: kontrolovat nové zprávy každých 20 minut. Token zařízení je sdílen se serverem SimpleX Chat, ale ne kolik máte kontaktů nebo zpráv."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Soukromější**: kontrolovat nové zprávy každých 20 minut. Token zařízení je sdílen se serverem SimpleX Chat, ale ne kolik máte kontaktů nebo zpráv."; /* 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)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. */ "**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."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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. */ "**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."; @@ -274,12 +262,6 @@ /* No comment provided by engineer. */ "Abort changing address?" = "Přerušit změnu adresy?"; -/* No comment provided by engineer. */ -"About SimpleX" = "O SimpleX"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "O SimpleX adrese"; - /* No comment provided by engineer. */ "About SimpleX Chat" = "O SimpleX chat"; @@ -307,9 +289,6 @@ /* 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." = "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."; -/* No comment provided by engineer. */ -"Add preset servers" = "Přidejte přednastavené servery"; - /* No comment provided by engineer. */ "Add profile" = "Přidat profil"; @@ -436,6 +415,9 @@ /* No comment provided by engineer. */ "Answer call" = "Přijmout hovor"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "Servery může provozovat kdokoli."; + /* No comment provided by engineer. */ "App build: %@" = "Sestavení aplikace: %@"; @@ -562,7 +544,8 @@ /* No comment provided by engineer. */ "Can't invite contacts!" = "Nelze pozvat kontakty!"; -/* No comment provided by engineer. */ +/* alert action + alert button */ "Cancel" = "Zrušit"; /* feature offered item */ @@ -571,7 +554,7 @@ /* No comment provided by engineer. */ "Cannot access keychain to save database password" = "Nelze získat přístup ke klíčence pro uložení hesla databáze"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "Nelze přijmout soubor"; /* No comment provided by engineer. */ @@ -620,9 +603,6 @@ /* chat item text */ "changing address…" = "změna adresy…"; -/* No comment provided by engineer. */ -"Chat archive" = "Chat se archivuje"; - /* No comment provided by engineer. */ "Chat console" = "Konzola pro chat"; @@ -645,9 +625,12 @@ "Chat preferences" = "Předvolby chatu"; /* No comment provided by engineer. */ -"Chats" = "Chaty"; +"Chat profile" = "Profil uživatele"; /* No comment provided by engineer. */ +"Chats" = "Chaty"; + +/* alert title */ "Check server address and try again." = "Zkontrolujte adresu serveru a zkuste to znovu."; /* No comment provided by engineer. */ @@ -746,7 +729,7 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Připojování k serveru... (chyba: %@)"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "připojení…"; /* No comment provided by engineer. */ @@ -812,9 +795,6 @@ /* No comment provided by engineer. */ "Create" = "Vytvořit"; -/* No comment provided by engineer. */ -"Create an address to let people connect with you." = "Vytvořit adresu, aby se s vámi lidé mohli spojit."; - /* server test step */ "Create file" = "Vytvořit soubor"; @@ -839,9 +819,6 @@ /* No comment provided by engineer. */ "Create your profile" = "Vytvořte si profil"; -/* No comment provided by engineer. */ -"Created on %@" = "Vytvořeno na %@"; - /* No comment provided by engineer. */ "creator" = "tvůrce"; @@ -938,7 +915,8 @@ /* No comment provided by engineer. */ "default (yes)" = "výchozí (ano)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Smazat"; @@ -954,12 +932,6 @@ /* No comment provided by engineer. */ "Delete all files" = "Odstranit všechny soubory"; -/* No comment provided by engineer. */ -"Delete archive" = "Smazat archiv"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "Smazat archiv chatu?"; - /* No comment provided by engineer. */ "Delete chat profile" = "Smazat chat profil"; @@ -1087,7 +1059,7 @@ "Direct messages" = "Přímé zprávy"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Přímé zprávy mezi členy jsou v této skupině zakázány."; +"Direct messages between members are prohibited." = "Přímé zprávy mezi členy jsou v této skupině zakázány."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Vypnout (zachovat přepsání)"; @@ -1111,7 +1083,7 @@ "Disappearing messages are prohibited in this chat." = "Mizící zprávy jsou v tomto chatu zakázány."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "Mizící zprávy jsou v této skupině zakázány."; +"Disappearing messages are prohibited." = "Mizící zprávy jsou v této skupině zakázány."; /* No comment provided by engineer. */ "Disappears at" = "Zmizí v"; @@ -1305,9 +1277,6 @@ /* No comment provided by engineer. */ "Error accepting contact request" = "Chyba při přijímání žádosti o kontakt"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Chyba přístupu k souboru databáze"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Chyba přidávání člena(ů)"; @@ -1377,18 +1346,12 @@ /* No comment provided by engineer. */ "Error joining group" = "Chyba při připojování ke skupině"; -/* No comment provided by engineer. */ -"Error loading %@ servers" = "Chyba načítání %@ serverů"; - -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Chyba při příjmu souboru"; /* No comment provided by engineer. */ "Error removing member" = "Chyba při odebrání člena"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Chyba při ukládání serverů %@"; - /* No comment provided by engineer. */ "Error saving group profile" = "Chyba při ukládání profilu skupiny"; @@ -1422,7 +1385,7 @@ /* No comment provided by engineer. */ "Error stopping chat" = "Chyba při zastavení chatu"; -/* No comment provided by engineer. */ +/* alertTitle */ "Error switching profile!" = "Chyba při přepínání profilu!"; /* No comment provided by engineer. */ @@ -1443,8 +1406,7 @@ /* No comment provided by engineer. */ "Error: " = "Chyba: "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Chyba: %@"; /* No comment provided by engineer. */ @@ -1499,7 +1461,7 @@ "Files and media" = "Soubory a média"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "Soubory a média jsou zakázány v této skupině."; +"Files and media are prohibited." = "Soubory a média jsou zakázány v této skupině."; /* No comment provided by engineer. */ "Files and media prohibited!" = "Soubory a média jsou zakázány!"; @@ -1543,9 +1505,6 @@ /* No comment provided by engineer. */ "Full name (optional)" = "Celé jméno (volitelně)"; -/* No comment provided by engineer. */ -"Full name:" = "Celé jméno:"; - /* No comment provided by engineer. */ "Fully re-implemented - work in background!" = "Plně přepracováno, prácuje na pozadí!"; @@ -1585,24 +1544,6 @@ /* No comment provided by engineer. */ "Group links" = "Odkazy na skupiny"; -/* No comment provided by engineer. */ -"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. (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."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Členové skupiny mohou posílat mizící zprávy."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Členové skupiny mohou posílat soubory a média."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Členové skupiny mohou posílat hlasové zprávy."; - /* notification */ "Group message:" = "Skupinová zpráva:"; @@ -1660,9 +1601,6 @@ /* time unit */ "hours" = "hodin"; -/* No comment provided by engineer. */ -"How it works" = "Jak to funguje"; - /* No comment provided by engineer. */ "How SimpleX works" = "Jak SimpleX funguje"; @@ -1703,7 +1641,7 @@ "Immediately" = "Ihned"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Odolná vůči spamu a zneužití"; +"Immune to spam" = "Odolná vůči spamu a zneužití"; /* No comment provided by engineer. */ "Import" = "Import"; @@ -1772,10 +1710,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Nainstalujte [SimpleX Chat pro terminál](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "Okamžitá oznámení budou skryta!\n"; +"Instant" = "Okamžitě"; /* No comment provided by engineer. */ -"Instantly" = "Okamžitě"; +"Instant push notifications will be hidden!\n" = "Okamžitá oznámení budou skryta!\n"; /* No comment provided by engineer. */ "Interface" = "Rozhranní"; @@ -1792,7 +1730,7 @@ /* invalid chat item */ "invalid data" = "neplatné údaje"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "Neplatná adresa serveru!"; /* item status text */ @@ -1838,7 +1776,7 @@ "Irreversible message deletion is prohibited in this chat." = "Nevratné mazání zpráv je v tomto chatu zakázáno."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "Nevratné mazání zpráv je v této skupině zakázáno."; +"Irreversible message deletion is prohibited." = "Nevratné mazání zpráv je v této skupině zakázáno."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Umožňuje mít v jednom profilu chatu mnoho anonymních spojení bez jakýchkoli sdílených údajů mezi nimi."; @@ -1921,9 +1859,6 @@ /* 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"; @@ -1936,24 +1871,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Režim zámku"; -/* No comment provided by engineer. */ -"Make a private connection" = "Vytvořte si soukromé připojení"; - /* No comment provided by engineer. */ "Make one message disappear" = "Nechat jednu zprávu zmizet"; /* No comment provided by engineer. */ "Make profile private!" = "Změnit profil na soukromý!"; -/* No comment provided by engineer. */ -"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Ujistěte se, že adresy %@ serverů jsou ve správném formátu, oddělené řádky a nejsou duplicitní (%@)."; - /* No comment provided by engineer. */ "Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Ujistěte se, že adresy serverů WebRTC ICE jsou ve správném formátu, oddělené na řádcích a nejsou duplicitní."; -/* No comment provided by engineer. */ -"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Mnoho lidí se ptalo: *Pokud SimpleX nemá žádné uživatelské identifikátory, jak může doručovat zprávy?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Označit jako smazané pro všechny"; @@ -1990,6 +1916,24 @@ /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "Člen bude odstraněn ze skupiny - toto nelze vzít zpět!"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Členové skupin mohou přidávat reakce na zprávy."; + +/* No comment provided by engineer. */ +"Members can irreversibly delete sent messages. (24 hours)" = "Členové skupiny mohou nevratně mazat odeslané zprávy. (24 hodin)"; + +/* No comment provided by engineer. */ +"Members can send direct messages." = "Členové skupiny mohou posílat přímé zprávy."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Členové skupiny mohou posílat mizící zprávy."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Členové skupiny mohou posílat soubory a média."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Členové skupiny mohou posílat hlasové zprávy."; + /* item status text */ "Message delivery error" = "Chyba doručení zprávy"; @@ -2006,7 +1950,7 @@ "Message reactions are prohibited in this chat." = "Reakce na zprávy jsou v tomto chatu zakázány."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Reakce na zprávy jsou v této skupině zakázány."; +"Message reactions are prohibited." = "Reakce na zprávy jsou v této skupině zakázány."; /* notification */ "message received" = "zpráva přijata"; @@ -2033,7 +1977,7 @@ "Migration is completed" = "Přenesení dokončeno"; /* No comment provided by engineer. */ -"Migrations: %@" = "Migrace: %@"; +"Migrations:" = "Migrace:"; /* time unit */ "minutes" = "minut"; @@ -2095,9 +2039,6 @@ /* notification */ "New contact:" = "Nový kontakt:"; -/* No comment provided by engineer. */ -"New database archive" = "Archiv nové databáze"; - /* No comment provided by engineer. */ "New desktop app!" = "Nová desktopová aplikace!"; @@ -2158,12 +2099,18 @@ /* No comment provided by engineer. */ "No permission to record voice message" = "Nemáte oprávnění nahrávat hlasové zprávy"; +/* No comment provided by engineer. */ +"No push server" = "Místní"; + /* No comment provided by engineer. */ "No received or sent files" = "Žádné přijaté ani odeslané soubory"; /* copied message info in history */ "no text" = "žádný text"; +/* No comment provided by engineer. */ +"No user identifiers." = "Bez uživatelských identifikátorů"; + /* No comment provided by engineer. */ "Notifications" = "Oznámení"; @@ -2190,15 +2137,12 @@ /* feature offered item */ "offered %@: %@" = "nabídl %1$@: %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ok"; /* No comment provided by engineer. */ "Old database" = "Stará databáze"; -/* No comment provided by engineer. */ -"Old database archive" = "Archiv staré databáze"; - /* group pref value */ "on" = "zapnuto"; @@ -2215,7 +2159,7 @@ "Onion hosts will not be used." = "Onion hostitelé nebudou použiti."; /* No comment provided by engineer. */ -"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Pouze klientská zařízení ukládají uživatelské profily, kontakty, skupiny a zprávy odeslané s **2vrstvým šifrováním typu end-to-end**."; +"Only client devices store user profiles, contacts, groups, and messages." = "Pouze klientská zařízení ukládají uživatelské profily, kontakty, skupiny a zprávy odeslané s **2vrstvým šifrováním typu end-to-end**."; /* No comment provided by engineer. */ "Only group owners can change group preferences." = "Předvolby skupiny mohou měnit pouze vlastníci skupiny."; @@ -2268,12 +2212,6 @@ /* No comment provided by engineer. */ "Open Settings" = "Otevřít nastavení"; -/* authentication reason */ -"Open user profiles" = "Otevřít uživatelské profily"; - -/* 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."; - /* member role */ "owner" = "vlastník"; @@ -2302,10 +2240,7 @@ "peer-to-peer" = "peer-to-peer"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "Lidé se s vámi mohou spojit pouze prostřednictvím odkazů, které sdílíte."; - -/* No comment provided by engineer. */ -"Periodically" = "Pravidelně"; +"Periodic" = "Pravidelně"; /* message decrypt error item */ "Permanent decryption error" = "Chyba dešifrování"; @@ -2361,9 +2296,6 @@ /* No comment provided by engineer. */ "Preserve the last message draft, with attachments." = "Zachování posledního návrhu zprávy s přílohami."; -/* No comment provided by engineer. */ -"Preset server" = "Přednastavený server"; - /* No comment provided by engineer. */ "Preset server address" = "Přednastavená adresa serveru"; @@ -2388,7 +2320,7 @@ /* No comment provided by engineer. */ "Profile password" = "Heslo profilu"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "Aktualizace profilu bude zaslána vašim kontaktům."; /* No comment provided by engineer. */ @@ -2443,7 +2375,7 @@ "Read more" = "Přečíst více"; /* No comment provided by engineer. */ -"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Další informace naleznete v [Uživatelské příručce](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)."; /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Přečtěte si více v [Uživatelské příručce](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2451,9 +2383,6 @@ /* No comment provided by engineer. */ "Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Přečtěte si více v našem [GitHub repozitáři](https://github.com/simplex-chat/simplex-chat#readme)."; -/* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Další informace najdete v našem repozitáři GitHub."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Informace o dodání jsou zakázány"; @@ -2602,13 +2531,14 @@ /* No comment provided by engineer. */ "Run chat" = "Spustit chat"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Uložit"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Uložit (a informovat kontakty)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Uložit a upozornit kontakt"; /* No comment provided by engineer. */ @@ -2617,12 +2547,6 @@ /* No comment provided by engineer. */ "Save and update group profile" = "Uložit a aktualizovat profil skupiny"; -/* No comment provided by engineer. */ -"Save archive" = "Uložit archiv"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Uložit nastavení automatického přijímání"; - /* No comment provided by engineer. */ "Save group profile" = "Uložení profilu skupiny"; @@ -2632,7 +2556,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Uložit přístupovou frázi do Klíčenky"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "Uložit předvolby?"; /* No comment provided by engineer. */ @@ -2641,12 +2565,9 @@ /* No comment provided by engineer. */ "Save servers" = "Uložit servery"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "Uložit servery?"; -/* No comment provided by engineer. */ -"Save settings?" = "Uložit nastavení?"; - /* No comment provided by engineer. */ "Save welcome message?" = "Uložit uvítací zprávu?"; @@ -2731,9 +2652,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Odeslat oznámení"; -/* No comment provided by engineer. */ -"Send notifications:" = "Odeslat oznámení:"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Zasílání otázek a nápadů"; @@ -2743,7 +2661,7 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Odeslat je z galerie nebo vlastní klávesnice."; -/* No comment provided by engineer. */ +/* alert message */ "Sender cancelled file transfer." = "Odesílatel zrušil přenos souboru."; /* No comment provided by engineer. */ @@ -2827,7 +2745,8 @@ /* No comment provided by engineer. */ "Settings" = "Nastavení"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Sdílet"; /* No comment provided by engineer. */ @@ -2836,7 +2755,7 @@ /* No comment provided by engineer. */ "Share address" = "Sdílet adresu"; -/* No comment provided by engineer. */ +/* alert title */ "Share address with contacts?" = "Sdílet adresu s kontakty?"; /* No comment provided by engineer. */ @@ -2926,9 +2845,6 @@ /* No comment provided by engineer. */ "Stop" = "Zastavit"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Zastavte chat pro povolení akcí databáze"; - /* 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." = "Zastavení chatu pro export, import nebo smazání databáze chatu. Během zastavení chatu nebudete moci přijímat a odesílat zprávy."; @@ -2944,10 +2860,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "Zastavit odesílání souboru?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Přestat sdílet"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "Přestat sdílet adresu?"; /* authentication reason */ @@ -3004,7 +2920,7 @@ /* No comment provided by engineer. */ "Test servers" = "Testovací servery"; -/* No comment provided by engineer. */ +/* alert title */ "Tests failed!" = "Testy selhaly!"; /* No comment provided by engineer. */ @@ -3016,9 +2932,6 @@ /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Díky uživatelům - přispívejte prostřednictvím Weblate!"; -/* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "1. Platforma bez identifikátorů uživatelů - soukromá už od záměru."; - /* No comment provided by engineer. */ "The app can notify you when you receive messages or contact requests - please open settings to enable." = "Aplikace vás může upozornit na přijaté zprávy nebo žádosti o kontakt - povolte to v nastavení."; @@ -3037,6 +2950,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Šifrování funguje a nové povolení šifrování není vyžadováno. To může vyvolat chybu v připojení!"; +/* No comment provided by engineer. */ +"The future of messaging" = "Nová generace soukromých zpráv"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "Hash předchozí zprávy se liší."; @@ -3049,9 +2965,6 @@ /* No comment provided by engineer. */ "The message will be marked as moderated for all members." = "Zpráva bude pro všechny členy označena jako moderovaná."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "Nová generace soukromých zpráv"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "Stará databáze nebyla během přenášení odstraněna, lze ji smazat."; @@ -3103,15 +3016,15 @@ /* No comment provided by engineer. */ "To make a new connection" = "Vytvoření nového připojení"; -/* 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." = "Pro ochranu soukromí namísto ID uživatelů používaných všemi ostatními platformami má SimpleX identifikátory pro fronty zpráv, oddělené pro každý z vašich kontaktů."; - /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "K ochraně časového pásma používají obrazové/hlasové soubory 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." = "Chcete-li chránit své informace, zapněte zámek SimpleX Lock.\nPřed zapnutím této funkce budete vyzváni k dokončení ověření."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "Pro ochranu soukromí namísto ID uživatelů používaných všemi ostatními platformami má SimpleX identifikátory pro fronty zpráv, oddělené pro každý z vašich kontaktů."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "Chcete-li nahrávat hlasové zprávy, udělte povolení k použití mikrofonu."; @@ -3238,9 +3151,6 @@ /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "Používat servery SimpleX Chat?"; -/* No comment provided by engineer. */ -"User profile" = "Profil uživatele"; - /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Používat servery SimpleX Chat."; @@ -3296,7 +3206,7 @@ "Voice messages are prohibited in this chat." = "Hlasové zprávy jsou v tomto chatu zakázány."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "Hlasové zprávy jsou v této skupině zakázány."; +"Voice messages are prohibited." = "Hlasové zprávy jsou v této skupině zakázány."; /* No comment provided by engineer. */ "Voice messages prohibited!" = "Hlasové zprávy jsou zakázány!"; @@ -3340,9 +3250,6 @@ /* No comment provided by engineer. */ "When available" = "Když je k dispozici"; -/* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Když někdo požádá o připojení, můžete žádost přijmout nebo odmítnout."; - /* 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." = "Pokud s někým sdílíte inkognito profil, bude tento profil použit pro skupiny, do kterých vás pozve."; @@ -3358,9 +3265,6 @@ /* pref value */ "yes" = "ano"; -/* No comment provided by engineer. */ -"You" = "Vy"; - /* No comment provided by engineer. */ "You accepted connection" = "Přijali jste spojení"; @@ -3412,9 +3316,6 @@ /* No comment provided by engineer. */ "You can share this address with your contacts to let them connect with **%@**." = "Tuto adresu můžete sdílet s vašimi kontakty, abyse se mohli spojit s **%@**."; -/* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit."; - /* No comment provided by engineer. */ "You can start chat via app Settings / Database or by restarting the app" = "Chat můžete zahájit prostřednictvím aplikace Nastavení / Databáze nebo restartováním aplikace"; @@ -3440,10 +3341,10 @@ "you changed role of %@ to %@" = "změnili jste roli z %1$@ na %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." = "Sami řídíte, přes který server(y) **přijímat** zprávy, své kontakty – servery, které používáte k odesílání zpráv."; +"You could not be verified; please try again." = "Nemohli jste být ověřeni; Zkuste to prosím znovu."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "Nemohli jste být ověřeni; Zkuste to prosím znovu."; +"You decide who can connect." = "Lidé se s vámi mohou spojit pouze prostřednictvím odkazu, který sdílíte."; /* No comment provided by engineer. */ "You have to enter passphrase every time the app starts - it is not stored on the device." = "Musíte zadat přístupovou frázi při každém spuštění aplikace - není uložena v zařízení."; @@ -3511,9 +3412,6 @@ /* 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" = "Pro tuto skupinu používáte inkognito profil - abyste zabránili sdílení svého hlavního profilu, není pozvání kontaktů povoleno"; -/* No comment provided by engineer. */ -"Your %@ servers" = "Vaše servery %@"; - /* No comment provided by engineer. */ "Your calls" = "Vaše hovory"; @@ -3554,7 +3452,7 @@ "Your profile **%@** will be shared." = "Váš profil **%@** bude sdílen."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty.\nServery SimpleX nevidí váš profil."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty. Servery SimpleX nevidí váš profil."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení."; @@ -3562,9 +3460,6 @@ /* No comment provided by engineer. */ "Your random profile" = "Váš náhodný profil"; -/* No comment provided by engineer. */ -"Your server" = "Váš server"; - /* No comment provided by engineer. */ "Your server address" = "Adresa vašeho serveru"; @@ -3577,6 +3472,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "Vaše servery SMP"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "Vaše XFTP servery"; - diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index bb8e730bce..cad89ed29a 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -65,10 +56,7 @@ "[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 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. */ -"**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."; +"**Create 1-time link**: to create and share a new invitation link." = "**Kontakt hinzufügen**: Um einen neuen Einladungslink zu erstellen."; /* No comment provided by engineer. */ "**Create group**: to create a new group." = "**Gruppe erstellen**: Um eine neue Gruppe zu erstellen."; @@ -80,10 +68,10 @@ "**e2e encrypted** video call" = "**E2E-verschlüsselter** Videoanruf"; /* 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." = "**Mehr Privatsphäre**: Es wird alle 20 Minuten auf neue Nachrichten geprüft. Nur Ihr Geräte-Token wird dem SimpleX-Chat-Server mitgeteilt, aber nicht wie viele Kontakte Sie haben oder welche Nachrichten Sie empfangen."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Mehr Privatsphäre**: Es wird alle 20 Minuten auf neue Nachrichten geprüft. Nur Ihr Geräte-Token wird dem SimpleX-Chat-Server mitgeteilt, aber nicht wie viele Kontakte Sie haben oder welche Nachrichten Sie empfangen."; /* 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)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. */ "**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Bitte beachten Sie**: Aus Sicherheitsgründen wird die Nachrichtenentschlüsselung Ihrer Verbindungen abgebrochen, wenn Sie die gleiche Datenbank auf zwei Geräten nutzen."; @@ -92,7 +80,10 @@ "**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."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received." = "**Link scannen / einfügen**: Um eine Verbindung über den Link herzustellen, den Sie erhalten haben."; /* 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."; @@ -154,12 +145,21 @@ /* No comment provided by engineer. */ "%@ is verified" = "%@ wurde erfolgreich überprüft"; +/* No comment provided by engineer. */ +"%@ server" = "%@ Server"; + +/* No comment provided by engineer. */ +"%@ servers" = "%@ Server"; + /* No comment provided by engineer. */ "%@ uploaded" = "%@ hochgeladen"; /* notification title */ "%@ wants to connect!" = "%@ will sich mit Ihnen verbinden!"; +/* format for date separator in chat */ +"%@, %@" = "%1$@, %2$@"; + /* No comment provided by engineer. */ "%@, %@ and %lld members" = "%@, %@ und %lld Mitglieder"; @@ -172,9 +172,24 @@ /* time interval */ "%d days" = "%d Tage"; +/* forward confirmation reason */ +"%d file(s) are still being downloaded." = "%d Datei(en) wird/werden immer noch heruntergeladen."; + +/* forward confirmation reason */ +"%d file(s) failed to download." = "Bei %d Datei(en) ist das Herunterladen fehlgeschlagen."; + +/* forward confirmation reason */ +"%d file(s) were deleted." = "%d Datei(en) wurde(n) gelöscht."; + +/* forward confirmation reason */ +"%d file(s) were not downloaded." = "%d Datei(en) wurde(n) nicht heruntergeladen."; + /* time interval */ "%d hours" = "%d Stunden"; +/* alert title */ +"%d messages not forwarded" = "%d Nachrichten wurden nicht weitergeleitet"; + /* time interval */ "%d min" = "%d min"; @@ -289,6 +304,12 @@ /* time interval */ "1 week" = "wöchentlich"; +/* No comment provided by engineer. */ +"1-time link" = "Einmal-Link"; + +/* No comment provided by engineer. */ +"1-time link can be used *with one contact only* - share in person or via any messenger." = "Ein Einmal-Link kann *nur mit einem Kontakt* genutzt werden - teilen Sie in nur persönlich oder über einen beliebigen Messenger."; + /* No comment provided by engineer. */ "5 minutes" = "5 Minuten"; @@ -323,10 +344,7 @@ "Abort changing address?" = "Wechsel der Empfängeradresse beenden?"; /* No comment provided by engineer. */ -"About SimpleX" = "Über SimpleX"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "Über die SimpleX-Adresse"; +"About operators" = "Über Betreiber"; /* No comment provided by engineer. */ "About SimpleX Chat" = "Über SimpleX Chat"; @@ -342,6 +360,9 @@ swipe action */ "Accept" = "Annehmen"; +/* No comment provided by engineer. */ +"Accept conditions" = "Nutzungsbedingungen akzeptieren"; + /* No comment provided by engineer. */ "Accept connection request?" = "Kontaktanfrage annehmen?"; @@ -355,6 +376,12 @@ /* call status */ "accepted call" = "Anruf angenommen"; +/* No comment provided by engineer. */ +"Accepted conditions" = "Akzeptierte Nutzungsbedingungen"; + +/* chat list item title */ +"accepted invitation" = "Einladung akzeptiert"; + /* No comment provided by engineer. */ "Acknowledged" = "Bestätigt"; @@ -368,10 +395,7 @@ "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"; +"Add friends" = "Freunde aufnehmen"; /* No comment provided by engineer. */ "Add profile" = "Profil hinzufügen"; @@ -382,12 +406,24 @@ /* No comment provided by engineer. */ "Add servers by scanning QR codes." = "Fügen Sie Server durch Scannen der QR Codes hinzu."; +/* No comment provided by engineer. */ +"Add team members" = "Team-Mitglieder aufnehmen"; + /* No comment provided by engineer. */ "Add to another device" = "Einem anderen Gerät hinzufügen"; /* No comment provided by engineer. */ "Add welcome message" = "Begrüßungsmeldung hinzufügen"; +/* No comment provided by engineer. */ +"Add your team members to the conversations." = "Nehmen Sie Team-Mitglieder in Ihre Unterhaltungen auf."; + +/* No comment provided by engineer. */ +"Added media & file servers" = "Medien- und Dateiserver hinzugefügt"; + +/* No comment provided by engineer. */ +"Added message servers" = "Nachrichtenserver hinzugefügt"; + /* No comment provided by engineer. */ "Additional accent" = "Erste Akzentfarbe"; @@ -403,6 +439,12 @@ /* No comment provided by engineer. */ "Address change will be aborted. Old receiving address will be used." = "Der Wechsel der Empfängeradresse wird beendet. Die bisherige Adresse wird weiter verwendet."; +/* No comment provided by engineer. */ +"Address or 1-time link?" = "Adress- oder Einmal-Link?"; + +/* No comment provided by engineer. */ +"Address settings" = "Adress-Einstellungen"; + /* member role */ "admin" = "Admin"; @@ -437,7 +479,7 @@ "All data is erased when it is entered." = "Alle Daten werden gelöscht, sobald dieser eingegeben wird."; /* No comment provided by engineer. */ -"All data is private to your device." = "Alle Daten werden nur auf Ihrem Gerät gespeichert."; +"All data is kept private on your device." = "Alle Daten werden nur auf Ihrem Gerät gespeichert."; /* No comment provided by engineer. */ "All group members will remain connected." = "Alle Gruppenmitglieder bleiben verbunden."; @@ -445,6 +487,9 @@ /* feature role */ "all members" = "Alle Mitglieder"; +/* No comment provided by engineer. */ +"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Alle Nachrichten und Dateien werden **Ende-zu-Ende verschlüsselt** versendet - in Direkt-Nachrichten mit Post-Quantum-Security."; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone!" = "Es werden alle Nachrichten gelöscht. Dies kann nicht rückgängig gemacht werden!"; @@ -454,7 +499,7 @@ /* No comment provided by engineer. */ "All new messages from %@ will be hidden!" = "Von %@ werden alle neuen Nachrichten ausgeblendet!"; -/* No comment provided by engineer. */ +/* profile dropdown */ "All profiles" = "Alle Profile"; /* No comment provided by engineer. */ @@ -559,6 +604,9 @@ /* No comment provided by engineer. */ "Answer call" = "Anruf annehmen"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "Jeder kann seine eigenen Server aufsetzen."; + /* No comment provided by engineer. */ "App build: %@" = "App Build: %@"; @@ -577,6 +625,9 @@ /* No comment provided by engineer. */ "App passcode is replaced with self-destruct passcode." = "App-Zugangscode wurde durch den Selbstzerstörungs-Zugangscode ersetzt."; +/* No comment provided by engineer. */ +"App session" = "App-Sitzung"; + /* No comment provided by engineer. */ "App version" = "App Version"; @@ -649,6 +700,9 @@ /* No comment provided by engineer. */ "Auto-accept images" = "Bilder automatisch akzeptieren"; +/* alert title */ +"Auto-accept settings" = "Einstellungen automatisch akzeptieren"; + /* No comment provided by engineer. */ "Back" = "Zurück"; @@ -670,14 +724,29 @@ /* No comment provided by engineer. */ "Bad message ID" = "Falsche Nachrichten-ID"; +/* No comment provided by engineer. */ +"Better calls" = "Verbesserte Anrufe"; + /* No comment provided by engineer. */ "Better groups" = "Bessere Gruppen"; +/* No comment provided by engineer. */ +"Better message dates." = "Verbesserte Nachrichten-Datumsinformation"; + /* No comment provided by engineer. */ "Better messages" = "Verbesserungen bei Nachrichten"; /* No comment provided by engineer. */ -"Better networking" = "Bessere Vernetzung"; +"Better networking" = "Kontrollieren Sie Ihr Netzwerk"; + +/* No comment provided by engineer. */ +"Better notifications" = "Verbesserte Benachrichtigungen"; + +/* No comment provided by engineer. */ +"Better security ✅" = "Verbesserte Sicherheit ✅"; + +/* No comment provided by engineer. */ +"Better user experience" = "Verbesserte Nutzer-Erfahrung"; /* No comment provided by engineer. */ "Black" = "Schwarz"; @@ -739,6 +808,12 @@ /* 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)!" = "Bulgarisch, Finnisch, Thailändisch und Ukrainisch - Dank der Nutzer und [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; +/* No comment provided by engineer. */ +"Business address" = "Geschäftliche Adresse"; + +/* No comment provided by engineer. */ +"Business chats" = "Geschäftliche Chats"; + /* 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)." = "Per Chat-Profil (Voreinstellung) oder [per Verbindung](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; @@ -781,7 +856,8 @@ /* No comment provided by engineer. */ "Can't message member" = "Mitglied kann nicht benachrichtigt werden"; -/* No comment provided by engineer. */ +/* alert action + alert button */ "Cancel" = "Abbrechen"; /* No comment provided by engineer. */ @@ -796,7 +872,7 @@ /* No comment provided by engineer. */ "Cannot forward message" = "Die Nachricht kann nicht weitergeleitet werden"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "Datei kann nicht empfangen werden"; /* snd error text */ @@ -808,6 +884,9 @@ /* No comment provided by engineer. */ "Change" = "Ändern"; +/* authentication reason */ +"Change chat profiles" = "Chat-Profile wechseln"; + /* No comment provided by engineer. */ "Change database passphrase?" = "Datenbank-Passwort ändern?"; @@ -852,7 +931,13 @@ "changing address…" = "Wechsel der Empfängeradresse wurde gestartet…"; /* No comment provided by engineer. */ -"Chat archive" = "Datenbank Archiv"; +"Chat" = "Chat"; + +/* No comment provided by engineer. */ +"Chat already exists" = "Chat besteht bereits"; + +/* No comment provided by engineer. */ +"Chat already exists!" = "Chat besteht bereits!"; /* No comment provided by engineer. */ "Chat colors" = "Chat-Farben"; @@ -890,13 +975,31 @@ /* No comment provided by engineer. */ "Chat preferences" = "Chat-Präferenzen"; +/* alert message */ +"Chat preferences were changed." = "Die Chat-Präferenzen wurden geändert."; + +/* No comment provided by engineer. */ +"Chat profile" = "Benutzerprofil"; + /* No comment provided by engineer. */ "Chat theme" = "Chat-Design"; +/* No comment provided by engineer. */ +"Chat will be deleted for all members - this cannot be undone!" = "Der Chat wird für alle Mitglieder gelöscht. Dies kann nicht rückgängig gemacht werden!"; + +/* No comment provided by engineer. */ +"Chat will be deleted for you - this cannot be undone!" = "Der Chat wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!"; + /* No comment provided by engineer. */ "Chats" = "Chats"; /* No comment provided by engineer. */ +"Check messages every 20 min." = "Alle 20min Nachrichten überprüfen."; + +/* No comment provided by engineer. */ +"Check messages when allowed." = "Wenn es erlaubt ist, Nachrichten überprüfen."; + +/* alert title */ "Check server address and try again." = "Überprüfen Sie die Serveradresse und versuchen Sie es nochmal."; /* No comment provided by engineer. */ @@ -921,16 +1024,16 @@ "Chunks uploaded" = "Daten-Pakete hochgeladen"; /* swipe action */ -"Clear" = "Löschen"; +"Clear" = "Entfernen"; /* No comment provided by engineer. */ -"Clear conversation" = "Chatinhalte löschen"; +"Clear conversation" = "Chat-Inhalte entfernen"; /* No comment provided by engineer. */ -"Clear conversation?" = "Unterhaltung löschen?"; +"Clear conversation?" = "Chat-Inhalte entfernen?"; /* No comment provided by engineer. */ -"Clear private notes?" = "Private Notizen löschen?"; +"Clear private notes?" = "Private Notizen entfernen?"; /* No comment provided by engineer. */ "Clear verification" = "Überprüfung zurücknehmen"; @@ -957,10 +1060,34 @@ "Completed" = "Abgeschlossen"; /* No comment provided by engineer. */ -"Configure ICE servers" = "ICE-Server konfigurieren"; +"Conditions accepted on: %@." = "Die Nutzungsbedingungen wurden akzeptiert am: %@."; /* No comment provided by engineer. */ -"Configured %@ servers" = "Konfigurierte %@ Server"; +"Conditions are accepted for the operator(s): **%@**." = "Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**."; + +/* No comment provided by engineer. */ +"Conditions are already accepted for these operator(s): **%@**." = "Die Nutzungsbedingungen der/des folgenden Betreiber(s) wurden schon akzeptiert: **%@**."; + +/* No comment provided by engineer. */ +"Conditions of use" = "Nutzungsbedingungen"; + +/* No comment provided by engineer. */ +"Conditions will be accepted for enabled operators after 30 days." = "Die Nutzungsbedingungen der aktivierten Betreiber werden nach 30 Tagen akzeptiert."; + +/* No comment provided by engineer. */ +"Conditions will be accepted for operator(s): **%@**." = "Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**."; + +/* No comment provided by engineer. */ +"Conditions will be accepted for the operator(s): **%@**." = "Die Nutzungsbedingungen der/des Betreiber(s) werden akzeptiert: **%@**."; + +/* No comment provided by engineer. */ +"Conditions will be accepted on: %@." = "Die Nutzungsbedingungen werden akzeptiert am: %@."; + +/* No comment provided by engineer. */ +"Conditions will be automatically accepted for enabled operators on: %@." = "Die Nutzungsbedingungen der aktivierten Betreiber werden automatisch akzeptiert am: %@."; + +/* No comment provided by engineer. */ +"Configure ICE servers" = "ICE-Server konfigurieren"; /* No comment provided by engineer. */ "Confirm" = "Bestätigen"; @@ -1082,7 +1209,7 @@ /* No comment provided by engineer. */ "Connecting to desktop" = "Mit dem Desktop verbinden"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "Verbinde…"; /* No comment provided by engineer. */ @@ -1106,6 +1233,9 @@ /* No comment provided by engineer. */ "Connection request sent!" = "Verbindungsanfrage wurde gesendet!"; +/* No comment provided by engineer. */ +"Connection security" = "Verbindungs-Sicherheit"; + /* No comment provided by engineer. */ "Connection terminated" = "Verbindung beendet"; @@ -1167,7 +1297,7 @@ "Continue" = "Weiter"; /* No comment provided by engineer. */ -"Conversation deleted!" = "Unterhaltung gelöscht!"; +"Conversation deleted!" = "Chat-Inhalte entfernt!"; /* No comment provided by engineer. */ "Copy" = "Kopieren"; @@ -1178,6 +1308,9 @@ /* No comment provided by engineer. */ "Core version: v%@" = "Core Version: v%@"; +/* No comment provided by engineer. */ +"Corner" = "Abrundung Ecken"; + /* No comment provided by engineer. */ "Correct name to %@?" = "Richtiger Name für %@?"; @@ -1185,10 +1318,10 @@ "Create" = "Erstellen"; /* No comment provided by engineer. */ -"Create a group using a random profile." = "Erstellen Sie eine Gruppe mit einem zufälligen Profil."; +"Create 1-time link" = "Einmal-Link erstellen"; /* No comment provided by engineer. */ -"Create an address to let people connect with you." = "Erstellen Sie eine Adresse, damit sich Personen mit Ihnen verbinden können."; +"Create a group using a random profile." = "Erstellen Sie eine Gruppe mit einem zufälligen Profil."; /* server test step */ "Create file" = "Datei erstellen"; @@ -1229,9 +1362,6 @@ /* copied message info */ "Created at: %@" = "Erstellt um: %@"; -/* No comment provided by engineer. */ -"Created on %@" = "Erstellt am %@"; - /* No comment provided by engineer. */ "Creating archive link" = "Archiv-Link erzeugen"; @@ -1241,6 +1371,9 @@ /* No comment provided by engineer. */ "creator" = "Ersteller"; +/* No comment provided by engineer. */ +"Current conditions text couldn't be loaded, you can review conditions via this link:" = "Der Text der aktuellen Nutzungsbedingungen konnte nicht geladen werden. Sie können die Nutzungsbedingungen unter diesem Link einsehen:"; + /* No comment provided by engineer. */ "Current Passcode" = "Aktueller Zugangscode"; @@ -1259,6 +1392,9 @@ /* No comment provided by engineer. */ "Custom time" = "Zeit anpassen"; +/* No comment provided by engineer. */ +"Customizable message shape." = "Anpassbares Format des Nachrichtenfelds"; + /* No comment provided by engineer. */ "Customize theme" = "Design anpassen"; @@ -1349,7 +1485,8 @@ /* No comment provided by engineer. */ "default (yes)" = "Voreinstellung (Ja)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Löschen"; @@ -1375,10 +1512,7 @@ "Delete and notify contact" = "Kontakt löschen und benachrichtigen"; /* No comment provided by engineer. */ -"Delete archive" = "Archiv löschen"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "Chat Archiv löschen?"; +"Delete chat" = "Chat löschen"; /* No comment provided by engineer. */ "Delete chat profile" = "Chat-Profil löschen"; @@ -1386,6 +1520,9 @@ /* No comment provided by engineer. */ "Delete chat profile?" = "Chat-Profil löschen?"; +/* No comment provided by engineer. */ +"Delete chat?" = "Chat löschen?"; + /* No comment provided by engineer. */ "Delete connection" = "Verbindung löschen"; @@ -1449,6 +1586,9 @@ /* No comment provided by engineer. */ "Delete old database?" = "Alte Datenbank löschen?"; +/* No comment provided by engineer. */ +"Delete or moderate up to 200 messages." = "Bis zu 200 Nachrichten löschen oder moderieren"; + /* No comment provided by engineer. */ "Delete pending connection?" = "Ausstehende Verbindung löschen?"; @@ -1488,6 +1628,9 @@ /* No comment provided by engineer. */ "Deletion errors" = "Fehler beim Löschen"; +/* No comment provided by engineer. */ +"Delivered even when Apple drops them." = "Auslieferung, selbst wenn Apple sie löscht."; + /* No comment provided by engineer. */ "Delivery" = "Zustellung"; @@ -1555,7 +1698,10 @@ "Direct messages" = "Direkte Nachrichten"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "In dieser Gruppe sind Direktnachrichten zwischen Mitgliedern nicht erlaubt."; +"Direct messages between members are prohibited in this chat." = "In diesem Chat sind Direktnachrichten zwischen Mitgliedern nicht erlaubt."; + +/* No comment provided by engineer. */ +"Direct messages between members are prohibited." = "In dieser Gruppe sind Direktnachrichten zwischen Mitgliedern nicht erlaubt."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Deaktivieren (vorgenommene Einstellungen bleiben erhalten)"; @@ -1582,7 +1728,7 @@ "Disappearing messages are prohibited in this chat." = "In diesem Chat sind verschwindende Nachrichten nicht erlaubt."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "In dieser Gruppe sind verschwindende Nachrichten nicht erlaubt."; +"Disappearing messages are prohibited." = "In dieser Gruppe sind verschwindende Nachrichten nicht erlaubt."; /* No comment provided by engineer. */ "Disappears at" = "Verschwindet um"; @@ -1611,6 +1757,9 @@ /* No comment provided by engineer. */ "Do NOT send messages directly, even if your or destination server does not support private routing." = "Nachrichten werden nicht direkt versendet, selbst wenn Ihr oder der Zielserver kein privates Routing unterstützt."; +/* No comment provided by engineer. */ +"Do not use credentials with proxy." = "Verwenden Sie keine Anmeldeinformationen mit einem Proxy."; + /* No comment provided by engineer. */ "Do NOT use private routing." = "Sie nutzen KEIN privates Routing."; @@ -1629,7 +1778,8 @@ /* No comment provided by engineer. */ "Downgrade and open chat" = "Datenbank herabstufen und den Chat öffnen"; -/* chat item action */ +/* alert button + chat item action */ "Download" = "Herunterladen"; /* No comment provided by engineer. */ @@ -1641,6 +1791,9 @@ /* server test step */ "Download file" = "Datei herunterladen"; +/* alert action */ +"Download files" = "Dateien herunterladen"; + /* No comment provided by engineer. */ "Downloaded" = "Heruntergeladen"; @@ -1668,6 +1821,9 @@ /* No comment provided by engineer. */ "e2e encrypted" = "E2E-verschlüsselt"; +/* No comment provided by engineer. */ +"E2E encrypted notifications." = "E2E-verschlüsselte Benachrichtigungen."; + /* chat item action */ "Edit" = "Bearbeiten"; @@ -1686,6 +1842,9 @@ /* No comment provided by engineer. */ "Enable camera access" = "Kamera-Zugriff aktivieren"; +/* No comment provided by engineer. */ +"Enable Flux" = "Flux aktivieren"; + /* No comment provided by engineer. */ "Enable for all" = "Für Alle aktivieren"; @@ -1845,24 +2004,33 @@ /* No comment provided by engineer. */ "Error aborting address change" = "Fehler beim Beenden des Adresswechsels"; +/* alert title */ +"Error accepting conditions" = "Fehler beim Akzeptieren der Nutzungsbedingungen"; + /* No comment provided by engineer. */ "Error accepting contact request" = "Fehler beim Annehmen der Kontaktanfrage"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Fehler beim Zugriff auf die Datenbankdatei"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Fehler beim Hinzufügen von Mitgliedern"; +/* alert title */ +"Error adding server" = "Fehler beim Hinzufügen des Servers"; + /* No comment provided by engineer. */ "Error changing address" = "Fehler beim Wechseln der Empfängeradresse"; +/* No comment provided by engineer. */ +"Error changing connection profile" = "Fehler beim Wechseln des Verbindungs-Profils"; + /* No comment provided by engineer. */ "Error changing role" = "Fehler beim Ändern der Rolle"; /* No comment provided by engineer. */ "Error changing setting" = "Fehler beim Ändern der Einstellung"; +/* No comment provided by engineer. */ +"Error changing to incognito!" = "Fehler beim Wechseln zum Inkognito-Profil!"; + /* No comment provided by engineer. */ "Error connecting to forwarding server %@. Please try later." = "Fehler beim Verbinden mit dem Weiterleitungsserver %@. Bitte versuchen Sie es später erneut."; @@ -1932,13 +2100,16 @@ /* No comment provided by engineer. */ "Error joining group" = "Fehler beim Beitritt zur Gruppe"; +/* alert title */ +"Error loading servers" = "Fehler beim Laden der Server"; + /* No comment provided by engineer. */ -"Error loading %@ servers" = "Fehler beim Laden von %@ Servern"; +"Error migrating settings" = "Fehler beim Migrieren der Einstellungen"; /* No comment provided by engineer. */ "Error opening chat" = "Fehler beim Öffnen des Chats"; -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Fehler beim Empfangen der Datei"; /* No comment provided by engineer. */ @@ -1953,9 +2124,6 @@ /* No comment provided by engineer. */ "Error resetting statistics" = "Fehler beim Zurücksetzen der Statistiken"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Fehler beim Speichern der %@-Server"; - /* No comment provided by engineer. */ "Error saving group profile" = "Fehler beim Speichern des Gruppenprofils"; @@ -1968,6 +2136,9 @@ /* No comment provided by engineer. */ "Error saving passphrase to keychain" = "Fehler beim Speichern des Passworts in den Schlüsselbund"; +/* alert title */ +"Error saving servers" = "Fehler beim Speichern der Server"; + /* when migrating */ "Error saving settings" = "Fehler beim Abspeichern der Einstellungen"; @@ -1996,6 +2167,9 @@ "Error stopping chat" = "Fehler beim Beenden des Chats"; /* No comment provided by engineer. */ +"Error switching profile" = "Fehler beim Wechseln des Profils"; + +/* alertTitle */ "Error switching profile!" = "Fehler beim Umschalten des Profils!"; /* No comment provided by engineer. */ @@ -2007,6 +2181,9 @@ /* No comment provided by engineer. */ "Error updating message" = "Fehler beim Aktualisieren der Nachricht"; +/* alert title */ +"Error updating server" = "Fehler beim Aktualisieren des Servers"; + /* No comment provided by engineer. */ "Error updating settings" = "Fehler beim Aktualisieren der Einstellungen"; @@ -2022,8 +2199,7 @@ /* No comment provided by engineer. */ "Error: " = "Fehler: "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Fehler: %@"; /* No comment provided by engineer. */ @@ -2035,6 +2211,9 @@ /* No comment provided by engineer. */ "Errors" = "Fehler"; +/* servers error */ +"Errors in servers configuration." = "Fehler in der Server-Konfiguration."; + /* No comment provided by engineer. */ "Even when disabled in the conversation." = "Auch wenn sie im Chat deaktiviert sind."; @@ -2048,7 +2227,7 @@ "Expand" = "Erweitern"; /* No comment provided by engineer. */ -"expired" = "abgelaufen"; +"expired" = "Abgelaufen"; /* No comment provided by engineer. */ "Export database" = "Datenbank exportieren"; @@ -2083,6 +2262,9 @@ /* No comment provided by engineer. */ "File error" = "Datei-Fehler"; +/* alert message */ +"File errors:\n%@" = "Datei-Fehler:\n%@"; + /* file error text */ "File not found - most likely file was deleted or cancelled." = "Datei nicht gefunden - höchstwahrscheinlich wurde die Datei gelöscht oder der Transfer abgebrochen."; @@ -2117,7 +2299,7 @@ "Files and media" = "Dateien und Medien"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "In dieser Gruppe sind Dateien und Medien nicht erlaubt."; +"Files and media are prohibited." = "In dieser Gruppe sind Dateien und Medien nicht erlaubt."; /* No comment provided by engineer. */ "Files and media not allowed" = "Dateien und Medien sind nicht erlaubt"; @@ -2158,15 +2340,42 @@ /* No comment provided by engineer. */ "Fix not supported by group member" = "Reparatur wird vom Gruppenmitglied nicht unterstützt"; +/* No comment provided by engineer. */ +"for better metadata privacy." = "für einen besseren Metadatenschutz."; + +/* servers error */ +"For chat profile %@:" = "Für das Chat-Profil %@:"; + /* No comment provided by engineer. */ "For console" = "Für Konsole"; +/* No comment provided by engineer. */ +"For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server." = "Wenn Ihr Kontakt beispielsweise Nachrichten über einen SimpleX-Chatserver empfängt, wird Ihre App diese über einen der Server von Flux versenden."; + +/* No comment provided by engineer. */ +"For private routing" = "Für privates Routing"; + +/* No comment provided by engineer. */ +"For social media" = "Für soziale Medien"; + /* chat item action */ "Forward" = "Weiterleiten"; +/* alert title */ +"Forward %d message(s)?" = "%d Nachricht(en) weiterleiten?"; + /* No comment provided by engineer. */ "Forward and save messages" = "Nachrichten weiterleiten und speichern"; +/* alert action */ +"Forward messages" = "Nachrichten weiterleiten"; + +/* alert message */ +"Forward messages without files?" = "Nachrichten ohne Dateien weiterleiten?"; + +/* No comment provided by engineer. */ +"Forward up to 20 messages at once." = "Bis zu 20 Nachrichten auf einmal weiterleiten"; + /* No comment provided by engineer. */ "forwarded" = "weitergeleitet"; @@ -2176,6 +2385,9 @@ /* No comment provided by engineer. */ "Forwarded from" = "Weitergeleitet aus"; +/* No comment provided by engineer. */ +"Forwarding %lld messages" = "%lld Nachricht(en) wird/werden weitergeleitet"; + /* No comment provided by engineer. */ "Forwarding server %@ failed to connect to destination server %@. Please try later." = "Weiterleitungsserver %@ konnte sich nicht mit dem Zielserver %@ verbinden. Bitte versuchen Sie es später erneut."; @@ -2203,9 +2415,6 @@ /* No comment provided by engineer. */ "Full name (optional)" = "Vollständiger Name (optional)"; -/* No comment provided by engineer. */ -"Full name:" = "Vollständiger Name:"; - /* No comment provided by engineer. */ "Fully decentralized – visible only to members." = "Vollständig dezentralisiert – nur für Mitglieder sichtbar."; @@ -2260,27 +2469,6 @@ /* No comment provided by engineer. */ "Group links" = "Gruppen-Links"; -/* No comment provided by engineer. */ -"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. (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."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Gruppenmitglieder können verschwindende Nachrichten senden."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Gruppenmitglieder können Dateien und Medien senden."; - -/* No comment provided by engineer. */ -"Group members can send SimpleX links." = "Gruppenmitglieder können SimpleX-Links senden."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Gruppenmitglieder können Sprachnachrichten versenden."; - /* notification */ "Group message:" = "Grppennachricht:"; @@ -2306,7 +2494,7 @@ "Group will be deleted for all members - this cannot be undone!" = "Die Gruppe wird für alle Mitglieder gelöscht. Dies kann nicht rückgängig gemacht werden!"; /* No comment provided by engineer. */ -"Group will be deleted for you - this cannot be undone!" = "Die Gruppe wird für Sie gelöscht. Dies kann nicht rückgängig gemacht werden!"; +"Group will be deleted for you - this cannot be undone!" = "Die Gruppe wird nur bei Ihnen gelöscht. Dies kann nicht rückgängig gemacht werden!"; /* No comment provided by engineer. */ "Help" = "Hilfe"; @@ -2342,7 +2530,10 @@ "hours" = "Stunden"; /* No comment provided by engineer. */ -"How it works" = "Wie es funktioniert"; +"How it affects privacy" = "Wie es die Privatsphäre beeinflusst"; + +/* No comment provided by engineer. */ +"How it helps privacy" = "Wie es die Privatsphäre schützt"; /* No comment provided by engineer. */ "How SimpleX works" = "Wie SimpleX funktioniert"; @@ -2387,7 +2578,7 @@ "Immediately" = "Sofort"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Immun gegen Spam und Missbrauch"; +"Immune to spam" = "Immun gegen Spam und Missbrauch"; /* No comment provided by engineer. */ "Import" = "Importieren"; @@ -2407,6 +2598,9 @@ /* No comment provided by engineer. */ "Importing archive" = "Archiv wird importiert"; +/* No comment provided by engineer. */ +"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Verbesserte Nachrichten-Auslieferung und verringerter Datenverbrauch.\nWeitere Verbesserungen sind bald verfügbar!"; + /* No comment provided by engineer. */ "Improved message delivery" = "Verbesserte Zustellung von Nachrichten"; @@ -2483,10 +2677,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Installieren Sie [SimpleX Chat als Terminalanwendung](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "Sofortige Push-Benachrichtigungen werden verborgen!\n"; +"Instant" = "Sofort"; /* No comment provided by engineer. */ -"Instantly" = "Sofort"; +"Instant push notifications will be hidden!\n" = "Sofortige Push-Benachrichtigungen werden verborgen!\n"; /* No comment provided by engineer. */ "Interface" = "Schnittstelle"; @@ -2524,7 +2718,7 @@ /* No comment provided by engineer. */ "Invalid response" = "Ungültige Reaktion"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "Ungültige Serveradresse!"; /* item status text */ @@ -2545,6 +2739,9 @@ /* No comment provided by engineer. */ "Invite members" = "Mitglieder einladen"; +/* No comment provided by engineer. */ +"Invite to chat" = "Zum Chat einladen"; + /* No comment provided by engineer. */ "Invite to group" = "In Gruppe einladen"; @@ -2566,6 +2763,9 @@ /* No comment provided by engineer. */ "iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "Für die sichere Speicherung des Passworts nach dem Neustart der App und dem Wechsel des Passworts wird der iOS Schlüsselbund verwendet - dies erlaubt den Empfang von Push-Benachrichtigungen."; +/* No comment provided by engineer. */ +"IP address" = "IP-Adresse"; + /* No comment provided by engineer. */ "Irreversible message deletion" = "Unwiederbringliches löschen einer Nachricht"; @@ -2573,7 +2773,7 @@ "Irreversible message deletion is prohibited in this chat." = "In diesem Chat ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "In dieser Gruppe ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt."; +"Irreversible message deletion is prohibited." = "In dieser Gruppe ist das unwiederbringliche Löschen von Nachrichten nicht erlaubt."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Er ermöglicht mehrere anonyme Verbindungen in einem einzigen Chat-Profil ohne Daten zwischen diesen zu teilen."; @@ -2626,16 +2826,16 @@ /* No comment provided by engineer. */ "Joining group" = "Der Gruppe beitreten"; -/* No comment provided by engineer. */ +/* alert action */ "Keep" = "Behalten"; /* No comment provided by engineer. */ -"Keep conversation" = "Unterhaltung behalten"; +"Keep conversation" = "Chat-Inhalte beibehalten"; /* 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. */ +/* alert title */ "Keep unused invitation?" = "Nicht genutzte Einladung behalten?"; /* No comment provided by engineer. */ @@ -2656,6 +2856,12 @@ /* swipe action */ "Leave" = "Verlassen"; +/* No comment provided by engineer. */ +"Leave chat" = "Chat verlassen"; + +/* No comment provided by engineer. */ +"Leave chat?" = "Chat verlassen?"; + /* No comment provided by engineer. */ "Leave group" = "Gruppe verlassen"; @@ -2692,9 +2898,6 @@ /* 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"; @@ -2707,24 +2910,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Sperr-Modus"; -/* No comment provided by engineer. */ -"Make a private connection" = "Stellen Sie eine private Verbindung her"; - /* No comment provided by engineer. */ "Make one message disappear" = "Eine verschwindende Nachricht verfassen"; /* No comment provided by engineer. */ "Make profile private!" = "Privates Profil erzeugen!"; -/* No comment provided by engineer. */ -"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 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?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Für Alle als gelöscht markieren"; @@ -2764,15 +2958,42 @@ /* item status text */ "Member inactive" = "Mitglied inaktiv"; +/* No comment provided by engineer. */ +"Member role will be changed to \"%@\". All chat members will be notified." = "Die Rolle des Mitglieds wird auf \"%@\" geändert. Alle Chat-Mitglieder werden darüber informiert."; + /* No comment provided by engineer. */ "Member role will be changed to \"%@\". All group members will be notified." = "Die Mitgliederrolle wird auf \"%@\" geändert. Alle Mitglieder der Gruppe werden benachrichtigt."; /* No comment provided by engineer. */ "Member role will be changed to \"%@\". The member will receive a new invitation." = "Die Mitgliederrolle wird auf \"%@\" geändert. Das Mitglied wird eine neue Einladung erhalten."; +/* No comment provided by engineer. */ +"Member will be removed from chat - this cannot be undone!" = "Das Mitglied wird aus dem Chat entfernt. Dies kann nicht rückgängig gemacht werden!"; + /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "Das Mitglied wird aus der Gruppe entfernt. Dies kann nicht rückgängig gemacht werden!"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Gruppenmitglieder können eine Reaktion auf Nachrichten geben."; + +/* No comment provided by engineer. */ +"Members can irreversibly delete sent messages. (24 hours)" = "Gruppenmitglieder können gesendete Nachrichten unwiederbringlich löschen. (24 Stunden)"; + +/* No comment provided by engineer. */ +"Members can send direct messages." = "Gruppenmitglieder können Direktnachrichten versenden."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Gruppenmitglieder können verschwindende Nachrichten senden."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Gruppenmitglieder können Dateien und Medien senden."; + +/* No comment provided by engineer. */ +"Members can send SimpleX links." = "Gruppenmitglieder können SimpleX-Links senden."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Gruppenmitglieder können Sprachnachrichten versenden."; + /* No comment provided by engineer. */ "Menus" = "Menüs"; @@ -2807,7 +3028,7 @@ "Message reactions are prohibited in this chat." = "In diesem Chat sind Reaktionen auf Nachrichten nicht erlaubt."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "In dieser Gruppe sind Reaktionen auf Nachrichten nicht erlaubt."; +"Message reactions are prohibited." = "In dieser Gruppe sind Reaktionen auf Nachrichten nicht erlaubt."; /* notification */ "message received" = "Nachricht empfangen"; @@ -2818,6 +3039,9 @@ /* No comment provided by engineer. */ "Message servers" = "Nachrichten-Server"; +/* No comment provided by engineer. */ +"Message shape" = "Nachrichten-Form"; + /* No comment provided by engineer. */ "Message source remains private." = "Die Nachrichtenquelle bleibt privat."; @@ -2848,6 +3072,9 @@ /* No comment provided by engineer. */ "Messages sent" = "Gesendete Nachrichten"; +/* alert message */ +"Messages were deleted after you selected them." = "Die Nachrichten wurden gelöscht, nachdem Sie sie ausgewählt hatten."; + /* No comment provided by engineer. */ "Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Nachrichten, Dateien und Anrufe sind durch **Ende-zu-Ende-Verschlüsselung** mit Perfect Forward Secrecy, Ablehnung und Einbruchs-Wiederherstellung geschützt."; @@ -2888,7 +3115,7 @@ "Migration is completed" = "Die Migration wurde abgeschlossen"; /* No comment provided by engineer. */ -"Migrations: %@" = "Migrationen: %@"; +"Migrations:" = "Migrationen:"; /* time unit */ "minutes" = "Minuten"; @@ -2920,6 +3147,9 @@ /* No comment provided by engineer. */ "More reliable network connection." = "Zuverlässigere Netzwerkverbindung."; +/* No comment provided by engineer. */ +"More reliable notifications" = "Zuverlässigere Benachrichtigungen"; + /* item status description */ "Most likely this connection is deleted." = "Wahrscheinlich ist diese Verbindung gelöscht worden."; @@ -2944,12 +3174,18 @@ /* No comment provided by engineer. */ "Network connection" = "Netzwerkverbindung"; +/* No comment provided by engineer. */ +"Network decentralization" = "Dezentralisiertes Netzwerk"; + /* snd error text */ "Network issues - message expired after many attempts to send it." = "Netzwerk-Fehler - die Nachricht ist nach vielen Sende-Versuchen abgelaufen."; /* No comment provided by engineer. */ "Network management" = "Netzwerk-Verwaltung"; +/* No comment provided by engineer. */ +"Network operator" = "Netzwerk-Betreiber"; + /* No comment provided by engineer. */ "Network settings" = "Netzwerkeinstellungen"; @@ -2971,15 +3207,15 @@ /* notification */ "New contact:" = "Neuer Kontakt:"; -/* No comment provided by engineer. */ -"New database archive" = "Neues Datenbankarchiv"; - /* No comment provided by engineer. */ "New desktop app!" = "Neue Desktop-App!"; /* No comment provided by engineer. */ "New display name" = "Neuer Anzeigename"; +/* notification */ +"New events" = "Neue Ereignisse"; + /* No comment provided by engineer. */ "New in %@" = "Neu in %@"; @@ -3001,6 +3237,15 @@ /* No comment provided by engineer. */ "New passphrase…" = "Neues Passwort…"; +/* No comment provided by engineer. */ +"New server" = "Neuer Server"; + +/* No comment provided by engineer. */ +"New SOCKS credentials will be used every time you start the app." = "Jedes Mal wenn Sie die App starten, werden neue SOCKS-Anmeldeinformationen genutzt"; + +/* No comment provided by engineer. */ +"New SOCKS credentials will be used for each server." = "Für jeden Server werden neue SOCKS-Anmeldeinformationen genutzt"; + /* pref value */ "no" = "Nein"; @@ -3040,30 +3285,66 @@ /* No comment provided by engineer. */ "No info, try to reload" = "Keine Information - es wird versucht neu zu laden"; +/* servers error */ +"No media & file servers." = "Keine Medien- und Dateiserver."; + +/* servers error */ +"No message servers." = "Keine Nachrichten-Server."; + /* No comment provided by engineer. */ "No network connection" = "Keine Netzwerkverbindung"; +/* No comment provided by engineer. */ +"No permission to record speech" = "Keine Genehmigung für Sprach-Aufnahmen"; + +/* No comment provided by engineer. */ +"No permission to record video" = "Keine Genehmigung für Video-Aufnahmen"; + /* No comment provided by engineer. */ "No permission to record voice message" = "Keine Berechtigung für das Aufnehmen von Sprachnachrichten"; +/* No comment provided by engineer. */ +"No push server" = "Lokal"; + /* No comment provided by engineer. */ "No received or sent files" = "Keine empfangenen oder gesendeten Dateien"; +/* servers error */ +"No servers for private message routing." = "Keine Server für privates Nachrichten-Routing."; + +/* servers error */ +"No servers to receive files." = "Keine Server für den Empfang von Dateien."; + +/* servers error */ +"No servers to receive messages." = "Keine Server für den Empfang von Nachrichten."; + +/* servers error */ +"No servers to send files." = "Keine Server für das Versenden von Dateien."; + /* copied message info in history */ "no text" = "Kein Text"; +/* No comment provided by engineer. */ +"No user identifiers." = "Keine Benutzerkennungen."; + /* No comment provided by engineer. */ "Not compatible!" = "Nicht kompatibel!"; /* No comment provided by engineer. */ "Nothing selected" = "Nichts ausgewählt"; +/* alert title */ +"Nothing to forward!" = "Es gibt nichts zum Weiterleiten!"; + /* No comment provided by engineer. */ "Notifications" = "Benachrichtigungen"; /* No comment provided by engineer. */ "Notifications are disabled!" = "Benachrichtigungen sind deaktiviert!"; +/* No comment provided by engineer. */ +"Notifications privacy" = "Datenschutz für Benachrichtigungen"; + /* No comment provided by engineer. */ "Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" = "Administratoren können nun\n- Nachrichten von Gruppenmitgliedern löschen\n- Gruppenmitglieder deaktivieren (\"Beobachter\"-Rolle)"; @@ -3084,7 +3365,7 @@ /* feature offered item */ "offered %@: %@" = "angeboten %1$@: %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ok"; /* No comment provided by engineer. */ @@ -3093,9 +3374,6 @@ /* No comment provided by engineer. */ "Old database" = "Alte Datenbank"; -/* No comment provided by engineer. */ -"Old database archive" = "Altes Datenbankarchiv"; - /* group pref value */ "on" = "Ein"; @@ -3112,10 +3390,13 @@ "Onion hosts will not be used." = "Onion-Hosts werden nicht verwendet."; /* No comment provided by engineer. */ -"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Nur die Endgeräte speichern die Benutzerprofile, Kontakte, Gruppen und Nachrichten, welche über eine **2-Schichten Ende-zu-Ende-Verschlüsselung** gesendet werden."; +"Only chat owners can change preferences." = "Nur Chat-Eigentümer können die Präferenzen ändern."; /* No comment provided by engineer. */ -"Only delete conversation" = "Nur die Unterhaltung löschen"; +"Only client devices store user profiles, contacts, groups, and messages." = "Nur die Endgeräte speichern die Benutzerprofile, Kontakte, Gruppen und Nachrichten, welche über eine **2-Schichten Ende-zu-Ende-Verschlüsselung** gesendet werden."; + +/* No comment provided by engineer. */ +"Only delete conversation" = "Nur die Chat-Inhalte löschen"; /* No comment provided by engineer. */ "Only group owners can change group preferences." = "Gruppen-Präferenzen können nur von Gruppen-Eigentümern geändert werden."; @@ -3159,33 +3440,39 @@ /* No comment provided by engineer. */ "Open" = "Öffnen"; +/* No comment provided by engineer. */ +"Open changes" = "Änderungen öffnen"; + /* No comment provided by engineer. */ "Open chat" = "Chat öffnen"; /* authentication reason */ "Open chat console" = "Chat-Konsole öffnen"; +/* No comment provided by engineer. */ +"Open conditions" = "Nutzungsbedingungen öffnen"; + /* No comment provided by engineer. */ "Open group" = "Gruppe öffnen"; /* authentication reason */ "Open migration to another device" = "Migration auf ein anderes Gerät öffnen"; -/* No comment provided by engineer. */ -"Open server settings" = "Server-Einstellungen öffnen"; - /* No comment provided by engineer. */ "Open Settings" = "Geräte-Einstellungen öffnen"; -/* authentication reason */ -"Open user profiles" = "Benutzerprofile öffnen"; - -/* No comment provided by engineer. */ -"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 app…" = "App wird geöffnet…"; +/* No comment provided by engineer. */ +"Operator" = "Betreiber"; + +/* alert title */ +"Operator server" = "Betreiber-Server"; + +/* No comment provided by engineer. */ +"Or import archive file" = "Oder importieren Sie eine Archiv-Datei"; + /* No comment provided by engineer. */ "Or paste archive link" = "Oder fügen Sie den Archiv-Link ein"; @@ -3199,17 +3486,20 @@ "Or show this code" = "Oder diesen QR-Code anzeigen"; /* No comment provided by engineer. */ -"other" = "andere"; +"Or to share privately" = "Oder zum privaten Teilen"; + +/* No comment provided by engineer. */ +"other" = "Andere"; /* No comment provided by engineer. */ "Other" = "Andere"; -/* No comment provided by engineer. */ -"Other %@ servers" = "Andere %@ Server"; - /* No comment provided by engineer. */ "other errors" = "Andere Fehler"; +/* alert message */ +"Other file errors:\n%@" = "Andere(r) Datei-Fehler:\n%@"; + /* member role */ "owner" = "Eigentümer"; @@ -3231,6 +3521,9 @@ /* No comment provided by engineer. */ "Passcode set!" = "Zugangscode eingestellt!"; +/* No comment provided by engineer. */ +"Password" = "Passwort"; + /* No comment provided by engineer. */ "Password to show" = "Passwort anzeigen"; @@ -3256,10 +3549,7 @@ "Pending" = "Ausstehend"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "Verbindungen mit Kontakten sind nur über Links möglich, die Sie oder Ihre Kontakte untereinander teilen."; - -/* No comment provided by engineer. */ -"Periodically" = "Periodisch"; +"Periodic" = "Periodisch"; /* message decrypt error item */ "Permanent decryption error" = "Entschlüsselungsfehler"; @@ -3327,6 +3617,9 @@ /* No comment provided by engineer. */ "Polish interface" = "Polnische Bedienoberfläche"; +/* No comment provided by engineer. */ +"Port" = "Port"; + /* server test error */ "Possibly, certificate fingerprint in server address is incorrect" = "Der Fingerabdruck des Zertifikats in der Serveradresse ist wahrscheinlich ungültig"; @@ -3334,10 +3627,10 @@ "Preserve the last message draft, with attachments." = "Den letzten Nachrichtenentwurf, auch mit seinen Anhängen, aufbewahren."; /* No comment provided by engineer. */ -"Preset server" = "Voreingestellter Server"; +"Preset server address" = "Voreingestellte Serveradresse"; /* No comment provided by engineer. */ -"Preset server address" = "Voreingestellte Serveradresse"; +"Preset servers" = "Voreingestellte Server"; /* No comment provided by engineer. */ "Preview" = "Vorschau"; @@ -3348,6 +3641,9 @@ /* No comment provided by engineer. */ "Privacy & security" = "Datenschutz & Sicherheit"; +/* No comment provided by engineer. */ +"Privacy for your customers." = "Schutz der Privatsphäre Ihrer Kunden."; + /* No comment provided by engineer. */ "Privacy redefined" = "Datenschutz neu definiert"; @@ -3378,19 +3674,13 @@ /* No comment provided by engineer. */ "Profile images" = "Profil-Bilder"; -/* No comment provided by engineer. */ -"Profile name" = "Profilname"; - -/* No comment provided by engineer. */ -"Profile name:" = "Profilname:"; - /* No comment provided by engineer. */ "Profile password" = "Passwort für Profil"; /* No comment provided by engineer. */ "Profile theme" = "Profil-Design"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "Profil-Aktualisierung wird an Ihre Kontakte gesendet."; /* No comment provided by engineer. */ @@ -3444,6 +3734,9 @@ /* No comment provided by engineer. */ "Proxied servers" = "Proxy-Server"; +/* No comment provided by engineer. */ +"Proxy requires password" = "Der Proxy benötigt ein Passwort"; + /* No comment provided by engineer. */ "Push notifications" = "Push-Benachrichtigungen"; @@ -3460,7 +3753,7 @@ "Rate the app" = "Bewerten Sie die App"; /* No comment provided by engineer. */ -"Reachable chat toolbar" = "Erreichbare Chat-Symbolleiste"; +"Reachable chat toolbar" = "Chat-Symbolleiste unten"; /* chat item menu */ "React…" = "Reagiere…"; @@ -3472,10 +3765,10 @@ "Read more" = "Mehr erfahren"; /* 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."; +"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/chat-profiles.html#incognito-mode)." = "Lesen Sie mehr dazu im [Benutzerhandbuch](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Mehr dazu in der [Benutzeranleitung](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses) lesen."; /* 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."; @@ -3483,9 +3776,6 @@ /* No comment provided by engineer. */ "Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Erfahren Sie in unserem [GitHub-Repository](https://github.com/simplex-chat/simplex-chat#readme) mehr dazu."; -/* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Erfahren Sie in unserem GitHub-Repository mehr dazu."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Bestätigungen sind deaktiviert"; @@ -3589,6 +3879,9 @@ /* No comment provided by engineer. */ "Remove" = "Entfernen"; +/* No comment provided by engineer. */ +"Remove archive?" = "Archiv entfernen?"; + /* No comment provided by engineer. */ "Remove image" = "Bild entfernen"; @@ -3643,6 +3936,9 @@ /* chat item action */ "Reply" = "Antwort"; +/* chat list item title */ +"requested to connect" = "Zur Verbindung aufgefordert"; + /* No comment provided by engineer. */ "Required" = "Erforderlich"; @@ -3694,6 +3990,12 @@ /* chat item action */ "Reveal" = "Aufdecken"; +/* No comment provided by engineer. */ +"Review conditions" = "Nutzungsbedingungen einsehen"; + +/* No comment provided by engineer. */ +"Review later" = "Später einsehen"; + /* No comment provided by engineer. */ "Revoke" = "Widerrufen"; @@ -3715,13 +4017,14 @@ /* No comment provided by engineer. */ "Safer groups" = "Sicherere Gruppen"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Speichern"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Speichern (und Kontakte benachrichtigen)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Speichern und Kontakt benachrichtigen"; /* No comment provided by engineer. */ @@ -3733,12 +4036,6 @@ /* No comment provided by engineer. */ "Save and update group profile" = "Gruppen-Profil sichern und aktualisieren"; -/* No comment provided by engineer. */ -"Save archive" = "Archiv speichern"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Einstellungen von \"Automatisch akzeptieren\" speichern"; - /* No comment provided by engineer. */ "Save group profile" = "Gruppenprofil speichern"; @@ -3748,7 +4045,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Passwort im Schlüsselbund speichern"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "Präferenzen speichern?"; /* No comment provided by engineer. */ @@ -3757,15 +4054,15 @@ /* No comment provided by engineer. */ "Save servers" = "Alle Server speichern"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "Alle Server speichern?"; -/* No comment provided by engineer. */ -"Save settings?" = "Einstellungen speichern?"; - /* No comment provided by engineer. */ "Save welcome message?" = "Begrüßungsmeldung speichern?"; +/* alert title */ +"Save your profile?" = "Ihr Profil speichern?"; + /* No comment provided by engineer. */ "saved" = "abgespeichert"; @@ -3784,6 +4081,9 @@ /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Gespeicherte WebRTC ICE-Server werden entfernt"; +/* No comment provided by engineer. */ +"Saving %lld messages" = "Es wird/werden %lld Nachricht(en) gesichert"; + /* No comment provided by engineer. */ "Scale" = "Skalieren"; @@ -3815,7 +4115,7 @@ "Search bar accepts invitation links." = "In der Suchleiste werden nun auch Einladungslinks akzeptiert."; /* No comment provided by engineer. */ -"Search or paste SimpleX link" = "Suchen oder fügen Sie den SimpleX-Link ein"; +"Search or paste SimpleX link" = "Suchen oder SimpleX-Link einfügen"; /* network option */ "sec" = "sek"; @@ -3847,6 +4147,9 @@ /* chat item action */ "Select" = "Auswählen"; +/* No comment provided by engineer. */ +"Select chat profile" = "Chat-Profil auswählen"; + /* No comment provided by engineer. */ "Selected %lld" = "%lld ausgewählt"; @@ -3904,9 +4207,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Benachrichtigungen senden"; -/* No comment provided by engineer. */ -"Send notifications:" = "Benachrichtigungen senden:"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Senden Sie Fragen und Ideen"; @@ -3919,7 +4219,7 @@ /* 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. */ +/* alert message */ "Sender cancelled file transfer." = "Der Absender hat die Dateiübertragung abgebrochen."; /* No comment provided by engineer. */ @@ -3979,6 +4279,12 @@ /* No comment provided by engineer. */ "Sent via proxy" = "Über einen Proxy gesendet"; +/* No comment provided by engineer. */ +"Server" = "Server"; + +/* alert message */ +"Server added to operator %@." = "Der Server wurde dem Betreiber %@ hinzugefügt."; + /* No comment provided by engineer. */ "Server address" = "Server-Adresse"; @@ -3988,6 +4294,15 @@ /* srv error text. */ "Server address is incompatible with network settings." = "Die Server-Adresse ist nicht mit den Netzwerkeinstellungen kompatibel."; +/* alert title */ +"Server operator changed." = "Der Server-Betreiber wurde geändert."; + +/* No comment provided by engineer. */ +"Server operators" = "Server-Betreiber"; + +/* alert title */ +"Server protocol changed." = "Das Server-Protokoll wurde geändert."; + /* queue info */ "server queue info: %@\n\nlast received msg: %@" = "Server-Warteschlangen-Information: %1$@\n\nZuletzt empfangene Nachricht: %2$@"; @@ -4060,19 +4375,29 @@ /* No comment provided by engineer. */ "Settings" = "Einstellungen"; +/* alert message */ +"Settings were changed." = "Die Einstellungen wurden geändert."; + /* No comment provided by engineer. */ "Shape profile images" = "Form der Profil-Bilder"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Teilen"; /* No comment provided by engineer. */ "Share 1-time link" = "Einmal-Link teilen"; +/* No comment provided by engineer. */ +"Share 1-time link with a friend" = "Den Einmal-Einladungslink mit einem Freund teilen"; + /* No comment provided by engineer. */ "Share address" = "Adresse teilen"; /* No comment provided by engineer. */ +"Share address publicly" = "Die Adresse öffentlich teilen"; + +/* alert title */ "Share address with contacts?" = "Die Adresse mit Kontakten teilen?"; /* No comment provided by engineer. */ @@ -4081,6 +4406,12 @@ /* No comment provided by engineer. */ "Share link" = "Link teilen"; +/* No comment provided by engineer. */ +"Share profile" = "Profil teilen"; + +/* No comment provided by engineer. */ +"Share SimpleX address on social media." = "Die SimpleX-Adresse auf sozialen Medien teilen."; + /* No comment provided by engineer. */ "Share this 1-time invite link" = "Teilen Sie diesen Einmal-Einladungslink"; @@ -4126,6 +4457,15 @@ /* No comment provided by engineer. */ "SimpleX Address" = "SimpleX-Adresse"; +/* No comment provided by engineer. */ +"SimpleX address and 1-time links are safe to share via any messenger." = "Die SimpleX-Adresse und Einmal-Links können sicher über beliebige Messenger geteilt werden."; + +/* No comment provided by engineer. */ +"SimpleX address or 1-time link?" = "SimpleX-Adresse oder Einmal-Link?"; + +/* No comment provided by engineer. */ +"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "SimpleX-Chat und Flux haben vereinbart, die von Flux betriebenen Server in die App aufzunehmen."; + /* No comment provided by engineer. */ "SimpleX Chat security was audited by Trail of Bits." = "Die Sicherheit von SimpleX Chat wurde von Trail of Bits überprüft."; @@ -4142,7 +4482,7 @@ "SimpleX links" = "SimpleX-Links"; /* No comment provided by engineer. */ -"SimpleX links are prohibited in this group." = "In dieser Gruppe sind SimpleX-Links nicht erlaubt."; +"SimpleX links are prohibited." = "In dieser Gruppe sind SimpleX-Links nicht erlaubt."; /* No comment provided by engineer. */ "SimpleX links not allowed" = "SimpleX-Links sind nicht erlaubt"; @@ -4162,6 +4502,9 @@ /* simplex link type */ "SimpleX one-time invitation" = "SimpleX-Einmal-Einladung"; +/* No comment provided by engineer. */ +"SimpleX protocols reviewed by Trail of Bits." = "Die SimpleX-Protokolle wurden von Trail of Bits überprüft."; + /* No comment provided by engineer. */ "Simplified incognito mode" = "Vereinfachter Inkognito-Modus"; @@ -4180,9 +4523,15 @@ /* No comment provided by engineer. */ "SMP server" = "SMP-Server"; +/* No comment provided by engineer. */ +"SOCKS proxy" = "SOCKS-Proxy"; + /* blur media */ "Soft" = "Weich"; +/* No comment provided by engineer. */ +"Some app settings were not migrated." = "Einige App-Einstellungen wurden nicht migriert."; + /* No comment provided by engineer. */ "Some file(s) were not exported:" = "Einzelne Datei(en) wurde(n) nicht exportiert:"; @@ -4192,6 +4541,9 @@ /* No comment provided by engineer. */ "Some non-fatal errors occurred during import:" = "Während des Imports traten ein paar nicht schwerwiegende Fehler auf:"; +/* alert message */ +"Some servers failed the test:\n%@" = "Einige Server haben den Test nicht bestanden:\n%@"; + /* notification title */ "Somebody" = "Jemand"; @@ -4225,9 +4577,6 @@ /* No comment provided by engineer. */ "Stop chat" = "Chat beenden"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Chat beenden, um Datenbankaktionen zu erlauben"; - /* 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." = "Beenden Sie den Chat, um die Chat-Datenbank zu exportieren, zu importieren oder zu löschen. Solange der Chat angehalten ist, können Sie keine Nachrichten empfangen oder senden."; @@ -4243,10 +4592,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "Das Senden der Datei beenden?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Teilen beenden"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "Das Teilen der Adresse beenden?"; /* authentication reason */ @@ -4276,18 +4625,30 @@ /* No comment provided by engineer. */ "Support SimpleX Chat" = "Unterstützung von SimpleX Chat"; +/* No comment provided by engineer. */ +"Switch audio and video during the call." = "Während des Anrufs zwischen Audio und Video wechseln"; + +/* No comment provided by engineer. */ +"Switch chat profile for 1-time invitations." = "Das Chat-Profil für Einmal-Einladungen wechseln"; + /* No comment provided by engineer. */ "System" = "System"; /* No comment provided by engineer. */ "System authentication" = "System-Authentifizierung"; +/* No comment provided by engineer. */ +"Tail" = "Sprechblasen-Format"; + /* No comment provided by engineer. */ "Take picture" = "Machen Sie ein Foto"; /* No comment provided by engineer. */ "Tap button " = "Schaltfläche antippen "; +/* No comment provided by engineer. */ +"Tap Create SimpleX address in the menu to create it later." = "Tippen Sie im Menü auf SimpleX-Adresse erstellen, um sie später zu erstellen."; + /* No comment provided by engineer. */ "Tap to activate profile." = "Zum Aktivieren des Profils tippen."; @@ -4333,7 +4694,7 @@ /* No comment provided by engineer. */ "Test servers" = "Teste alle Server"; -/* No comment provided by engineer. */ +/* alert title */ "Tests failed!" = "Tests sind fehlgeschlagen!"; /* No comment provided by engineer. */ @@ -4346,10 +4707,10 @@ "Thanks to the users – contribute via Weblate!" = "Dank der Nutzer - Tragen Sie per Weblate bei!"; /* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "Die erste Plattform ohne Benutzerkennungen – Privat per Design."; +"The app can notify you when you receive messages or contact requests - please open settings to enable." = "Wenn sie Nachrichten oder Kontaktanfragen empfangen, kann Sie die App benachrichtigen - Um dies zu aktivieren, öffnen Sie bitte die Einstellungen."; /* No comment provided by engineer. */ -"The app can notify you when you receive messages or contact requests - please open settings to enable." = "Wenn sie Nachrichten oder Kontaktanfragen empfangen, kann Sie die App benachrichtigen - Um dies zu aktivieren, öffnen Sie bitte die Einstellungen."; +"The app protects your privacy by using different operators in each conversation." = "Durch Verwendung verschiedener Netzwerk-Betreiber für jede Unterhaltung schützt die App Ihre Privatsphäre."; /* No comment provided by engineer. */ "The app will ask to confirm downloads from unknown file servers (except .onion)." = "Die App wird eine Bestätigung bei Downloads von unbekannten Datei-Servern anfordern (außer bei .onion)."; @@ -4360,6 +4721,9 @@ /* 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 reached the limit of undelivered messages, your contact may be offline." = "Diese Verbindung hat das Limit der nicht ausgelieferten Nachrichten erreicht. Ihr Kontakt ist möglicherweise offline."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "Die von Ihnen akzeptierte Verbindung wird abgebrochen!"; @@ -4372,6 +4736,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Die Verschlüsselung funktioniert und ein neues Verschlüsselungsabkommen ist nicht erforderlich. Es kann zu Verbindungsfehlern kommen!"; +/* No comment provided by engineer. */ +"The future of messaging" = "Die nächste Generation von privatem Messaging"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "Der Hash der vorherigen Nachricht unterscheidet sich."; @@ -4385,20 +4752,26 @@ "The message will be marked as moderated for all members." = "Diese Nachricht wird für alle Mitglieder als moderiert gekennzeichnet."; /* No comment provided by engineer. */ -"The messages will be deleted for all members." = "Die Nachrichten werden für alle Mitglieder gelöscht werden."; +"The messages will be deleted for all members." = "Die Nachrichten werden für alle Gruppenmitglieder gelöscht."; /* No comment provided by engineer. */ "The messages will be marked as moderated for all members." = "Die Nachrichten werden für alle Mitglieder als moderiert gekennzeichnet werden."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "Die nächste Generation von privatem Messaging"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "Die alte Datenbank wurde während der Migration nicht entfernt. Sie kann gelöscht werden."; /* No comment provided by engineer. */ "The profile is only shared with your contacts." = "Das Profil wird nur mit Ihren Kontakten geteilt."; +/* No comment provided by engineer. */ +"The same conditions will apply to operator **%@**." = "Dieselben Nutzungsbedingungen gelten auch für den Betreiber **%@**."; + +/* No comment provided by engineer. */ +"The same conditions will apply to operator(s): **%@**." = "Dieselben Nutzungsbedingungen gelten auch für den/die Betreiber: **%@**."; + +/* No comment provided by engineer. */ +"The second preset operator in the app!" = "Der zweite voreingestellte Netzwerk-Betreiber in der App!"; + /* No comment provided by engineer. */ "The second tick we missed! ✅" = "Wir haben das zweite Häkchen vermisst! ✅"; @@ -4406,14 +4779,23 @@ "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 **%@**." = "Mögliche Server für neue Verbindungen von Ihrem aktuellen Chat-Profil **%@**."; +"The servers for new connections of your current chat profile **%@**." = "Nachrichten-Server für neue Verbindungen über Ihr aktuelles Chat-Profil **%@**."; + +/* No comment provided by engineer. */ +"The servers for new files of your current chat profile **%@**." = "Medien- und Datei-Server für neue Daten über Ihr aktuelles 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. */ +"The uploaded database archive will be permanently removed from the servers." = "Das hochgeladene Datenbank-Archiv wird dauerhaft von den Servern entfernt."; + /* No comment provided by engineer. */ "Themes" = "Design"; +/* No comment provided by engineer. */ +"These conditions will also apply for: **%@**." = "Diese Nutzungsbedingungen gelten auch für: **%@**."; + /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Diese Einstellungen betreffen Ihr aktuelles Profil **%@**."; @@ -4478,7 +4860,7 @@ "To make a new connection" = "Um eine Verbindung mit einem neuen Kontakt zu erstellen"; /* 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." = "Zum Schutz Ihrer Privatsphäre verwendet SimpleX an Stelle von Benutzerkennungen, die von allen anderen Plattformen verwendet werden, Kennungen für Nachrichtenwarteschlangen, die für jeden Ihrer Kontakte individuell sind."; +"To protect against your link being replaced, you can compare contact security codes." = "Zum Schutz vor dem Austausch Ihres Links können Sie die Sicherheitscodes Ihrer Kontakte vergleichen."; /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "Bild- und Sprachdateinamen enthalten UTC, um Informationen zur Zeitzone zu schützen."; @@ -4489,15 +4871,33 @@ /* No comment provided by engineer. */ "To protect your IP address, private routing uses your SMP servers to deliver messages." = "Zum Schutz Ihrer IP-Adresse, wird für die Nachrichten-Auslieferung privates Routing über Ihre konfigurierten SMP-Server genutzt."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "Zum Schutz Ihrer Privatsphäre verwendet SimpleX an Stelle von Benutzerkennungen, die von allen anderen Plattformen verwendet werden, Kennungen für Nachrichtenwarteschlangen, die für jeden Ihrer Kontakte individuell sind."; + +/* No comment provided by engineer. */ +"To receive" = "Für den Empfang"; + +/* No comment provided by engineer. */ +"To record speech please grant permission to use Microphone." = "Bitte erteilen Sie für Sprach-Aufnahmen die Genehmigung das Mikrofon zu nutzen."; + +/* No comment provided by engineer. */ +"To record video please grant permission to use Camera." = "Bitte erteilen Sie für Video-Aufnahmen die Genehmigung die Kamera zu nutzen."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können."; /* No comment provided by engineer. */ "To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." = "Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Ihre Chat-Profile** ein, um Ihr verborgenes Profil zu sehen."; +/* No comment provided by engineer. */ +"To send" = "Für das Senden"; + /* No comment provided by engineer. */ "To support instant push notifications the chat database has to be migrated." = "Um sofortige Push-Benachrichtigungen zu unterstützen, muss die Chat-Datenbank migriert werden."; +/* No comment provided by engineer. */ +"To use the servers of **%@**, accept conditions of use." = "Um die Server von **%@** zu nutzen, müssen Sie dessen Nutzungsbedingungen akzeptieren."; + /* No comment provided by engineer. */ "To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Um die Ende-zu-Ende-Verschlüsselung mit Ihrem Kontakt zu überprüfen, müssen Sie den Sicherheitscode in Ihren Apps vergleichen oder scannen."; @@ -4555,6 +4955,9 @@ /* rcv group event chat item */ "unblocked %@" = "%@ wurde freigegeben"; +/* No comment provided by engineer. */ +"Undelivered messages" = "Nicht ausgelieferte Nachrichten"; + /* No comment provided by engineer. */ "Unexpected migration state" = "Unerwarteter Migrationsstatus"; @@ -4588,7 +4991,7 @@ /* No comment provided by engineer. */ "unknown servers" = "Unbekannte Relais"; -/* No comment provided by engineer. */ +/* alert title */ "Unknown servers!" = "Unbekannte Server!"; /* No comment provided by engineer. */ @@ -4672,12 +5075,21 @@ /* No comment provided by engineer. */ "Use .onion hosts" = "Verwende .onion-Hosts"; +/* No comment provided by engineer. */ +"Use %@" = "Verwende %@"; + /* No comment provided by engineer. */ "Use chat" = "Verwenden Sie Chat"; /* No comment provided by engineer. */ "Use current profile" = "Aktuelles Profil nutzen"; +/* No comment provided by engineer. */ +"Use for files" = "Für Dateien verwenden"; + +/* No comment provided by engineer. */ +"Use for messages" = "Für Nachrichten verwenden"; + /* No comment provided by engineer. */ "Use for new connections" = "Für neue Verbindungen nutzen"; @@ -4702,21 +5114,27 @@ /* No comment provided by engineer. */ "Use server" = "Server nutzen"; +/* No comment provided by engineer. */ +"Use servers" = "Verwende Server"; + /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "Verwenden Sie SimpleX-Chat-Server?"; +/* No comment provided by engineer. */ +"Use SOCKS proxy" = "SOCKS-Proxy nutzen"; + /* No comment provided by engineer. */ "Use the app while in the call." = "Die App kann während eines Anrufs genutzt werden."; /* No comment provided by engineer. */ -"Use the app with one hand." = "Die App mit einer Hand nutzen."; - -/* No comment provided by engineer. */ -"User profile" = "Benutzerprofil"; +"Use the app with one hand." = "Die App mit einer Hand bedienen."; /* No comment provided by engineer. */ "User selection" = "Benutzer-Auswahl"; +/* No comment provided by engineer. */ +"Username" = "Benutzername"; + /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Verwendung von SimpleX-Chat-Servern."; @@ -4783,9 +5201,15 @@ /* No comment provided by engineer. */ "Videos and files up to 1gb" = "Videos und Dateien bis zu 1GB"; +/* No comment provided by engineer. */ +"View conditions" = "Nutzungsbedingungen anschauen"; + /* No comment provided by engineer. */ "View security code" = "Schauen Sie sich den Sicherheitscode an"; +/* No comment provided by engineer. */ +"View updated conditions" = "Aktualisierte Nutzungsbedingungen anschauen"; + /* chat feature */ "Visible history" = "Sichtbarer Nachrichtenverlauf"; @@ -4799,7 +5223,7 @@ "Voice messages are prohibited in this chat." = "In diesem Chat sind Sprachnachrichten nicht erlaubt."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "In dieser Gruppe sind Sprachnachrichten nicht erlaubt."; +"Voice messages are prohibited." = "In dieser Gruppe sind Sprachnachrichten nicht erlaubt."; /* No comment provided by engineer. */ "Voice messages not allowed" = "Sprachnachrichten sind nicht erlaubt"; @@ -4868,7 +5292,7 @@ "when IP hidden" = "Wenn die IP-Adresse versteckt ist"; /* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Wenn Personen eine Verbindung anfordern, können Sie diese annehmen oder ablehnen."; +"When more than one operator is enabled, none of them has metadata to learn who communicates with whom." = "Wenn mehrere Netzwerk-Betreiber aktiviert sind, hat keiner von ihnen Metadaten, um zu erfahren, wer mit wem kommuniziert."; /* 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."; @@ -4894,7 +5318,7 @@ /* No comment provided by engineer. */ "Without Tor or VPN, your IP address will be visible to file servers." = "Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für Datei-Server sichtbar sein."; -/* No comment provided by engineer. */ +/* alert message */ "Without Tor or VPN, your IP address will be visible to these XFTP relays: %@." = "Ohne Tor- oder VPN-Nutzung wird Ihre IP-Adresse für diese XFTP-Relais sichtbar sein: %@."; /* No comment provided by engineer. */ @@ -4918,9 +5342,6 @@ /* No comment provided by engineer. */ "you" = "Profil"; -/* No comment provided by engineer. */ -"You" = "Profil"; - /* No comment provided by engineer. */ "You **must not** use the same database on two devices." = "Sie dürfen die selbe Datenbank **nicht** auf zwei Geräten nutzen."; @@ -4936,6 +5357,9 @@ /* No comment provided by engineer. */ "You are already connected to %@." = "Sie sind bereits mit %@ verbunden."; +/* No comment provided by engineer. */ +"You are already connected with %@." = "Sie sind bereits mit %@ verbunden."; + /* No comment provided by engineer. */ "You are already connecting to %@." = "Sie sind bereits mit %@ verbunden."; @@ -4981,6 +5405,12 @@ /* No comment provided by engineer. */ "You can change it in Appearance settings." = "Kann von Ihnen in den Erscheinungsbild-Einstellungen geändert werden."; +/* No comment provided by engineer. */ +"You can configure operators in Network & servers settings." = "Sie können die Betreiber in den Netzwerk- und Servereinstellungen konfigurieren."; + +/* No comment provided by engineer. */ +"You can configure servers via settings." = "Sie können die Server über die Einstellungen konfigurieren."; + /* No comment provided by engineer. */ "You can create it later" = "Sie können dies später erstellen"; @@ -5005,6 +5435,9 @@ /* No comment provided by engineer. */ "You can send messages to %@ from Archived contacts." = "Sie können aus den archivierten Kontakten heraus Nachrichten an %@ versenden."; +/* No comment provided by engineer. */ +"You can set connection name, to remember who the link was shared with." = "Sie können einen Verbindungsnamen festlegen, um sich zu merken, mit wem der Link geteilt wurde."; + /* No comment provided by engineer. */ "You can set lock screen notification preview via settings." = "Über die Geräte-Einstellungen können Sie die Benachrichtigungsvorschau im Sperrbildschirm erlauben."; @@ -5014,14 +5447,11 @@ /* No comment provided by engineer. */ "You can share this address with your contacts to let them connect with **%@**." = "Sie können diese Adresse mit Ihren Kontakten teilen, um sie mit **%@** verbinden zu lassen."; -/* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Sie können Ihre Adresse als Link oder als QR-Code teilen – Jede Person kann sich darüber mit Ihnen verbinden."; - /* No comment provided by engineer. */ "You can start chat via app Settings / Database or by restarting the app" = "Sie können den Chat über die App-Einstellungen / Datenbank oder durch Neustart der App starten"; /* No comment provided by engineer. */ -"You can still view conversation with %@ in the list of chats." = "Sie können in der Chatliste weiterhin die Unterhaltung mit %@ einsehen."; +"You can still view conversation with %@ in the list of chats." = "Sie können in der Chat-Liste weiterhin die Unterhaltung mit %@ einsehen."; /* No comment provided by engineer. */ "You can turn on SimpleX Lock via Settings." = "Sie können die SimpleX-Sperre über die Einstellungen aktivieren."; @@ -5029,7 +5459,7 @@ /* 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. */ +/* alert message */ "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. */ @@ -5048,10 +5478,10 @@ "you changed role of %@ to %@" = "Sie haben die Rolle von %1$@ auf %2$@ geändert"; /* No comment provided by engineer. */ -"You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." = "Sie können selbst festlegen, über welche Server Sie Ihre Nachrichten **empfangen** und an Ihre Kontakte **senden** wollen."; +"You could not be verified; please try again." = "Sie konnten nicht überprüft werden; bitte versuchen Sie es erneut."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "Sie konnten nicht überprüft werden; bitte versuchen Sie es erneut."; +"You decide who can connect." = "Sie entscheiden, wer sich mit Ihnen verbinden kann."; /* No comment provided by engineer. */ "You have already requested connection via this address!" = "Sie haben über diese Adresse bereits eine Verbindung beantragt!"; @@ -5128,6 +5558,9 @@ /* No comment provided by engineer. */ "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 chat. Chat history will be preserved." = "Sie werden von diesem Chat keine Nachrichten mehr erhalten. Der Nachrichtenverlauf wird beibehalten."; + /* 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 Nachrichtenverlauf wird beibehalten."; @@ -5143,9 +5576,6 @@ /* 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" = "Sie verwenden ein Inkognito-Profil für diese Gruppe. Um zu verhindern, dass Sie Ihr Hauptprofil teilen, ist in diesem Fall das Einladen von Kontakten nicht erlaubt"; -/* No comment provided by engineer. */ -"Your %@ servers" = "Ihre %@-Server"; - /* No comment provided by engineer. */ "Your calls" = "Anrufe"; @@ -5155,9 +5585,15 @@ /* No comment provided by engineer. */ "Your chat database is not encrypted - set passphrase to encrypt it." = "Ihre Chat-Datenbank ist nicht verschlüsselt. Bitte legen Sie ein Passwort fest, um sie zu schützen."; +/* alert title */ +"Your chat preferences" = "Ihre Chat-Präferenzen"; + /* No comment provided by engineer. */ "Your chat profiles" = "Ihre Chat-Profile"; +/* No comment provided by engineer. */ +"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Ihre Verbindung wurde auf %@ verschoben. Während Sie auf das Profil weitergeleitet wurden trat aber ein unerwarteter Fehler auf."; + /* No comment provided by engineer. */ "Your contact sent a file that is larger than currently supported maximum size (%@)." = "Ihr Kontakt hat eine Datei gesendet, die größer ist als die derzeit unterstützte maximale Größe (%@)."; @@ -5167,6 +5603,9 @@ /* No comment provided by engineer. */ "Your contacts will remain connected." = "Ihre Kontakte bleiben weiterhin verbunden."; +/* No comment provided by engineer. */ +"Your credentials may be sent unencrypted." = "Ihre Anmeldeinformationen können unverschlüsselt versendet werden."; + /* No comment provided by engineer. */ "Your current chat database will be DELETED and REPLACED with the imported one." = "Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT."; @@ -5189,7 +5628,10 @@ "Your profile **%@** will be shared." = "Ihr Profil **%@** wird geteilt."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt.\nSimpleX-Server können Ihr Profil nicht einsehen."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht einsehen."; + +/* alert message */ +"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Ihr Profil wurde geändert. Wenn Sie es speichern, wird das aktualisierte Profil an alle Ihre Kontakte gesendet."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert."; @@ -5198,10 +5640,10 @@ "Your random profile" = "Ihr Zufallsprofil"; /* No comment provided by engineer. */ -"Your server" = "Ihr Server"; +"Your server address" = "Ihre Serveradresse"; /* No comment provided by engineer. */ -"Your server address" = "Ihre Serveradresse"; +"Your servers" = "Ihre Server"; /* No comment provided by engineer. */ "Your settings" = "Einstellungen"; @@ -5212,6 +5654,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "Ihre SMP-Server"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "Ihre XFTP-Server"; - diff --git a/apps/ios/en.lproj/Localizable.strings b/apps/ios/en.lproj/Localizable.strings index cf485752ea..cb83427195 100644 --- a/apps/ios/en.lproj/Localizable.strings +++ b/apps/ios/en.lproj/Localizable.strings @@ -1,9 +1,6 @@ /* 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*"; @@ -27,4 +24,3 @@ /* No comment provided by engineer. */ "No group!" = "Group not found!"; - diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings index 7645a8e2b6..e7570f177e 100644 --- a/apps/ios/es.lproj/Localizable.strings +++ b/apps/ios/es.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -65,10 +56,7 @@ "[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."; +"**Create 1-time link**: to create and share a new invitation link." = "**Añadir contacto**: crea un enlace de invitación nuevo."; /* No comment provided by engineer. */ "**Create group**: to create a new group." = "**Crear grupo**: crea un grupo nuevo."; @@ -80,10 +68,10 @@ "**e2e encrypted** video call" = "Videollamada con **cifrado de extremo a extremo**"; /* 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." = "**Más privado**: comprueba los mensajes nuevos cada 20 minutos. El token del dispositivo se comparte con el servidor de SimpleX Chat, pero no cuántos contactos o mensajes tienes."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Más privado**: comprueba los mensajes nuevos cada 20 minutos. El token del dispositivo se comparte con el servidor de SimpleX Chat, pero no cuántos contactos o mensajes tienes."; /* 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)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. */ "**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Recuarda**: usar la misma base de datos en dos dispositivos hará que falle el descifrado de mensajes como protección de seguridad."; @@ -92,7 +80,10 @@ "**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."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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 / Paste link**: to connect via a link you received." = "**Escanear / Pegar enlace**: para conectar mediante un enlace recibido."; /* 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."; @@ -154,12 +145,21 @@ /* No comment provided by engineer. */ "%@ is verified" = "%@ está verificado"; +/* No comment provided by engineer. */ +"%@ server" = "%@ servidor"; + +/* No comment provided by engineer. */ +"%@ servers" = "%@ servidores"; + /* No comment provided by engineer. */ "%@ uploaded" = "%@ subido"; /* notification title */ "%@ wants to connect!" = "¡ %@ quiere contactar!"; +/* format for date separator in chat */ +"%@, %@" = "%1$@, %2$@"; + /* No comment provided by engineer. */ "%@, %@ and %lld members" = "%@, %@ y %lld miembro(s) más"; @@ -170,25 +170,40 @@ "%@:" = "%@:"; /* time interval */ -"%d days" = "%d días"; +"%d days" = "%d día(s)"; + +/* forward confirmation reason */ +"%d file(s) are still being downloaded." = "%d archivo(s) se está(n) descargando todavía."; + +/* forward confirmation reason */ +"%d file(s) failed to download." = "La descarga ha fallado para %d archivo(s)."; + +/* forward confirmation reason */ +"%d file(s) were deleted." = "%d archivo(s) ha(n) sido eliminado(s)."; + +/* forward confirmation reason */ +"%d file(s) were not downloaded." = "%d archivo(s) no se ha(n) descargado."; /* time interval */ -"%d hours" = "%d horas"; +"%d hours" = "%d hora(s)"; + +/* alert title */ +"%d messages not forwarded" = "%d mensaje(s) no enviado(s)"; /* time interval */ -"%d min" = "%d minutos"; +"%d min" = "%d minuto(s)"; /* time interval */ -"%d months" = "%d meses"; +"%d months" = "%d mes(es)"; /* time interval */ -"%d sec" = "%d segundos"; +"%d sec" = "%d segundo(s)"; /* integrity error chat item */ -"%d skipped message(s)" = "%d mensaje(s) saltado(s"; +"%d skipped message(s)" = "%d mensaje(s) omitido(s)"; /* time interval */ -"%d weeks" = "%d semanas"; +"%d weeks" = "%d semana(s)"; /* No comment provided by engineer. */ "%lld" = "%lld"; @@ -289,6 +304,12 @@ /* time interval */ "1 week" = "una semana"; +/* No comment provided by engineer. */ +"1-time link" = "Enlace de un uso"; + +/* No comment provided by engineer. */ +"1-time link can be used *with one contact only* - share in person or via any messenger." = "Los enlaces de un uso pueden ser usados *solamente con un contacto* - compártelos en persona o mediante cualquier aplicación de mensajería."; + /* No comment provided by engineer. */ "5 minutes" = "5 minutos"; @@ -305,7 +326,7 @@ "A new contact" = "Contacto nuevo"; /* No comment provided by engineer. */ -"A new random profile will be shared." = "Se compartirá un perfil nuevo aleatorio."; +"A new random profile will be shared." = "Compartirás un perfil nuevo aleatorio."; /* No comment provided by engineer. */ "A separate TCP connection will be used **for each chat profile you have in the app**." = "Se usará una conexión TCP independiente **por cada perfil que tengas en la aplicación**."; @@ -323,10 +344,7 @@ "Abort changing address?" = "¿Cancelar el cambio de servidor?"; /* No comment provided by engineer. */ -"About SimpleX" = "Acerca de SimpleX"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "Acerca de la dirección SimpleX"; +"About operators" = "Acerca de los operadores"; /* No comment provided by engineer. */ "About SimpleX Chat" = "Sobre SimpleX Chat"; @@ -342,6 +360,9 @@ swipe action */ "Accept" = "Aceptar"; +/* No comment provided by engineer. */ +"Accept conditions" = "Aceptar condiciones"; + /* No comment provided by engineer. */ "Accept connection request?" = "¿Aceptar solicitud de conexión?"; @@ -355,6 +376,12 @@ /* call status */ "accepted call" = "llamada aceptada"; +/* No comment provided by engineer. */ +"Accepted conditions" = "Condiciones aceptadas"; + +/* chat list item title */ +"accepted invitation" = "invitación aceptada"; + /* No comment provided by engineer. */ "Acknowledged" = "Confirmaciones"; @@ -368,10 +395,7 @@ "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"; +"Add friends" = "Añadir amigos"; /* No comment provided by engineer. */ "Add profile" = "Añadir perfil"; @@ -382,12 +406,24 @@ /* No comment provided by engineer. */ "Add servers by scanning QR codes." = "Añadir servidores mediante el escaneo de códigos QR."; +/* No comment provided by engineer. */ +"Add team members" = "Añadir miembros del equipo"; + /* No comment provided by engineer. */ "Add to another device" = "Añadir a otro dispositivo"; /* No comment provided by engineer. */ "Add welcome message" = "Añadir mensaje de bienvenida"; +/* No comment provided by engineer. */ +"Add your team members to the conversations." = "Añade a los miembros de tu equipo a las conversaciones."; + +/* No comment provided by engineer. */ +"Added media & file servers" = "Servidores de archivos y multimedia añadidos"; + +/* No comment provided by engineer. */ +"Added message servers" = "Servidores de mensajes añadidos"; + /* No comment provided by engineer. */ "Additional accent" = "Acento adicional"; @@ -403,6 +439,12 @@ /* No comment provided by engineer. */ "Address change will be aborted. Old receiving address will be used." = "El cambio de dirección se cancelará. Se usará la antigua dirección de recepción."; +/* No comment provided by engineer. */ +"Address or 1-time link?" = "¿Dirección o enlace de un uso?"; + +/* No comment provided by engineer. */ +"Address settings" = "Configuración de dirección"; + /* member role */ "admin" = "administrador"; @@ -437,7 +479,7 @@ "All data is erased when it is entered." = "Al introducirlo todos los datos son eliminados."; /* No comment provided by engineer. */ -"All data is private to your device." = "Todos los datos son privados y están en tu dispositivo."; +"All data is kept private on your device." = "Todos los datos son privados y están en tu dispositivo."; /* No comment provided by engineer. */ "All group members will remain connected." = "Todos los miembros del grupo permanecerán conectados."; @@ -445,6 +487,9 @@ /* feature role */ "all members" = "todos los miembros"; +/* No comment provided by engineer. */ +"All messages and files are sent **end-to-end encrypted**, with post-quantum security in direct messages." = "Todos los mensajes y archivos son enviados **cifrados de extremo a extremo** y con seguridad de cifrado postcuántico en mensajes directos."; + /* No comment provided by engineer. */ "All messages will be deleted - this cannot be undone!" = "Todos los mensajes serán borrados. ¡No podrá deshacerse!"; @@ -454,7 +499,7 @@ /* No comment provided by engineer. */ "All new messages from %@ will be hidden!" = "¡Los mensajes nuevos de %@ estarán ocultos!"; -/* No comment provided by engineer. */ +/* profile dropdown */ "All profiles" = "Todos los perfiles"; /* No comment provided by engineer. */ @@ -506,7 +551,7 @@ "Allow to send files and media." = "Se permite enviar archivos y multimedia."; /* No comment provided by engineer. */ -"Allow to send SimpleX links." = "Permitir enviar enlaces SimpleX."; +"Allow to send SimpleX links." = "Se permite enviar enlaces SimpleX."; /* No comment provided by engineer. */ "Allow to send voice messages." = "Permites enviar mensajes de voz."; @@ -559,6 +604,9 @@ /* No comment provided by engineer. */ "Answer call" = "Responder llamada"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "Cualquiera puede alojar servidores."; + /* No comment provided by engineer. */ "App build: %@" = "Compilación app: %@"; @@ -577,6 +625,9 @@ /* No comment provided by engineer. */ "App passcode is replaced with self-destruct passcode." = "El código de acceso será reemplazado por código de autodestrucción."; +/* No comment provided by engineer. */ +"App session" = "Sesión de aplicación"; + /* No comment provided by engineer. */ "App version" = "Versión de la aplicación"; @@ -596,7 +647,7 @@ "Archive and upload" = "Archivar y subir"; /* No comment provided by engineer. */ -"Archive contacts to chat later." = "Archivar contactos para charlar más tarde."; +"Archive contacts to chat later." = "Archiva contactos para charlar más tarde."; /* No comment provided by engineer. */ "Archived contacts" = "Contactos archivados"; @@ -649,6 +700,9 @@ /* No comment provided by engineer. */ "Auto-accept images" = "Aceptar imágenes automáticamente"; +/* alert title */ +"Auto-accept settings" = "Auto aceptar configuración"; + /* No comment provided by engineer. */ "Back" = "Volver"; @@ -670,15 +724,30 @@ /* No comment provided by engineer. */ "Bad message ID" = "ID de mensaje incorrecto"; +/* No comment provided by engineer. */ +"Better calls" = "Llamadas mejoradas"; + /* No comment provided by engineer. */ "Better groups" = "Grupos mejorados"; +/* No comment provided by engineer. */ +"Better message dates." = "Sistema de fechas mejorado."; + /* No comment provided by engineer. */ "Better messages" = "Mensajes mejorados"; /* No comment provided by engineer. */ "Better networking" = "Uso de red mejorado"; +/* No comment provided by engineer. */ +"Better notifications" = "Notificaciones mejoradas"; + +/* No comment provided by engineer. */ +"Better security ✅" = "Seguridad mejorada ✅"; + +/* No comment provided by engineer. */ +"Better user experience" = "Experiencia de usuario mejorada"; + /* No comment provided by engineer. */ "Black" = "Negro"; @@ -713,7 +782,7 @@ "Blocked by admin" = "Bloqueado por administrador"; /* No comment provided by engineer. */ -"Blur for better privacy." = "Difuminar para más privacidad."; +"Blur for better privacy." = "Difumina para mayor privacidad."; /* No comment provided by engineer. */ "Blur media" = "Difuminar multimedia"; @@ -739,6 +808,12 @@ /* 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)!" = "Búlgaro, Finlandés, Tailandés y Ucraniano - gracias a los usuarios y [Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"; +/* No comment provided by engineer. */ +"Business address" = "Dirección empresarial"; + +/* No comment provided by engineer. */ +"Business chats" = "Chats empresariales"; + /* 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)." = "Mediante perfil (predeterminado) o [por conexión](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; @@ -781,7 +856,8 @@ /* No comment provided by engineer. */ "Can't message member" = "No se pueden enviar mensajes al miembro"; -/* No comment provided by engineer. */ +/* alert action + alert button */ "Cancel" = "Cancelar"; /* No comment provided by engineer. */ @@ -796,7 +872,7 @@ /* No comment provided by engineer. */ "Cannot forward message" = "No se puede reenviar el mensaje"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "No se puede recibir el archivo"; /* snd error text */ @@ -808,6 +884,9 @@ /* No comment provided by engineer. */ "Change" = "Cambiar"; +/* authentication reason */ +"Change chat profiles" = "Cambiar perfil de usuario"; + /* No comment provided by engineer. */ "Change database passphrase?" = "¿Cambiar contraseña de la base de datos?"; @@ -852,7 +931,13 @@ "changing address…" = "cambiando de servidor…"; /* No comment provided by engineer. */ -"Chat archive" = "Archivo del chat"; +"Chat" = "Chat"; + +/* No comment provided by engineer. */ +"Chat already exists" = "El chat ya existe"; + +/* No comment provided by engineer. */ +"Chat already exists!" = "¡El chat ya existe!"; /* No comment provided by engineer. */ "Chat colors" = "Colores del chat"; @@ -890,13 +975,31 @@ /* No comment provided by engineer. */ "Chat preferences" = "Preferencias de Chat"; +/* alert message */ +"Chat preferences were changed." = "Las preferencias del chat han sido modificadas."; + +/* No comment provided by engineer. */ +"Chat profile" = "Perfil de usuario"; + /* No comment provided by engineer. */ "Chat theme" = "Tema de chat"; +/* No comment provided by engineer. */ +"Chat will be deleted for all members - this cannot be undone!" = "El chat será eliminado para todos los miembros. ¡No podrá deshacerse!"; + +/* No comment provided by engineer. */ +"Chat will be deleted for you - this cannot be undone!" = "El chat será eliminado para tí. ¡No podrá deshacerse!"; + /* No comment provided by engineer. */ "Chats" = "Chats"; /* No comment provided by engineer. */ +"Check messages every 20 min." = "Comprobar mensajes cada 20 min."; + +/* No comment provided by engineer. */ +"Check messages when allowed." = "Comprobar mensajes cuando se permita."; + +/* alert title */ "Check server address and try again." = "Comprueba la dirección del servidor e inténtalo de nuevo."; /* No comment provided by engineer. */ @@ -957,10 +1060,34 @@ "Completed" = "Completadas"; /* No comment provided by engineer. */ -"Configure ICE servers" = "Configure servidores ICE"; +"Conditions accepted on: %@." = "Condiciones aceptadas el: %@."; /* No comment provided by engineer. */ -"Configured %@ servers" = "%@ servidores configurados"; +"Conditions are accepted for the operator(s): **%@**." = "Las condiciones se han aceptado para el(los) operador(s): **%@**."; + +/* No comment provided by engineer. */ +"Conditions are already accepted for these operator(s): **%@**." = "Las condiciones ya se han aceptado para el/los siguiente(s) operador(s): **%@**."; + +/* No comment provided by engineer. */ +"Conditions of use" = "Condiciones de uso"; + +/* No comment provided by engineer. */ +"Conditions will be accepted for enabled operators after 30 days." = "Las condiciones de los operadores habilitados serán aceptadas después de 30 días."; + +/* No comment provided by engineer. */ +"Conditions will be accepted for operator(s): **%@**." = "Las condiciones serán aceptadas para el/los operador(es): **%@**."; + +/* No comment provided by engineer. */ +"Conditions will be accepted for the operator(s): **%@**." = "Las condiciones serán aceptadas para el/los operador(es): **%@**."; + +/* No comment provided by engineer. */ +"Conditions will be accepted on: %@." = "Las condiciones serán aceptadas el: %@."; + +/* No comment provided by engineer. */ +"Conditions will be automatically accepted for enabled operators on: %@." = "Las condiciones serán aceptadas automáticamente para los operadores habilitados el: %@."; + +/* No comment provided by engineer. */ +"Configure ICE servers" = "Configure servidores ICE"; /* No comment provided by engineer. */ "Confirm" = "Confirmar"; @@ -987,7 +1114,7 @@ "Confirm password" = "Confirmar contraseña"; /* No comment provided by engineer. */ -"Confirm that you remember database passphrase to migrate it." = "Para migrar confirma que recuerdas la frase de contraseña de la base de datos."; +"Confirm that you remember database passphrase to migrate it." = "Para migrar la base de datos confirma que recuerdas la frase de contraseña."; /* No comment provided by engineer. */ "Confirm upload" = "Confirmar subida"; @@ -1082,14 +1209,14 @@ /* No comment provided by engineer. */ "Connecting to desktop" = "Conectando con ordenador"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "conectando…"; /* No comment provided by engineer. */ "Connection" = "Conexión"; /* No comment provided by engineer. */ -"Connection and servers status." = "Estado de conexión y servidores."; +"Connection and servers status." = "Estado de tu conexión y servidores."; /* No comment provided by engineer. */ "Connection error" = "Error conexión"; @@ -1106,6 +1233,9 @@ /* No comment provided by engineer. */ "Connection request sent!" = "¡Solicitud de conexión enviada!"; +/* No comment provided by engineer. */ +"Connection security" = "Seguridad de conexión"; + /* No comment provided by engineer. */ "Connection terminated" = "Conexión finalizada"; @@ -1178,6 +1308,9 @@ /* No comment provided by engineer. */ "Core version: v%@" = "Versión Core: v%@"; +/* No comment provided by engineer. */ +"Corner" = "Esquina"; + /* No comment provided by engineer. */ "Correct name to %@?" = "¿Corregir el nombre a %@?"; @@ -1185,10 +1318,10 @@ "Create" = "Crear"; /* No comment provided by engineer. */ -"Create a group using a random profile." = "Crear grupo usando perfil aleatorio."; +"Create 1-time link" = "Crear enlace de un uso"; /* 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."; +"Create a group using a random profile." = "Crear grupo usando perfil aleatorio."; /* server test step */ "Create file" = "Crear archivo"; @@ -1229,9 +1362,6 @@ /* copied message info */ "Created at: %@" = "Creado: %@"; -/* No comment provided by engineer. */ -"Created on %@" = "Creado en %@"; - /* No comment provided by engineer. */ "Creating archive link" = "Creando enlace al archivo"; @@ -1241,6 +1371,9 @@ /* No comment provided by engineer. */ "creator" = "creador"; +/* No comment provided by engineer. */ +"Current conditions text couldn't be loaded, you can review conditions via this link:" = "El texto con las condiciones actuales no se ha podido cargar, puedes revisar las condiciones en el siguiente enlace:"; + /* No comment provided by engineer. */ "Current Passcode" = "Código de Acceso"; @@ -1259,6 +1392,9 @@ /* No comment provided by engineer. */ "Custom time" = "Tiempo personalizado"; +/* No comment provided by engineer. */ +"Customizable message shape." = "Forma personalizable de los mensajes."; + /* No comment provided by engineer. */ "Customize theme" = "Personalizar tema"; @@ -1305,7 +1441,7 @@ "Database passphrase & export" = "Base de datos y contraseña"; /* No comment provided by engineer. */ -"Database passphrase is different from saved in the keychain." = "La contraseña es distinta a la almacenada en Keychain."; +"Database passphrase is different from saved in the keychain." = "La contraseña es diferente a la almacenada en Keychain."; /* No comment provided by engineer. */ "Database passphrase is required to open chat." = "Para abrir la aplicación se requiere la contraseña de la base de datos."; @@ -1349,7 +1485,8 @@ /* No comment provided by engineer. */ "default (yes)" = "predeterminado (sí)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Eliminar"; @@ -1375,10 +1512,7 @@ "Delete and notify contact" = "Eliminar y notificar contacto"; /* No comment provided by engineer. */ -"Delete archive" = "Eliminar archivo"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "¿Eliminar archivo del chat?"; +"Delete chat" = "Eliminar chat"; /* No comment provided by engineer. */ "Delete chat profile" = "Eliminar perfil"; @@ -1386,6 +1520,9 @@ /* No comment provided by engineer. */ "Delete chat profile?" = "¿Eliminar perfil?"; +/* No comment provided by engineer. */ +"Delete chat?" = "¿Eliminar chat?"; + /* No comment provided by engineer. */ "Delete connection" = "Eliminar conexión"; @@ -1405,7 +1542,7 @@ "Delete file" = "Eliminar archivo"; /* No comment provided by engineer. */ -"Delete files and media?" = "Eliminar archivos y multimedia?"; +"Delete files and media?" = "¿Eliminar archivos y multimedia?"; /* No comment provided by engineer. */ "Delete files for all chat profiles" = "Eliminar archivos de todos los perfiles"; @@ -1449,6 +1586,9 @@ /* No comment provided by engineer. */ "Delete old database?" = "¿Eliminar base de datos antigua?"; +/* No comment provided by engineer. */ +"Delete or moderate up to 200 messages." = "Borra o modera hasta 200 mensajes a la vez."; + /* No comment provided by engineer. */ "Delete pending connection?" = "¿Eliminar conexión pendiente?"; @@ -1488,6 +1628,9 @@ /* No comment provided by engineer. */ "Deletion errors" = "Errores de eliminación"; +/* No comment provided by engineer. */ +"Delivered even when Apple drops them." = "Entregados incluso cuando Apple los descarta."; + /* No comment provided by engineer. */ "Delivery" = "Entrega"; @@ -1555,7 +1698,10 @@ "Direct messages" = "Mensajes directos"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Los mensajes directos entre miembros del grupo no están permitidos."; +"Direct messages between members are prohibited in this chat." = "Mensajes directos no permitidos entre miembros de este chat."; + +/* No comment provided by engineer. */ +"Direct messages between members are prohibited." = "Los mensajes directos entre miembros del grupo no están permitidos."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Desactivar (conservando anulaciones)"; @@ -1582,7 +1728,7 @@ "Disappearing messages are prohibited in this chat." = "Los mensajes temporales no están permitidos en este chat."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "Los mensajes temporales no están permitidos en este grupo."; +"Disappearing messages are prohibited." = "Los mensajes temporales no están permitidos en este grupo."; /* No comment provided by engineer. */ "Disappears at" = "Desaparecerá"; @@ -1594,7 +1740,7 @@ "Disconnect" = "Desconectar"; /* No comment provided by engineer. */ -"Disconnect desktop?" = "¿Desconectar ordenador?"; +"Disconnect desktop?" = "¿Desconectar del ordenador?"; /* No comment provided by engineer. */ "Discover and join groups" = "Descubre y únete a grupos"; @@ -1606,11 +1752,14 @@ "Do it later" = "Hacer más tarde"; /* No comment provided by engineer. */ -"Do not send history to new members." = "No enviar historial a miembros nuevos."; +"Do not send history to new members." = "No se envía el historial a los miembros nuevos."; /* No comment provided by engineer. */ "Do NOT send messages directly, even if your or destination server does not support private routing." = "NO enviar mensajes directamente incluso si tu servidor o el de destino no soportan enrutamiento privado."; +/* No comment provided by engineer. */ +"Do not use credentials with proxy." = "No uses credenciales con proxy."; + /* No comment provided by engineer. */ "Do NOT use private routing." = "NO usar enrutamiento privado."; @@ -1624,12 +1773,13 @@ "Don't enable" = "No activar"; /* No comment provided by engineer. */ -"Don't show again" = "No mostrar de nuevo"; +"Don't show again" = "No volver a mostrar"; /* No comment provided by engineer. */ "Downgrade and open chat" = "Degradar y abrir Chat"; -/* chat item action */ +/* alert button + chat item action */ "Download" = "Descargar"; /* No comment provided by engineer. */ @@ -1641,6 +1791,9 @@ /* server test step */ "Download file" = "Descargar archivo"; +/* alert action */ +"Download files" = "Descargar archivos"; + /* No comment provided by engineer. */ "Downloaded" = "Descargado"; @@ -1668,6 +1821,9 @@ /* No comment provided by engineer. */ "e2e encrypted" = "cifrado de extremo a extremo"; +/* No comment provided by engineer. */ +"E2E encrypted notifications." = "Notificaciones cifradas E2E."; + /* chat item action */ "Edit" = "Editar"; @@ -1686,6 +1842,9 @@ /* No comment provided by engineer. */ "Enable camera access" = "Permitir acceso a la cámara"; +/* No comment provided by engineer. */ +"Enable Flux" = "Habilita Flux"; + /* No comment provided by engineer. */ "Enable for all" = "Activar para todos"; @@ -1845,24 +2004,33 @@ /* No comment provided by engineer. */ "Error aborting address change" = "Error al cancelar cambio de dirección"; +/* alert title */ +"Error accepting conditions" = "Error al aceptar las condiciones"; + /* No comment provided by engineer. */ "Error accepting contact request" = "Error al aceptar solicitud del contacto"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Error al acceder al archivo de la base de datos"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Error al añadir miembro(s)"; +/* alert title */ +"Error adding server" = "Error al añadir servidor"; + /* No comment provided by engineer. */ "Error changing address" = "Error al cambiar servidor"; +/* No comment provided by engineer. */ +"Error changing connection profile" = "Error al cambiar el perfil de conexión"; + /* No comment provided by engineer. */ "Error changing role" = "Error al cambiar rol"; /* No comment provided by engineer. */ "Error changing setting" = "Error cambiando configuración"; +/* No comment provided by engineer. */ +"Error changing to incognito!" = "¡Error al cambiar a incógnito!"; + /* No comment provided by engineer. */ "Error connecting to forwarding server %@. Please try later." = "Error al conectar con el servidor de reenvío %@. Por favor, inténtalo más tarde."; @@ -1932,13 +2100,16 @@ /* No comment provided by engineer. */ "Error joining group" = "Error al unirte al grupo"; +/* alert title */ +"Error loading servers" = "Error al cargar servidores"; + /* No comment provided by engineer. */ -"Error loading %@ servers" = "Error al cargar servidores %@"; +"Error migrating settings" = "Error al migrar la configuración"; /* No comment provided by engineer. */ "Error opening chat" = "Error al abrir chat"; -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Error al recibir archivo"; /* No comment provided by engineer. */ @@ -1953,9 +2124,6 @@ /* No comment provided by engineer. */ "Error resetting statistics" = "Error al restablecer las estadísticas"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Error al guardar servidores %@"; - /* No comment provided by engineer. */ "Error saving group profile" = "Error al guardar perfil de grupo"; @@ -1968,6 +2136,9 @@ /* No comment provided by engineer. */ "Error saving passphrase to keychain" = "Error al guardar contraseña en Keychain"; +/* alert title */ +"Error saving servers" = "Error al guardar servidores"; + /* when migrating */ "Error saving settings" = "Error al guardar ajustes"; @@ -1996,6 +2167,9 @@ "Error stopping chat" = "Error al parar SimpleX"; /* No comment provided by engineer. */ +"Error switching profile" = "Error al cambiar perfil"; + +/* alertTitle */ "Error switching profile!" = "¡Error al cambiar perfil!"; /* No comment provided by engineer. */ @@ -2007,6 +2181,9 @@ /* No comment provided by engineer. */ "Error updating message" = "Error al actualizar mensaje"; +/* alert title */ +"Error updating server" = "Error al actualizar el servidor"; + /* No comment provided by engineer. */ "Error updating settings" = "Error al actualizar configuración"; @@ -2022,8 +2199,7 @@ /* No comment provided by engineer. */ "Error: " = "Error: "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Error: %@"; /* No comment provided by engineer. */ @@ -2035,6 +2211,9 @@ /* No comment provided by engineer. */ "Errors" = "Errores"; +/* servers error */ +"Errors in servers configuration." = "Error en la configuración del servidor."; + /* No comment provided by engineer. */ "Even when disabled in the conversation." = "Incluso si está desactivado para la conversación."; @@ -2048,7 +2227,7 @@ "Expand" = "Expandir"; /* No comment provided by engineer. */ -"expired" = "expirado"; +"expired" = "expirados"; /* No comment provided by engineer. */ "Export database" = "Exportar base de datos"; @@ -2083,6 +2262,9 @@ /* No comment provided by engineer. */ "File error" = "Error de archivo"; +/* alert message */ +"File errors:\n%@" = "Error(es) de archivo\n%@"; + /* file error text */ "File not found - most likely file was deleted or cancelled." = "Archivo no encontrado, probablemente haya sido borrado o cancelado."; @@ -2117,7 +2299,7 @@ "Files and media" = "Archivos y multimedia"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "Los archivos y multimedia no están permitidos en este grupo."; +"Files and media are prohibited." = "Los archivos y multimedia no están permitidos en este grupo."; /* No comment provided by engineer. */ "Files and media not allowed" = "Archivos y multimedia no permitidos"; @@ -2158,15 +2340,42 @@ /* No comment provided by engineer. */ "Fix not supported by group member" = "Corrección no compatible con miembro del grupo"; +/* No comment provided by engineer. */ +"for better metadata privacy." = "para mejorar la privacidad de los metadatos."; + +/* servers error */ +"For chat profile %@:" = "Para el perfil de chat %@:"; + /* No comment provided by engineer. */ "For console" = "Para consola"; +/* No comment provided by engineer. */ +"For example, if your contact receives messages via a SimpleX Chat server, your app will deliver them via a Flux server." = "Si por ejemplo tu contacto recibe los mensajes a través de un servidor de SimpleX Chat, tu aplicación los entregará a través de un servidor de Flux."; + +/* No comment provided by engineer. */ +"For private routing" = "Para el enrutamiento privado"; + +/* No comment provided by engineer. */ +"For social media" = "Para redes sociales"; + /* chat item action */ "Forward" = "Reenviar"; +/* alert title */ +"Forward %d message(s)?" = "¿Reenviar %d mensaje(s)?"; + /* No comment provided by engineer. */ "Forward and save messages" = "Reenviar y guardar mensajes"; +/* alert action */ +"Forward messages" = "Reenviar mensajes"; + +/* alert message */ +"Forward messages without files?" = "¿Reenviar mensajes sin los archivos?"; + +/* No comment provided by engineer. */ +"Forward up to 20 messages at once." = "Desplazamiento de hasta 20 mensajes."; + /* No comment provided by engineer. */ "forwarded" = "reenviado"; @@ -2176,6 +2385,9 @@ /* No comment provided by engineer. */ "Forwarded from" = "Reenviado por"; +/* No comment provided by engineer. */ +"Forwarding %lld messages" = "Reenviando %lld mensajes"; + /* No comment provided by engineer. */ "Forwarding server %@ failed to connect to destination server %@. Please try later." = "El servidor de reenvío %@ no ha podido conectarse al servidor de destino %@. Por favor, intentalo más tarde."; @@ -2204,13 +2416,10 @@ "Full name (optional)" = "Nombre completo (opcional)"; /* No comment provided by engineer. */ -"Full name:" = "Nombre completo:"; +"Fully decentralized – visible only to members." = "Totalmente descentralizado. Visible sólo para los miembros."; /* No comment provided by engineer. */ -"Fully decentralized – visible only to members." = "Completamente descentralizado y sólo visible para los miembros."; - -/* No comment provided by engineer. */ -"Fully re-implemented - work in background!" = "Completamente reimplementado: ¡funciona en segundo plano!"; +"Fully re-implemented - work in background!" = "Totalmente revisado. ¡Funciona en segundo plano!"; /* No comment provided by engineer. */ "Further reduced battery usage" = "Reducción consumo de batería"; @@ -2260,27 +2469,6 @@ /* No comment provided by engineer. */ "Group links" = "Enlaces de grupo"; -/* No comment provided by engineer. */ -"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. (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."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Los miembros del grupo pueden enviar mensajes temporales."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Los miembros del grupo pueden enviar archivos y multimedia."; - -/* No comment provided by engineer. */ -"Group members can send SimpleX links." = "Los miembros del grupo pueden enviar enlaces SimpleX."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Los miembros del grupo pueden enviar mensajes de voz."; - /* notification */ "Group message:" = "Mensaje de grupo:"; @@ -2342,7 +2530,10 @@ "hours" = "horas"; /* No comment provided by engineer. */ -"How it works" = "Cómo funciona"; +"How it affects privacy" = "Cómo afecta a la privacidad"; + +/* No comment provided by engineer. */ +"How it helps privacy" = "Cómo ayuda a la privacidad"; /* No comment provided by engineer. */ "How SimpleX works" = "Cómo funciona SimpleX"; @@ -2387,7 +2578,7 @@ "Immediately" = "Inmediatamente"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Inmune a spam y abuso"; +"Immune to spam" = "Inmune a spam y abuso"; /* No comment provided by engineer. */ "Import" = "Importar"; @@ -2407,6 +2598,9 @@ /* No comment provided by engineer. */ "Importing archive" = "Importando archivo"; +/* No comment provided by engineer. */ +"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Reducción del tráfico y entrega mejorada.\n¡Pronto habrá nuevas mejoras!"; + /* No comment provided by engineer. */ "Improved message delivery" = "Entrega de mensajes mejorada"; @@ -2483,10 +2677,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Instalar terminal para [SimpleX Chat](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "¡Las notificaciones automáticas estarán ocultas!\n"; +"Instant" = "Al instante"; /* No comment provided by engineer. */ -"Instantly" = "Al instante"; +"Instant push notifications will be hidden!\n" = "¡Las notificaciones automáticas estarán ocultas!\n"; /* No comment provided by engineer. */ "Interface" = "Interfaz"; @@ -2524,7 +2718,7 @@ /* No comment provided by engineer. */ "Invalid response" = "Respuesta no válida"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "¡Dirección de servidor no válida!"; /* item status text */ @@ -2545,6 +2739,9 @@ /* No comment provided by engineer. */ "Invite members" = "Invitar miembros"; +/* No comment provided by engineer. */ +"Invite to chat" = "Invitar al chat"; + /* No comment provided by engineer. */ "Invite to group" = "Invitar al grupo"; @@ -2566,6 +2763,9 @@ /* No comment provided by engineer. */ "iOS Keychain will be used to securely store passphrase after you restart the app or change passphrase - it will allow receiving push notifications." = "iOS Keychain se usará para almacenar la contraseña de forma segura después de reiniciar la aplicación o cambiar la contraseña. Esto permitirá recibir notificaciones automáticas."; +/* No comment provided by engineer. */ +"IP address" = "Dirección IP"; + /* No comment provided by engineer. */ "Irreversible message deletion" = "Eliminación irreversible del mensaje"; @@ -2573,7 +2773,7 @@ "Irreversible message deletion is prohibited in this chat." = "La eliminación irreversible de mensajes no está permitida en este chat."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "La eliminación irreversible de mensajes no está permitida en este grupo."; +"Irreversible message deletion is prohibited." = "La eliminación irreversible de mensajes no está permitida en este grupo."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Permite tener varias conexiones anónimas sin datos compartidos entre estas dentro del mismo perfil."; @@ -2626,7 +2826,7 @@ /* No comment provided by engineer. */ "Joining group" = "Entrando al grupo"; -/* No comment provided by engineer. */ +/* alert action */ "Keep" = "Guardar"; /* No comment provided by engineer. */ @@ -2635,7 +2835,7 @@ /* 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. */ +/* alert title */ "Keep unused invitation?" = "¿Guardar invitación no usada?"; /* No comment provided by engineer. */ @@ -2656,6 +2856,12 @@ /* swipe action */ "Leave" = "Salir"; +/* No comment provided by engineer. */ +"Leave chat" = "Salir del chat"; + +/* No comment provided by engineer. */ +"Leave chat?" = "¿Salir del chat?"; + /* No comment provided by engineer. */ "Leave group" = "Salir del grupo"; @@ -2692,14 +2898,11 @@ /* 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"; /* No comment provided by engineer. */ -"Local profile data only" = "Sólo datos del perfil local"; +"Local profile data only" = "Eliminar sólo el perfil"; /* No comment provided by engineer. */ "Lock after" = "Bloquear en"; @@ -2707,24 +2910,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Modo bloqueo"; -/* No comment provided by engineer. */ -"Make a private connection" = "Establecer una conexión privada"; - /* No comment provided by engineer. */ "Make one message disappear" = "Escribir un mensaje temporal"; /* No comment provided by engineer. */ "Make profile private!" = "¡Hacer perfil privado!"; -/* No comment provided by engineer. */ -"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Asegúrate de que las direcciones del servidor %@ tienen el formato correcto, están separadas por líneas y no duplicadas (%@)."; - /* No comment provided by engineer. */ "Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Asegúrate de que las direcciones del servidor WebRTC ICE tienen el formato correcto, están separadas por líneas y no duplicadas."; -/* No comment provided by engineer. */ -"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Muchos se preguntarán: *si SimpleX no tiene identificadores de usuario, ¿cómo puede entregar los mensajes?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Marcar como eliminado para todos"; @@ -2764,15 +2958,42 @@ /* item status text */ "Member inactive" = "Miembro inactivo"; +/* No comment provided by engineer. */ +"Member role will be changed to \"%@\". All chat members will be notified." = "El rol del miembro cambiará a \"%@\" y todos serán notificados."; + /* No comment provided by engineer. */ "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 \"%@\" y recibirá una invitación nueva."; +/* No comment provided by engineer. */ +"Member will be removed from chat - this cannot be undone!" = "El miembro será eliminado del chat. ¡No podrá deshacerse!"; + /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "El miembro será expulsado del grupo. ¡No podrá deshacerse!"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Los miembros pueden añadir reacciones a los mensajes."; + +/* No comment provided by engineer. */ +"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. */ +"Members can send direct messages." = "Los miembros del grupo pueden enviar mensajes directos."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Los miembros del grupo pueden enviar mensajes temporales."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Los miembros del grupo pueden enviar archivos y multimedia."; + +/* No comment provided by engineer. */ +"Members can send SimpleX links." = "Los miembros del grupo pueden enviar enlaces SimpleX."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Los miembros del grupo pueden enviar mensajes de voz."; + /* No comment provided by engineer. */ "Menus" = "Menus"; @@ -2807,7 +3028,7 @@ "Message reactions are prohibited in this chat." = "Las reacciones a los mensajes no están permitidas en este chat."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Las reacciones a los mensajes no están permitidas en este grupo."; +"Message reactions are prohibited." = "Las reacciones a los mensajes no están permitidas en este grupo."; /* notification */ "message received" = "mensaje recibido"; @@ -2818,6 +3039,9 @@ /* No comment provided by engineer. */ "Message servers" = "Servidores de mensajes"; +/* No comment provided by engineer. */ +"Message shape" = "Forma del mensaje"; + /* No comment provided by engineer. */ "Message source remains private." = "El autor del mensaje se mantiene privado."; @@ -2848,6 +3072,9 @@ /* No comment provided by engineer. */ "Messages sent" = "Mensajes enviados"; +/* alert message */ +"Messages were deleted after you selected them." = "Los mensajes han sido borrados después de seleccionarlos."; + /* No comment provided by engineer. */ "Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Los mensajes, archivos y llamadas están protegidos mediante **cifrado de extremo a extremo** con secreto perfecto hacía adelante, repudio y recuperación tras ataque."; @@ -2888,7 +3115,7 @@ "Migration is completed" = "Migración completada"; /* No comment provided by engineer. */ -"Migrations: %@" = "Migraciones: %@"; +"Migrations:" = "Migraciones:"; /* time unit */ "minutes" = "minutos"; @@ -2920,6 +3147,9 @@ /* No comment provided by engineer. */ "More reliable network connection." = "Conexión de red más fiable."; +/* No comment provided by engineer. */ +"More reliable notifications" = "Notificaciones más fiables"; + /* item status description */ "Most likely this connection is deleted." = "Probablemente la conexión ha sido eliminada."; @@ -2944,12 +3174,18 @@ /* No comment provided by engineer. */ "Network connection" = "Conexión de red"; +/* No comment provided by engineer. */ +"Network decentralization" = "Descentralización de la red"; + /* snd error text */ "Network issues - message expired after many attempts to send it." = "Problema en la red - el mensaje ha expirado tras muchos intentos de envío."; /* No comment provided by engineer. */ "Network management" = "Gestión de la red"; +/* No comment provided by engineer. */ +"Network operator" = "Operador de red"; + /* No comment provided by engineer. */ "Network settings" = "Configuración de red"; @@ -2971,15 +3207,15 @@ /* notification */ "New contact:" = "Contacto nuevo:"; -/* No comment provided by engineer. */ -"New database archive" = "Nuevo archivo de bases de datos"; - /* No comment provided by engineer. */ "New desktop app!" = "Nueva aplicación para PC!"; /* No comment provided by engineer. */ "New display name" = "Nuevo nombre mostrado"; +/* notification */ +"New events" = "Eventos nuevos"; + /* No comment provided by engineer. */ "New in %@" = "Nuevo en %@"; @@ -3001,6 +3237,15 @@ /* No comment provided by engineer. */ "New passphrase…" = "Contraseña nueva…"; +/* No comment provided by engineer. */ +"New server" = "Servidor nuevo"; + +/* No comment provided by engineer. */ +"New SOCKS credentials will be used every time you start the app." = "Se usarán credenciales SOCKS nuevas cada vez que inicies la aplicación."; + +/* No comment provided by engineer. */ +"New SOCKS credentials will be used for each server." = "Se usarán credenciales SOCKS nuevas por cada servidor."; + /* pref value */ "no" = "no"; @@ -3040,30 +3285,66 @@ /* No comment provided by engineer. */ "No info, try to reload" = "No hay información, intenta recargar"; +/* servers error */ +"No media & file servers." = "Ningún servidor de archivos y multimedia."; + +/* servers error */ +"No message servers." = "Ningún servidor de mensajes."; + /* No comment provided by engineer. */ "No network connection" = "Sin conexión de red"; +/* No comment provided by engineer. */ +"No permission to record speech" = "Sin permiso para grabación de voz"; + +/* No comment provided by engineer. */ +"No permission to record video" = "Sin permiso para grabación de vídeo"; + /* No comment provided by engineer. */ "No permission to record voice message" = "Sin permiso para grabar mensajes de voz"; +/* No comment provided by engineer. */ +"No push server" = "Ningún servidor push"; + /* No comment provided by engineer. */ "No received or sent files" = "Sin archivos recibidos o enviados"; +/* servers error */ +"No servers for private message routing." = "Ningún servidor para enrutamiento privado."; + +/* servers error */ +"No servers to receive files." = "Ningún servidor para recibir archivos."; + +/* servers error */ +"No servers to receive messages." = "Ningún servidor para recibir mensajes."; + +/* servers error */ +"No servers to send files." = "Ningún servidor para enviar archivos."; + /* copied message info in history */ "no text" = "sin texto"; +/* No comment provided by engineer. */ +"No user identifiers." = "Sin identificadores de usuario."; + /* No comment provided by engineer. */ "Not compatible!" = "¡No compatible!"; /* No comment provided by engineer. */ "Nothing selected" = "Nada seleccionado"; +/* alert title */ +"Nothing to forward!" = "¡Nada para reenviar!"; + /* No comment provided by engineer. */ "Notifications" = "Notificaciones"; /* No comment provided by engineer. */ "Notifications are disabled!" = "¡Las notificaciones están desactivadas!"; +/* No comment provided by engineer. */ +"Notifications privacy" = "Privacidad en las notificaciones"; + /* No comment provided by engineer. */ "Now admins can:\n- delete members' messages.\n- disable members (\"observer\" role)" = "Ahora los administradores pueden:\n- eliminar mensajes de los miembros.\n- desactivar el rol miembro (a rol \"observador\")"; @@ -3084,7 +3365,7 @@ /* feature offered item */ "offered %@: %@" = "ofrecido %1$@: %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ok"; /* No comment provided by engineer. */ @@ -3093,9 +3374,6 @@ /* No comment provided by engineer. */ "Old database" = "Base de datos antigua"; -/* No comment provided by engineer. */ -"Old database archive" = "Archivo de bases de datos antiguas"; - /* group pref value */ "on" = "Activado"; @@ -3112,7 +3390,10 @@ "Onion hosts will not be used." = "No se usarán hosts .onion."; /* No comment provided by engineer. */ -"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**."; +"Only chat owners can change preferences." = "Sólo los propietarios del chat pueden cambiar las preferencias."; + +/* No comment provided by engineer. */ +"Only client devices store user profiles, contacts, groups, and messages." = "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 delete conversation" = "Sólo borrar la conversación"; @@ -3159,33 +3440,39 @@ /* No comment provided by engineer. */ "Open" = "Abrir"; +/* No comment provided by engineer. */ +"Open changes" = "Abrir cambios"; + /* No comment provided by engineer. */ "Open chat" = "Abrir chat"; /* authentication reason */ "Open chat console" = "Abrir consola de Chat"; +/* No comment provided by engineer. */ +"Open conditions" = "Abrir condiciones"; + /* No comment provided by engineer. */ "Open group" = "Grupo abierto"; /* authentication reason */ "Open migration to another device" = "Abrir menú migración a otro dispositivo"; -/* No comment provided by engineer. */ -"Open server settings" = "Abrir configuración del servidor"; - /* No comment provided by engineer. */ "Open Settings" = "Abrir Configuración"; -/* authentication reason */ -"Open user profiles" = "Abrir perfil de usuario"; - -/* No comment provided by engineer. */ -"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 app…" = "Iniciando aplicación…"; +/* No comment provided by engineer. */ +"Operator" = "Operador"; + +/* alert title */ +"Operator server" = "Servidor del operador"; + +/* No comment provided by engineer. */ +"Or import archive file" = "O importa desde un archivo"; + /* No comment provided by engineer. */ "Or paste archive link" = "O pegar enlace del archivo"; @@ -3198,18 +3485,21 @@ /* No comment provided by engineer. */ "Or show this code" = "O muestra este código QR"; +/* No comment provided by engineer. */ +"Or to share privately" = "O para compartir en privado"; + /* No comment provided by engineer. */ "other" = "otros"; /* No comment provided by engineer. */ "Other" = "Otro"; -/* No comment provided by engineer. */ -"Other %@ servers" = "Otros servidores %@"; - /* No comment provided by engineer. */ "other errors" = "otros errores"; +/* alert message */ +"Other file errors:\n%@" = "Otro(s) error(es) de archivo.\n%@"; + /* member role */ "owner" = "propietario"; @@ -3231,6 +3521,9 @@ /* No comment provided by engineer. */ "Passcode set!" = "¡Código de acceso guardado!"; +/* No comment provided by engineer. */ +"Password" = "Contraseña"; + /* No comment provided by engineer. */ "Password to show" = "Contraseña para hacerlo visible"; @@ -3253,13 +3546,10 @@ "peer-to-peer" = "p2p"; /* No comment provided by engineer. */ -"Pending" = "Pendiente"; +"Pending" = "Pendientes"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "Las personas pueden conectarse contigo solo mediante los enlaces que compartes."; - -/* No comment provided by engineer. */ -"Periodically" = "Periódicamente"; +"Periodic" = "Periódicamente"; /* message decrypt error item */ "Permanent decryption error" = "Error permanente descifrado"; @@ -3327,17 +3617,20 @@ /* No comment provided by engineer. */ "Polish interface" = "Interfaz en polaco"; +/* No comment provided by engineer. */ +"Port" = "Puerto"; + /* server test error */ -"Possibly, certificate fingerprint in server address is incorrect" = "Posiblemente la huella digital del certificado en la dirección del servidor es incorrecta"; +"Possibly, certificate fingerprint in server address is incorrect" = "Posiblemente la huella del certificado en la dirección del servidor es incorrecta"; /* No comment provided by engineer. */ "Preserve the last message draft, with attachments." = "Conserva el último borrador del mensaje con los datos adjuntos."; /* No comment provided by engineer. */ -"Preset server" = "Servidor predefinido"; +"Preset server address" = "Dirección predefinida del servidor"; /* No comment provided by engineer. */ -"Preset server address" = "Dirección del servidor predefinida"; +"Preset servers" = "Servidores predefinidos"; /* No comment provided by engineer. */ "Preview" = "Vista previa"; @@ -3348,6 +3641,9 @@ /* No comment provided by engineer. */ "Privacy & security" = "Seguridad y Privacidad"; +/* No comment provided by engineer. */ +"Privacy for your customers." = "Privacidad para tus clientes."; + /* No comment provided by engineer. */ "Privacy redefined" = "Privacidad redefinida"; @@ -3370,7 +3666,7 @@ "Private routing error" = "Error de enrutamiento privado"; /* No comment provided by engineer. */ -"Profile and server connections" = "Datos del perfil y conexiones"; +"Profile and server connections" = "Eliminar perfil y conexiones"; /* No comment provided by engineer. */ "Profile image" = "Imagen del perfil"; @@ -3378,19 +3674,13 @@ /* No comment provided by engineer. */ "Profile images" = "Forma de los perfiles"; -/* 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"; /* No comment provided by engineer. */ "Profile theme" = "Tema del perfil"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "La actualización del perfil se enviará a tus contactos."; /* No comment provided by engineer. */ @@ -3415,7 +3705,7 @@ "Prohibit sending files and media." = "No permitir el envío de archivos y multimedia."; /* No comment provided by engineer. */ -"Prohibit sending SimpleX links." = "No permitir el envío de enlaces SimpleX."; +"Prohibit sending SimpleX links." = "No se permite enviar enlaces SimpleX."; /* No comment provided by engineer. */ "Prohibit sending voice messages." = "No se permiten mensajes de voz."; @@ -3439,13 +3729,16 @@ "Protocol timeout per KB" = "Timeout protocolo por KB"; /* No comment provided by engineer. */ -"Proxied" = "Con proxy"; +"Proxied" = "Como proxy"; /* No comment provided by engineer. */ "Proxied servers" = "Servidores con proxy"; /* No comment provided by engineer. */ -"Push notifications" = "Notificaciones automáticas"; +"Proxy requires password" = "El proxy requiere contraseña"; + +/* No comment provided by engineer. */ +"Push notifications" = "Notificaciones push"; /* No comment provided by engineer. */ "Push server" = "Servidor push"; @@ -3469,23 +3762,20 @@ "Read" = "Leer"; /* No comment provided by engineer. */ -"Read more" = "Conoce más"; - -/* No comment provided by engineer. */ -"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Conoce más en el [Manual del Usuario](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +"Read more" = "Saber más"; /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/chat-profiles.html#incognito-mode)." = "Conoce más en la [Guía del Usuario](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/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Conoce más en el [Manual del Usuario](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)."; + /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Conoce 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](https://github.com/simplex-chat/simplex-chat#readme)." = "Conoce 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." = "Conoce más en nuestro repositorio GitHub."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Las confirmaciones están desactivadas"; @@ -3589,6 +3879,9 @@ /* No comment provided by engineer. */ "Remove" = "Eliminar"; +/* No comment provided by engineer. */ +"Remove archive?" = "¿Eliminar archivo?"; + /* No comment provided by engineer. */ "Remove image" = "Eliminar imagen"; @@ -3611,7 +3904,7 @@ "removed contact address" = "dirección de contacto eliminada"; /* profile update event chat item */ -"removed profile picture" = "imagen de perfil eliminada"; +"removed profile picture" = "ha eliminado la imagen del perfil"; /* rcv group event chat item */ "removed you" = "te ha expulsado"; @@ -3643,6 +3936,9 @@ /* chat item action */ "Reply" = "Responder"; +/* chat list item title */ +"requested to connect" = "solicitado para conectar"; + /* No comment provided by engineer. */ "Required" = "Obligatorio"; @@ -3694,6 +3990,12 @@ /* chat item action */ "Reveal" = "Revelar"; +/* No comment provided by engineer. */ +"Review conditions" = "Revisar condiciones"; + +/* No comment provided by engineer. */ +"Review later" = "Revisar más tarde"; + /* No comment provided by engineer. */ "Revoke" = "Revocar"; @@ -3715,13 +4017,14 @@ /* No comment provided by engineer. */ "Safer groups" = "Grupos más seguros"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Guardar"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Guardar (y notificar contactos)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Guardar y notificar contacto"; /* No comment provided by engineer. */ @@ -3733,12 +4036,6 @@ /* No comment provided by engineer. */ "Save and update group profile" = "Guardar y actualizar perfil del grupo"; -/* No comment provided by engineer. */ -"Save archive" = "Guardar archivo"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Guardar configuración de auto aceptar"; - /* No comment provided by engineer. */ "Save group profile" = "Guardar perfil de grupo"; @@ -3748,7 +4045,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Guardar la contraseña en Keychain"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "¿Guardar preferencias?"; /* No comment provided by engineer. */ @@ -3757,15 +4054,15 @@ /* No comment provided by engineer. */ "Save servers" = "Guardar servidores"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "¿Guardar servidores?"; -/* No comment provided by engineer. */ -"Save settings?" = "¿Guardar configuración?"; - /* No comment provided by engineer. */ "Save welcome message?" = "¿Guardar mensaje de bienvenida?"; +/* alert title */ +"Save your profile?" = "¿Guardar tu perfil?"; + /* No comment provided by engineer. */ "saved" = "guardado"; @@ -3784,6 +4081,9 @@ /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Los servidores WebRTC ICE guardados serán eliminados"; +/* No comment provided by engineer. */ +"Saving %lld messages" = "Guardando %lld mensajes"; + /* No comment provided by engineer. */ "Scale" = "Escala"; @@ -3847,6 +4147,9 @@ /* chat item action */ "Select" = "Seleccionar"; +/* No comment provided by engineer. */ +"Select chat profile" = "Selecciona perfil de chat"; + /* No comment provided by engineer. */ "Selected %lld" = "Seleccionados %lld"; @@ -3878,7 +4181,7 @@ "send direct message" = "Enviar mensaje directo"; /* No comment provided by engineer. */ -"Send direct message to connect" = "Envia un mensaje para conectar"; +"Send direct message to connect" = "Envía un mensaje para conectar"; /* No comment provided by engineer. */ "Send disappearing message" = "Enviar mensaje temporal"; @@ -3904,9 +4207,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Enviar notificaciones"; -/* No comment provided by engineer. */ -"Send notifications:" = "Enviar notificaciones:"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Consultas y sugerencias"; @@ -3917,9 +4217,9 @@ "Send them from gallery or custom keyboards." = "Envíalos desde la galería o desde teclados personalizados."; /* No comment provided by engineer. */ -"Send up to 100 last messages to new members." = "Enviar hasta 100 últimos mensajes a los miembros nuevos."; +"Send up to 100 last messages to new members." = "Se envían hasta 100 mensajes más recientes a los miembros nuevos."; -/* No comment provided by engineer. */ +/* alert message */ "Sender cancelled file transfer." = "El remitente ha cancelado la transferencia de archivos."; /* No comment provided by engineer. */ @@ -3956,7 +4256,7 @@ "Sent at: %@" = "Enviado: %@"; /* No comment provided by engineer. */ -"Sent directly" = "Enviado directamente"; +"Sent directly" = "Directamente"; /* notification */ "Sent file event" = "Evento de archivo enviado"; @@ -3977,7 +4277,13 @@ "Sent total" = "Total enviados"; /* No comment provided by engineer. */ -"Sent via proxy" = "Enviado vía proxy"; +"Sent via proxy" = "Mediante proxy"; + +/* No comment provided by engineer. */ +"Server" = "Servidor"; + +/* alert message */ +"Server added to operator %@." = "Servidor añadido al operador %@."; /* No comment provided by engineer. */ "Server address" = "Dirección del servidor"; @@ -3988,6 +4294,15 @@ /* srv error text. */ "Server address is incompatible with network settings." = "La dirección del servidor es incompatible con la configuración de la red."; +/* alert title */ +"Server operator changed." = "El operador del servidor ha cambiado."; + +/* No comment provided by engineer. */ +"Server operators" = "Operadores de servidores"; + +/* alert title */ +"Server protocol changed." = "El protocolo del servidor ha cambiado."; + /* queue info */ "server queue info: %@\n\nlast received msg: %@" = "información cola del servidor: %1$@\n\núltimo mensaje recibido: %2$@"; @@ -3998,7 +4313,7 @@ "Server requires authorization to upload, check password" = "El servidor requiere autorización para subir, comprueba la contraseña"; /* No comment provided by engineer. */ -"Server test failed!" = "¡Error en prueba del servidor!"; +"Server test failed!" = "¡Prueba no superada!"; /* No comment provided by engineer. */ "Server type" = "Tipo de servidor"; @@ -4040,7 +4355,7 @@ "set new contact address" = "nueva dirección de contacto"; /* profile update event chat item */ -"set new profile picture" = "nueva imagen de perfil"; +"set new profile picture" = "tiene nueva imagen del perfil"; /* No comment provided by engineer. */ "Set passcode" = "Código autodestrucción"; @@ -4060,19 +4375,29 @@ /* No comment provided by engineer. */ "Settings" = "Configuración"; +/* alert message */ +"Settings were changed." = "La configuración ha sido modificada."; + /* No comment provided by engineer. */ "Shape profile images" = "Dar forma a las imágenes de perfil"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Compartir"; /* No comment provided by engineer. */ "Share 1-time link" = "Compartir enlace de un uso"; +/* No comment provided by engineer. */ +"Share 1-time link with a friend" = "Compartir enlace de un uso con un amigo"; + /* No comment provided by engineer. */ "Share address" = "Compartir dirección"; /* No comment provided by engineer. */ +"Share address publicly" = "Campartir dirección públicamente"; + +/* alert title */ "Share address with contacts?" = "¿Compartir la dirección con los contactos?"; /* No comment provided by engineer. */ @@ -4081,6 +4406,12 @@ /* No comment provided by engineer. */ "Share link" = "Compartir enlace"; +/* No comment provided by engineer. */ +"Share profile" = "Comparte perfil"; + +/* No comment provided by engineer. */ +"Share SimpleX address on social media." = "Comparte tu dirección SimpleX en redes sociales."; + /* No comment provided by engineer. */ "Share this 1-time invite link" = "Comparte este enlace de un solo uso"; @@ -4126,6 +4457,15 @@ /* No comment provided by engineer. */ "SimpleX Address" = "Dirección SimpleX"; +/* No comment provided by engineer. */ +"SimpleX address and 1-time links are safe to share via any messenger." = "Compartir los enlaces de un uso y las direcciones SimpleX es seguro a través de cualquier medio."; + +/* No comment provided by engineer. */ +"SimpleX address or 1-time link?" = "¿Dirección SimpleX o enlace de un uso?"; + +/* No comment provided by engineer. */ +"SimpleX Chat and Flux made an agreement to include Flux-operated servers into the app." = "Simplex Chat y Flux han acordado incluir servidores operados por Flux en la aplicación"; + /* No comment provided by engineer. */ "SimpleX Chat security was audited by Trail of Bits." = "La seguridad de SimpleX Chat ha sido auditada por Trail of Bits."; @@ -4142,7 +4482,7 @@ "SimpleX links" = "Enlaces SimpleX"; /* No comment provided by engineer. */ -"SimpleX links are prohibited in this group." = "Los enlaces SimpleX no se permiten en este grupo."; +"SimpleX links are prohibited." = "Los enlaces SimpleX no se permiten en este grupo."; /* No comment provided by engineer. */ "SimpleX links not allowed" = "Enlaces SimpleX no permitidos"; @@ -4162,6 +4502,9 @@ /* simplex link type */ "SimpleX one-time invitation" = "Invitación SimpleX de un uso"; +/* No comment provided by engineer. */ +"SimpleX protocols reviewed by Trail of Bits." = "Protocolos de SimpleX auditados por Trail of Bits."; + /* No comment provided by engineer. */ "Simplified incognito mode" = "Modo incógnito simplificado"; @@ -4180,9 +4523,15 @@ /* No comment provided by engineer. */ "SMP server" = "Servidor SMP"; +/* No comment provided by engineer. */ +"SOCKS proxy" = "Proxy SOCKS"; + /* blur media */ "Soft" = "Suave"; +/* No comment provided by engineer. */ +"Some app settings were not migrated." = "Algunas configuraciones de la app no han sido migradas."; + /* No comment provided by engineer. */ "Some file(s) were not exported:" = "Algunos archivos no han sido exportados:"; @@ -4192,6 +4541,9 @@ /* No comment provided by engineer. */ "Some non-fatal errors occurred during import:" = "Han ocurrido algunos errores no críticos durante la importación:"; +/* alert message */ +"Some servers failed the test:\n%@" = "Algunos servidores no han superado la prueba:\n%@"; + /* notification title */ "Somebody" = "Alguien"; @@ -4225,9 +4577,6 @@ /* No comment provided by engineer. */ "Stop chat" = "Parar SimpleX"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Para habilitar las acciones sobre la base de datos, debes parar SimpleX"; - /* 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." = "Para poder exportar, importar o eliminar la base de datos primero debes parar SimpleX. Mientras tanto no podrás recibir ni enviar mensajes."; @@ -4243,10 +4592,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "¿Dejar de enviar el archivo?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Dejar de compartir"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "¿Dejar de compartir la dirección?"; /* authentication reason */ @@ -4276,18 +4625,30 @@ /* No comment provided by engineer. */ "Support SimpleX Chat" = "Soporte SimpleX Chat"; +/* No comment provided by engineer. */ +"Switch audio and video during the call." = "Intercambia audio y video durante la llamada."; + +/* No comment provided by engineer. */ +"Switch chat profile for 1-time invitations." = "Cambia el perfil de chat para invitaciones de un solo uso."; + /* No comment provided by engineer. */ "System" = "Sistema"; /* No comment provided by engineer. */ "System authentication" = "Autenticación del sistema"; +/* No comment provided by engineer. */ +"Tail" = "Cola"; + /* No comment provided by engineer. */ "Take picture" = "Tomar foto"; /* No comment provided by engineer. */ "Tap button " = "Pulsa el botón "; +/* No comment provided by engineer. */ +"Tap Create SimpleX address in the menu to create it later." = "Pulsa Crear dirección SimpleX en el menú para crearla más tarde."; + /* No comment provided by engineer. */ "Tap to activate profile." = "Pulsa sobre un perfil para activarlo."; @@ -4325,7 +4686,7 @@ "Temporary file error" = "Error en archivo temporal"; /* server test failure */ -"Test failed at step %@." = "La prueba ha fallado en el paso %@."; +"Test failed at step %@." = "Prueba no superada en el paso %@."; /* No comment provided by engineer. */ "Test server" = "Probar servidor"; @@ -4333,8 +4694,8 @@ /* No comment provided by engineer. */ "Test servers" = "Probar servidores"; -/* No comment provided by engineer. */ -"Tests failed!" = "¡Pruebas fallidas!"; +/* alert title */ +"Tests failed!" = "¡Pruebas no superadas!"; /* No comment provided by engineer. */ "Thank you for installing SimpleX Chat!" = "¡Gracias por instalar SimpleX Chat!"; @@ -4345,14 +4706,14 @@ /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "¡Nuestro agradecimiento a todos los colaboradores! Puedes contribuir a través de Weblate"; -/* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "La primera plataforma sin identificadores de usuario: diseñada para la privacidad."; - /* No comment provided by engineer. */ "The app can notify you when you receive messages or contact requests - please open settings to enable." = "La aplicación puede notificarte cuando recibas mensajes o solicitudes de contacto: por favor, abre la configuración para activarlo."; /* No comment provided by engineer. */ -"The app will ask to confirm downloads from unknown file servers (except .onion)." = "La aplicación pedirá que confirmes las descargas desde servidores de archivos desconocidos (excepto .onion)."; +"The app protects your privacy by using different operators in each conversation." = "La aplicación protege tu privacidad mediante el uso de diferentes operadores en cada conversación."; + +/* No comment provided by engineer. */ +"The app will ask to confirm downloads from unknown file servers (except .onion)." = "La aplicación pedirá que confirmes las descargas desde servidores de archivos desconocidos (excepto si son .onion)."; /* 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."; @@ -4360,6 +4721,9 @@ /* 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 reached the limit of undelivered messages, your contact may be offline." = "La conexión ha alcanzado el límite de mensajes no entregados. es posible que tu contacto esté desconectado."; + /* No comment provided by engineer. */ "The connection you accepted will be cancelled!" = "¡La conexión que has aceptado se cancelará!"; @@ -4372,6 +4736,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "El cifrado funciona y un cifrado nuevo no es necesario. ¡Podría dar lugar a errores de conexión!"; +/* No comment provided by engineer. */ +"The future of messaging" = "La nueva generación de mensajería privada"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "El hash del mensaje anterior es diferente."; @@ -4390,15 +4757,21 @@ /* No comment provided by engineer. */ "The messages will be marked as moderated for all members." = "Los mensajes serán marcados como moderados para todos los miembros."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "La nueva generación de mensajería privada"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "La base de datos antigua no se eliminó durante la migración, puede eliminarse."; /* No comment provided by engineer. */ "The profile is only shared with your contacts." = "El perfil sólo se comparte con tus contactos."; +/* No comment provided by engineer. */ +"The same conditions will apply to operator **%@**." = "Las mismas condiciones se aplicarán al operador **%@**."; + +/* No comment provided by engineer. */ +"The same conditions will apply to operator(s): **%@**." = "Las mismas condiciones se aplicarán a el/los operador(es) **%@**."; + +/* No comment provided by engineer. */ +"The second preset operator in the app!" = "¡Segundo operador predefinido!"; + /* No comment provided by engineer. */ "The second tick we missed! ✅" = "¡El doble check que nos faltaba! ✅"; @@ -4406,14 +4779,23 @@ "The sender will NOT be notified" = "El remitente NO será notificado"; /* 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 **%@**."; +"The servers for new connections of your current chat profile **%@**." = "Lista de servidores para las conexiones nuevas del perfil **%@**."; + +/* No comment provided by engineer. */ +"The servers for new files of your current chat profile **%@**." = "Los servidores para archivos nuevos en 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. */ +"The uploaded database archive will be permanently removed from the servers." = "El archivo de bases de datos subido será eliminado permanentemente de los servidores."; + /* No comment provided by engineer. */ "Themes" = "Temas"; +/* No comment provided by engineer. */ +"These conditions will also apply for: **%@**." = "Estas condiciones también se aplican para: **%@**."; + /* No comment provided by engineer. */ "These settings are for your current profile **%@**." = "Esta configuración afecta a tu perfil actual **%@**."; @@ -4478,7 +4860,7 @@ "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 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."; +"To protect against your link being replaced, you can compare contact security codes." = "Para protegerte contra una sustitución del enlace, puedes comparar los códigos de seguridad con tu contacto."; /* 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."; @@ -4489,15 +4871,33 @@ /* No comment provided by engineer. */ "To protect your IP address, private routing uses your SMP servers to deliver messages." = "Para proteger tu dirección IP, el enrutamiento privado usa tu lista de servidores SMP para enviar mensajes."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs 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 receive" = "Para recibir"; + +/* No comment provided by engineer. */ +"To record speech please grant permission to use Microphone." = "Para grabación de voz, por favor concede el permiso para usar el micrófono."; + +/* No comment provided by engineer. */ +"To record video please grant permission to use Camera." = "Para grabación de vídeo, por favor concede el permiso para usar la cámara."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "Para grabar el mensaje de voz concede permiso para usar el micrófono."; /* No comment provided by engineer. */ "To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." = "Para hacer visible tu perfil oculto, introduce la contraseña en el campo de búsqueda del menú **Mis perfiles**."; +/* No comment provided by engineer. */ +"To send" = "Para enviar"; + /* No comment provided by engineer. */ "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 use the servers of **%@**, accept conditions of use." = "Para usar los servidores de **%@**, acepta las condiciones de uso."; + /* No comment provided by engineer. */ "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."; @@ -4555,6 +4955,9 @@ /* rcv group event chat item */ "unblocked %@" = "ha desbloqueado a %@"; +/* No comment provided by engineer. */ +"Undelivered messages" = "Mensajes no entregados"; + /* No comment provided by engineer. */ "Unexpected migration state" = "Estado de migración inesperado"; @@ -4588,7 +4991,7 @@ /* No comment provided by engineer. */ "unknown servers" = "con servidores desconocidos"; -/* No comment provided by engineer. */ +/* alert title */ "Unknown servers!" = "¡Servidores desconocidos!"; /* No comment provided by engineer. */ @@ -4672,12 +5075,21 @@ /* No comment provided by engineer. */ "Use .onion hosts" = "Usar hosts .onion"; +/* No comment provided by engineer. */ +"Use %@" = "Usar %@"; + /* No comment provided by engineer. */ "Use chat" = "Usar Chat"; /* No comment provided by engineer. */ "Use current profile" = "Usar perfil actual"; +/* No comment provided by engineer. */ +"Use for files" = "Usar para archivos"; + +/* No comment provided by engineer. */ +"Use for messages" = "Usar para mensajes"; + /* No comment provided by engineer. */ "Use for new connections" = "Usar para conexiones nuevas"; @@ -4702,21 +5114,27 @@ /* No comment provided by engineer. */ "Use server" = "Usar servidor"; +/* No comment provided by engineer. */ +"Use servers" = "Usar servidores"; + /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "¿Usar servidores SimpleX Chat?"; +/* No comment provided by engineer. */ +"Use SOCKS proxy" = "Usar proxy SOCKS"; + /* No comment provided by engineer. */ "Use the app while in the call." = "Usar la aplicación durante la llamada."; /* No comment provided by engineer. */ -"Use the app with one hand." = "Usa la aplicación con una mano."; - -/* No comment provided by engineer. */ -"User profile" = "Perfil de usuario"; +"Use the app with one hand." = "Usa la aplicación con una sola mano."; /* No comment provided by engineer. */ "User selection" = "Selección de usuarios"; +/* No comment provided by engineer. */ +"Username" = "Nombre de usuario"; + /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Usar servidores SimpleX Chat."; @@ -4783,9 +5201,15 @@ /* No comment provided by engineer. */ "Videos and files up to 1gb" = "Vídeos y archivos de hasta 1Gb"; +/* No comment provided by engineer. */ +"View conditions" = "Ver condiciones"; + /* No comment provided by engineer. */ "View security code" = "Mostrar código de seguridad"; +/* No comment provided by engineer. */ +"View updated conditions" = "Ver condiciones actualizadas"; + /* chat feature */ "Visible history" = "Historial visible"; @@ -4799,7 +5223,7 @@ "Voice messages are prohibited in this chat." = "Los mensajes de voz no están permitidos en este chat."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "Los mensajes de voz no están permitidos en este grupo."; +"Voice messages are prohibited." = "Los mensajes de voz no están permitidos en este grupo."; /* No comment provided by engineer. */ "Voice messages not allowed" = "Mensajes de voz no permitidos"; @@ -4868,7 +5292,7 @@ "when IP hidden" = "con IP oculta"; /* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Cuando alguien solicite conectarse podrás aceptar o rechazar la solicitud."; +"When more than one operator is enabled, none of them has metadata to learn who communicates with whom." = "Cuando está habilitado más de un operador, ninguno dispone de los metadatos para conocer quién se comunica con quién."; /* 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." = "Cuando compartes un perfil incógnito con alguien, este perfil también se usará para los grupos a los que te inviten."; @@ -4894,7 +5318,7 @@ /* No comment provided by engineer. */ "Without Tor or VPN, your IP address will be visible to file servers." = "Sin Tor o VPN, tu dirección IP será visible para los servidores de archivos."; -/* No comment provided by engineer. */ +/* alert message */ "Without Tor or VPN, your IP address will be visible to these XFTP relays: %@." = "Sin Tor o VPN, tu dirección IP será visible para estos servidores XFTP: %@."; /* No comment provided by engineer. */ @@ -4918,9 +5342,6 @@ /* No comment provided by engineer. */ "you" = "tu"; -/* No comment provided by engineer. */ -"You" = "Tú"; - /* No comment provided by engineer. */ "You **must not** use the same database on two devices." = "**No debes** usar la misma base de datos en dos dispositivos."; @@ -4934,7 +5355,10 @@ "You already have a chat profile with the same display name. Please choose another name." = "Ya tienes un perfil con este nombre mostrado. Por favor, elige otro nombre."; /* No comment provided by engineer. */ -"You are already connected to %@." = "Ya estás conectado a %@."; +"You are already connected to %@." = "Ya estás conectado con %@."; + +/* No comment provided by engineer. */ +"You are already connected with %@." = "Ya estás conectado con %@."; /* No comment provided by engineer. */ "You are already connecting to %@." = "Ya estás conectando con %@."; @@ -4979,7 +5403,13 @@ "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 change it in Appearance settings." = "Puede cambiarlo desde el menú Apariencia."; +"You can change it in Appearance settings." = "Puedes cambiar la posición de la barra desde el menú Apariencia."; + +/* No comment provided by engineer. */ +"You can configure operators in Network & servers settings." = "Puedes configurar los operadores desde Servidores y Redes."; + +/* No comment provided by engineer. */ +"You can configure servers via settings." = "Puedes configurar los servidores a través de su configuración."; /* No comment provided by engineer. */ "You can create it later" = "Puedes crearla más tarde"; @@ -5005,6 +5435,9 @@ /* No comment provided by engineer. */ "You can send messages to %@ from Archived contacts." = "Puedes enviar mensajes a %@ desde Contactos archivados."; +/* No comment provided by engineer. */ +"You can set connection name, to remember who the link was shared with." = "Puedes añadir un nombre a la conexión para recordar a quién corresponde."; + /* No comment provided by engineer. */ "You can set lock screen notification preview via settings." = "Puedes configurar las notificaciones de la pantalla de bloqueo desde Configuración."; @@ -5014,9 +5447,6 @@ /* 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 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"; @@ -5029,7 +5459,7 @@ /* 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. */ +/* alert message */ "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. */ @@ -5048,10 +5478,10 @@ "you changed role of %@ to %@" = "has cambiado el rol de %1$@ a %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." = "Tú controlas a través de qué servidor(es) **recibes** los mensajes. Tus contactos controlan a través de qué servidor(es) **envías** tus mensajes."; +"You could not be verified; please try again." = "No has podido ser autenticado. Inténtalo de nuevo."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "No has podido ser autenticado. Inténtalo de nuevo."; +"You decide who can connect." = "Tu decides quién se conecta."; /* No comment provided by engineer. */ "You have already requested connection via this address!" = "¡Ya has solicitado la conexión mediante esta dirección!"; @@ -5128,6 +5558,9 @@ /* 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."; +/* No comment provided by engineer. */ +"You will stop receiving messages from this chat. Chat history will be preserved." = "Dejarás de recibir mensajes de este chat. El historial del chat se conserva."; + /* No comment provided by engineer. */ "You will stop receiving messages from this group. Chat history will be preserved." = "Dejarás de recibir mensajes de este grupo. El historial del chat se conservará."; @@ -5143,9 +5576,6 @@ /* 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 en este grupo. Para evitar descubrir tu perfil principal no se permite invitar contactos"; -/* No comment provided by engineer. */ -"Your %@ servers" = "Mis servidores %@"; - /* No comment provided by engineer. */ "Your calls" = "Llamadas"; @@ -5155,9 +5585,15 @@ /* No comment provided by engineer. */ "Your chat database is not encrypted - set passphrase to encrypt it." = "La base de datos no está cifrada - establece una contraseña para cifrarla."; +/* alert title */ +"Your chat preferences" = "Tus preferencias de chat"; + /* No comment provided by engineer. */ "Your chat profiles" = "Mis perfiles"; +/* No comment provided by engineer. */ +"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Tu conexión ha sido trasladada a %@ pero ha ocurrido un error inesperado al redirigirte al perfil."; + /* No comment provided by engineer. */ "Your contact sent a file that is larger than currently supported maximum size (%@)." = "El contacto ha enviado un archivo mayor al máximo admitido (%@)."; @@ -5167,6 +5603,9 @@ /* No comment provided by engineer. */ "Your contacts will remain connected." = "Tus contactos permanecerán conectados."; +/* No comment provided by engineer. */ +"Your credentials may be sent unencrypted." = "Tus credenciales podrían ser enviadas sin cifrar."; + /* No comment provided by engineer. */ "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."; @@ -5189,7 +5628,10 @@ "Your profile **%@** will be shared." = "El perfil **%@** será compartido."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos.\nLos servidores SimpleX no pueden ver tu perfil."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Tu perfil es almacenado en tu dispositivo y solamente se comparte con tus contactos. Los servidores SimpleX no pueden ver tu perfil."; + +/* alert message */ +"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Tu perfil ha sido modificado. Si lo guardas la actualización será enviada a todos tus contactos."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes se almacenan en tu dispositivo."; @@ -5198,10 +5640,10 @@ "Your random profile" = "Tu perfil aleatorio"; /* No comment provided by engineer. */ -"Your server" = "Tu servidor"; +"Your server address" = "Dirección del servidor"; /* No comment provided by engineer. */ -"Your server address" = "Dirección de tu servidor"; +"Your servers" = "Tus servidores"; /* No comment provided by engineer. */ "Your settings" = "Configuración"; @@ -5212,6 +5654,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "Servidores SMP"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "Servidores XFTP"; - diff --git a/apps/ios/fi.lproj/Localizable.strings b/apps/ios/fi.lproj/Localizable.strings index a7820e69b1..f0987f3e1b 100644 --- a/apps/ios/fi.lproj/Localizable.strings +++ b/apps/ios/fi.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -52,9 +43,6 @@ /* No comment provided by engineer. */ "[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Tähti GitHubissa](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." = "**Lisää uusi kontakti**: luo kertakäyttöinen QR-koodi tai linkki kontaktille."; - /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e-salattu** äänipuhelu"; @@ -62,16 +50,16 @@ "**e2e encrypted** video call" = "**e2e-salattu** videopuhelu"; /* 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." = "**Yksityisempi**: tarkista uudet viestit 20 minuutin välein. Laitetunnus jaetaan SimpleX Chat -palvelimen kanssa, mutta ei sitä, kuinka monta yhteystietoa tai viestiä sinulla on."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Yksityisempi**: tarkista uudet viestit 20 minuutin välein. Laitetunnus jaetaan SimpleX Chat -palvelimen kanssa, mutta ei sitä, kuinka monta yhteystietoa tai viestiä sinulla on."; /* 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)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. */ "**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."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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. */ "**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Varoitus**: Välittömät push-ilmoitukset vaativat tunnuslauseen, joka on tallennettu Keychainiin."; @@ -265,12 +253,6 @@ /* No comment provided by engineer. */ "Abort changing address?" = "Keskeytä osoitteenvaihto?"; -/* No comment provided by engineer. */ -"About SimpleX" = "Tietoja SimpleX:stä"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "Tietoja SimpleX osoitteesta"; - /* No comment provided by engineer. */ "About SimpleX Chat" = "Tietoja SimpleX Chatistä"; @@ -298,9 +280,6 @@ /* 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." = "Lisää osoite profiiliisi, jotta kontaktisi voivat jakaa sen muiden kanssa. Profiilipäivitys lähetetään kontakteillesi."; -/* No comment provided by engineer. */ -"Add preset servers" = "Lisää esiasetettuja palvelimia"; - /* No comment provided by engineer. */ "Add profile" = "Lisää profiili"; @@ -427,6 +406,9 @@ /* No comment provided by engineer. */ "Answer call" = "Vastaa puheluun"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "Avoimen lähdekoodin protokolla ja koodi - kuka tahansa voi käyttää palvelimia."; + /* No comment provided by engineer. */ "App build: %@" = "Sovellusversio: %@"; @@ -547,7 +529,8 @@ /* No comment provided by engineer. */ "Can't invite contacts!" = "Kontakteja ei voi kutsua!"; -/* No comment provided by engineer. */ +/* alert action + alert button */ "Cancel" = "Peruuta"; /* feature offered item */ @@ -556,7 +539,7 @@ /* No comment provided by engineer. */ "Cannot access keychain to save database password" = "Ei pääsyä avainnippuun tietokannan salasanan tallentamiseksi"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "Tiedostoa ei voi vastaanottaa"; /* No comment provided by engineer. */ @@ -605,9 +588,6 @@ /* chat item text */ "changing address…" = "muuttamassa osoitetta…"; -/* No comment provided by engineer. */ -"Chat archive" = "Chat-arkisto"; - /* No comment provided by engineer. */ "Chat console" = "Chat-konsoli"; @@ -630,9 +610,12 @@ "Chat preferences" = "Chat-asetukset"; /* No comment provided by engineer. */ -"Chats" = "Keskustelut"; +"Chat profile" = "Käyttäjäprofiili"; /* No comment provided by engineer. */ +"Chats" = "Keskustelut"; + +/* alert title */ "Check server address and try again." = "Tarkista palvelimen osoite ja yritä uudelleen."; /* No comment provided by engineer. */ @@ -728,7 +711,7 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Yhteyden muodostaminen palvelimeen... (virhe: %@)"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "yhdistää…"; /* No comment provided by engineer. */ @@ -794,9 +777,6 @@ /* No comment provided by engineer. */ "Create" = "Luo"; -/* No comment provided by engineer. */ -"Create an address to let people connect with you." = "Luo osoite, jolla ihmiset voivat ottaa sinuun yhteyttä."; - /* server test step */ "Create file" = "Luo tiedosto"; @@ -821,9 +801,6 @@ /* No comment provided by engineer. */ "Create your profile" = "Luo profiilisi"; -/* No comment provided by engineer. */ -"Created on %@" = "Luotu %@"; - /* No comment provided by engineer. */ "creator" = "luoja"; @@ -920,7 +897,8 @@ /* No comment provided by engineer. */ "default (yes)" = "oletusarvo (kyllä)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Poista"; @@ -936,12 +914,6 @@ /* No comment provided by engineer. */ "Delete all files" = "Poista kaikki tiedostot"; -/* No comment provided by engineer. */ -"Delete archive" = "Poista arkisto"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "Poista keskusteluarkisto?"; - /* No comment provided by engineer. */ "Delete chat profile" = "Poista keskusteluprofiili"; @@ -1069,7 +1041,7 @@ "Direct messages" = "Yksityisviestit"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Yksityisviestit jäsenten välillä ovat kiellettyjä tässä ryhmässä."; +"Direct messages between members are prohibited." = "Yksityisviestit jäsenten välillä ovat kiellettyjä tässä ryhmässä."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Poista käytöstä (pidä ohitukset)"; @@ -1093,7 +1065,7 @@ "Disappearing messages are prohibited in this chat." = "Katoavat viestit ovat kiellettyjä tässä keskustelussa."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "Katoavat viestit ovat kiellettyjä tässä ryhmässä."; +"Disappearing messages are prohibited." = "Katoavat viestit ovat kiellettyjä tässä ryhmässä."; /* No comment provided by engineer. */ "Disappears at" = "Katoaa klo"; @@ -1284,9 +1256,6 @@ /* No comment provided by engineer. */ "Error accepting contact request" = "Virhe kontaktipyynnön hyväksymisessä"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Virhe tietokantatiedoston käyttämisessä"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Virhe lisättäessä jäseniä"; @@ -1353,18 +1322,12 @@ /* No comment provided by engineer. */ "Error joining group" = "Virhe ryhmään liittymisessä"; -/* No comment provided by engineer. */ -"Error loading %@ servers" = "Virhe %@-palvelimien lataamisessa"; - -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Virhe tiedoston vastaanottamisessa"; /* No comment provided by engineer. */ "Error removing member" = "Virhe poistettaessa jäsentä"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Virhe %@ palvelimien tallentamisessa"; - /* No comment provided by engineer. */ "Error saving group profile" = "Virhe ryhmäprofiilin tallentamisessa"; @@ -1395,7 +1358,7 @@ /* No comment provided by engineer. */ "Error stopping chat" = "Virhe keskustelun lopettamisessa"; -/* No comment provided by engineer. */ +/* alertTitle */ "Error switching profile!" = "Virhe profiilin vaihdossa!"; /* No comment provided by engineer. */ @@ -1416,8 +1379,7 @@ /* No comment provided by engineer. */ "Error: " = "Virhe: "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Virhe: %@"; /* No comment provided by engineer. */ @@ -1475,7 +1437,7 @@ "Files and media" = "Tiedostot ja media"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "Tiedostot ja media ovat tässä ryhmässä kiellettyjä."; +"Files and media are prohibited." = "Tiedostot ja media ovat tässä ryhmässä kiellettyjä."; /* No comment provided by engineer. */ "Files and media prohibited!" = "Tiedostot ja media kielletty!"; @@ -1519,9 +1481,6 @@ /* No comment provided by engineer. */ "Full name (optional)" = "Koko nimi (valinnainen)"; -/* No comment provided by engineer. */ -"Full name:" = "Koko nimi:"; - /* No comment provided by engineer. */ "Fully re-implemented - work in background!" = "Täysin uudistettu - toimii taustalla!"; @@ -1561,24 +1520,6 @@ /* No comment provided by engineer. */ "Group links" = "Ryhmälinkit"; -/* No comment provided by engineer. */ -"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. (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ä."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Ryhmän jäsenet voivat lähettää katoavia viestejä."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Ryhmän jäsenet voivat lähettää tiedostoja ja mediaa."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Ryhmän jäsenet voivat lähettää ääniviestejä."; - /* notification */ "Group message:" = "Ryhmäviesti:"; @@ -1636,9 +1577,6 @@ /* time unit */ "hours" = "tuntia"; -/* No comment provided by engineer. */ -"How it works" = "Kuinka se toimii"; - /* No comment provided by engineer. */ "How SimpleX works" = "Miten SimpleX toimii"; @@ -1679,7 +1617,7 @@ "Immediately" = "Heti"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Immuuni roskapostille ja väärinkäytöksille"; +"Immune to spam" = "Immuuni roskapostille ja väärinkäytöksille"; /* No comment provided by engineer. */ "Import" = "Tuo"; @@ -1748,10 +1686,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Asenna [SimpleX Chat terminaalille](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "Välittömät push-ilmoitukset ovat piilossa!\n"; +"Instant" = "Heti"; /* No comment provided by engineer. */ -"Instantly" = "Heti"; +"Instant push notifications will be hidden!\n" = "Välittömät push-ilmoitukset ovat piilossa!\n"; /* No comment provided by engineer. */ "Interface" = "Käyttöliittymä"; @@ -1768,7 +1706,7 @@ /* invalid chat item */ "invalid data" = "virheelliset tiedot"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "Virheellinen palvelinosoite!"; /* item status text */ @@ -1814,7 +1752,7 @@ "Irreversible message deletion is prohibited in this chat." = "Viestien peruuttamaton poisto on kielletty tässä keskustelussa."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "Viestien peruuttamaton poisto on kielletty tässä ryhmässä."; +"Irreversible message deletion is prohibited." = "Viestien peruuttamaton poisto on kielletty tässä ryhmässä."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Se mahdollistaa useiden nimettömien yhteyksien muodostamisen yhdessä keskusteluprofiilissa ilman, että niiden välillä on jaettuja tietoja."; @@ -1897,9 +1835,6 @@ /* 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"; @@ -1912,24 +1847,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Lukitustila"; -/* No comment provided by engineer. */ -"Make a private connection" = "Luo yksityinen yhteys"; - /* No comment provided by engineer. */ "Make one message disappear" = "Hävitä yksi viesti"; /* No comment provided by engineer. */ "Make profile private!" = "Tee profiilista yksityinen!"; -/* No comment provided by engineer. */ -"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Varmista, että %@-palvelinosoitteet ovat oikeassa muodossa, että ne on erotettu toisistaan riveittäin ja että ne eivät ole päällekkäisiä (%@)."; - /* No comment provided by engineer. */ "Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Varmista, että WebRTC ICE -palvelinosoitteet ovat oikeassa muodossa, rivieroteltuina ja että ne eivät ole päällekkäisiä."; -/* No comment provided by engineer. */ -"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Monet ihmiset kysyivät: *Jos SimpleX:llä ei ole käyttäjätunnuksia, miten se voi toimittaa viestejä?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Merkitse poistetuksi kaikilta"; @@ -1966,6 +1892,24 @@ /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "Jäsen poistetaan ryhmästä - tätä ei voi perua!"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Ryhmän jäsenet voivat lisätä viestireaktioita."; + +/* No comment provided by engineer. */ +"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. */ +"Members can send direct messages." = "Ryhmän jäsenet voivat lähettää suoraviestejä."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Ryhmän jäsenet voivat lähettää katoavia viestejä."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Ryhmän jäsenet voivat lähettää tiedostoja ja mediaa."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Ryhmän jäsenet voivat lähettää ääniviestejä."; + /* item status text */ "Message delivery error" = "Viestin toimitusvirhe"; @@ -1982,7 +1926,7 @@ "Message reactions are prohibited in this chat." = "Viestireaktiot ovat kiellettyjä tässä keskustelussa."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Viestireaktiot ovat kiellettyjä tässä ryhmässä."; +"Message reactions are prohibited." = "Viestireaktiot ovat kiellettyjä tässä ryhmässä."; /* notification */ "message received" = "viesti vastaanotettu"; @@ -2009,7 +1953,7 @@ "Migration is completed" = "Siirto on valmis"; /* No comment provided by engineer. */ -"Migrations: %@" = "Siirrot: %@"; +"Migrations:" = "Siirrot:"; /* time unit */ "minutes" = "minuuttia"; @@ -2071,9 +2015,6 @@ /* notification */ "New contact:" = "Uusi kontakti:"; -/* No comment provided by engineer. */ -"New database archive" = "Uusi tietokanta-arkisto"; - /* No comment provided by engineer. */ "New display name" = "Uusi näyttönimi"; @@ -2131,12 +2072,18 @@ /* No comment provided by engineer. */ "No permission to record voice message" = "Ei lupaa ääniviestin tallentamiseen"; +/* No comment provided by engineer. */ +"No push server" = "Paikallinen"; + /* No comment provided by engineer. */ "No received or sent files" = "Ei vastaanotettuja tai lähetettyjä tiedostoja"; /* copied message info in history */ "no text" = "ei tekstiä"; +/* No comment provided by engineer. */ +"No user identifiers." = "Ensimmäinen alusta ilman käyttäjätunnisteita – suunniteltu yksityiseksi."; + /* No comment provided by engineer. */ "Notifications" = "Ilmoitukset"; @@ -2163,15 +2110,12 @@ /* feature offered item */ "offered %@: %@" = "tarjottu %1$@: %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ok"; /* No comment provided by engineer. */ "Old database" = "Vanha tietokanta"; -/* No comment provided by engineer. */ -"Old database archive" = "Vanha tietokanta-arkisto"; - /* group pref value */ "on" = "päällä"; @@ -2188,7 +2132,7 @@ "Onion hosts will not be used." = "Onion-isäntiä ei käytetä."; /* No comment provided by engineer. */ -"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Vain asiakaslaitteet tallentavat käyttäjäprofiileja, yhteystietoja, ryhmiä ja viestejä, jotka on lähetetty **kaksinkertaisella päästä päähän -salauksella**."; +"Only client devices store user profiles, contacts, groups, and messages." = "Vain asiakaslaitteet tallentavat käyttäjäprofiileja, yhteystietoja, ryhmiä ja viestejä, jotka on lähetetty **kaksinkertaisella päästä päähän -salauksella**."; /* No comment provided by engineer. */ "Only group owners can change group preferences." = "Vain ryhmän omistajat voivat muuttaa ryhmän asetuksia."; @@ -2238,12 +2182,6 @@ /* No comment provided by engineer. */ "Open Settings" = "Avaa Asetukset"; -/* authentication reason */ -"Open user profiles" = "Avaa käyttäjäprofiilit"; - -/* 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."; - /* member role */ "owner" = "omistaja"; @@ -2272,10 +2210,7 @@ "peer-to-peer" = "vertais"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "Ihmiset voivat ottaa sinuun yhteyttä vain jakamiesi linkkien kautta."; - -/* No comment provided by engineer. */ -"Periodically" = "Ajoittain"; +"Periodic" = "Ajoittain"; /* message decrypt error item */ "Permanent decryption error" = "Pysyvä salauksen purkuvirhe"; @@ -2331,9 +2266,6 @@ /* No comment provided by engineer. */ "Preserve the last message draft, with attachments." = "Säilytä viimeinen viestiluonnos liitteineen."; -/* No comment provided by engineer. */ -"Preset server" = "Esiasetettu palvelin"; - /* No comment provided by engineer. */ "Preset server address" = "Esiasetettu palvelimen osoite"; @@ -2358,7 +2290,7 @@ /* No comment provided by engineer. */ "Profile password" = "Profiilin salasana"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "Profiilipäivitys lähetetään kontakteillesi."; /* No comment provided by engineer. */ @@ -2413,7 +2345,7 @@ "Read more" = "Lue lisää"; /* No comment provided by engineer. */ -"Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." = "Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)."; /* No comment provided by engineer. */ "Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends)." = "Lue lisää [Käyttöoppaasta](https://simplex.chat/docs/guide/readme.html#connect-to-friends)."; @@ -2421,9 +2353,6 @@ /* No comment provided by engineer. */ "Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Lue lisää [GitHub-arkistosta](https://github.com/simplex-chat/simplex-chat#readme)."; -/* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Lue lisää GitHub-tietovarastostamme."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Kuittaukset pois käytöstä"; @@ -2572,13 +2501,14 @@ /* No comment provided by engineer. */ "Run chat" = "Käynnistä chat"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Tallenna"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Tallenna (ja ilmoita kontakteille)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Tallenna ja ilmoita kontaktille"; /* No comment provided by engineer. */ @@ -2587,12 +2517,6 @@ /* No comment provided by engineer. */ "Save and update group profile" = "Tallenna ja päivitä ryhmäprofiili"; -/* No comment provided by engineer. */ -"Save archive" = "Tallenna arkisto"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Tallenna automaattisen hyväksynnän asetukset"; - /* No comment provided by engineer. */ "Save group profile" = "Tallenna ryhmäprofiili"; @@ -2602,7 +2526,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Tallenna tunnuslause Avainnippuun"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "Tallenna asetukset?"; /* No comment provided by engineer. */ @@ -2611,12 +2535,9 @@ /* No comment provided by engineer. */ "Save servers" = "Tallenna palvelimet"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "Tallenna palvelimet?"; -/* No comment provided by engineer. */ -"Save settings?" = "Tallenna asetukset?"; - /* No comment provided by engineer. */ "Save welcome message?" = "Tallenna tervetuloviesti?"; @@ -2695,9 +2616,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Lähetys ilmoitukset"; -/* No comment provided by engineer. */ -"Send notifications:" = "Lähetys ilmoitukset:"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Lähetä kysymyksiä ja ideoita"; @@ -2707,7 +2625,7 @@ /* No comment provided by engineer. */ "Send them from gallery or custom keyboards." = "Lähetä ne galleriasta tai mukautetuista näppäimistöistä."; -/* No comment provided by engineer. */ +/* alert message */ "Sender cancelled file transfer." = "Lähettäjä peruutti tiedoston siirron."; /* No comment provided by engineer. */ @@ -2791,7 +2709,8 @@ /* No comment provided by engineer. */ "Settings" = "Asetukset"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Jaa"; /* No comment provided by engineer. */ @@ -2800,7 +2719,7 @@ /* No comment provided by engineer. */ "Share address" = "Jaa osoite"; -/* No comment provided by engineer. */ +/* alert title */ "Share address with contacts?" = "Jaa osoite kontakteille?"; /* No comment provided by engineer. */ @@ -2887,9 +2806,6 @@ /* No comment provided by engineer. */ "Stop" = "Lopeta"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Pysäytä keskustelu tietokantatoimien mahdollistamiseksi"; - /* 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." = "Pysäytä keskustelut viedäksesi, tuodaksesi tai poistaaksesi keskustelujen tietokannan. Et voi vastaanottaa ja lähettää viestejä, kun keskustelut on pysäytetty."; @@ -2905,10 +2821,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "Lopeta tiedoston lähettäminen?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Lopeta jakaminen"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "Lopeta osoitteen jakaminen?"; /* authentication reason */ @@ -2965,7 +2881,7 @@ /* No comment provided by engineer. */ "Test servers" = "Testipalvelimet"; -/* No comment provided by engineer. */ +/* alert title */ "Tests failed!" = "Testit epäonnistuivat!"; /* No comment provided by engineer. */ @@ -2977,9 +2893,6 @@ /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Kiitokset käyttäjille – osallistu Weblaten kautta!"; -/* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "Ensimmäinen alusta ilman käyttäjätunnisteita – suunniteltu yksityiseksi."; - /* No comment provided by engineer. */ "The app can notify you when you receive messages or contact requests - please open settings to enable." = "Sovellus voi ilmoittaa sinulle, kun saat viestejä tai yhteydenottopyyntöjä - avaa asetukset ottaaksesi ne käyttöön."; @@ -2998,6 +2911,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Salaus toimii ja uutta salaussopimusta ei tarvita. Tämä voi johtaa yhteysvirheisiin!"; +/* No comment provided by engineer. */ +"The future of messaging" = "Seuraavan sukupolven yksityisviestit"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "Edellisen viestin tarkiste on erilainen."; @@ -3010,9 +2926,6 @@ /* No comment provided by engineer. */ "The message will be marked as moderated for all members." = "Viesti merkitään moderoiduksi kaikille jäsenille."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "Seuraavan sukupolven yksityisviestit"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "Vanhaa tietokantaa ei poistettu siirron aikana, se voidaan kuitenkin poistaa."; @@ -3064,15 +2977,15 @@ /* No comment provided by engineer. */ "To make a new connection" = "Uuden yhteyden luominen"; -/* 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." = "Yksityisyyden suojaamiseksi kaikkien muiden alustojen käyttämien käyttäjätunnusten sijaan SimpleX käyttää viestijonojen tunnisteita, jotka ovat kaikille kontakteille erillisiä."; - /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "Aikavyöhykkeen suojaamiseksi kuva-/äänitiedostot käyttävät UTC:tä."; /* 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." = "Suojaa tietosi ottamalla SimpleX Lock käyttöön.\nSinua kehotetaan suorittamaan todennus loppuun, ennen kuin tämä ominaisuus otetaan käyttöön."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "Yksityisyyden suojaamiseksi kaikkien muiden alustojen käyttämien käyttäjätunnusten sijaan SimpleX käyttää viestijonojen tunnisteita, jotka ovat kaikille kontakteille erillisiä."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "Jos haluat nauhoittaa ääniviestin, anna lupa käyttää mikrofonia."; @@ -3196,9 +3109,6 @@ /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "Käytä SimpleX Chat palvelimia?"; -/* No comment provided by engineer. */ -"User profile" = "Käyttäjäprofiili"; - /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Käyttää SimpleX Chat -palvelimia."; @@ -3254,7 +3164,7 @@ "Voice messages are prohibited in this chat." = "Ääniviestit ovat kiellettyjä tässä keskustelussa."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "Ääniviestit ovat kiellettyjä tässä ryhmässä."; +"Voice messages are prohibited." = "Ääniviestit ovat kiellettyjä tässä ryhmässä."; /* No comment provided by engineer. */ "Voice messages prohibited!" = "Ääniviestit kielletty!"; @@ -3298,9 +3208,6 @@ /* No comment provided by engineer. */ "When available" = "Kun saatavilla"; -/* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Kun ihmiset pyytävät yhteyden muodostamista, voit hyväksyä tai hylätä sen."; - /* 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." = "Kun jaat inkognitoprofiilin jonkun kanssa, tätä profiilia käytetään ryhmissä, joihin tämä sinut kutsuu."; @@ -3316,9 +3223,6 @@ /* pref value */ "yes" = "kyllä"; -/* No comment provided by engineer. */ -"You" = "Sinä"; - /* No comment provided by engineer. */ "You accepted connection" = "Hyväksyit yhteyden"; @@ -3370,9 +3274,6 @@ /* No comment provided by engineer. */ "You can share this address with your contacts to let them connect with **%@**." = "Voit jakaa tämän osoitteen kontaktiesi kanssa, jotta ne voivat muodostaa yhteyden **%@** kanssa."; -/* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Voit jakaa osoitteesi linkkinä tai QR-koodina - kuka tahansa voi muodostaa yhteyden sinuun."; - /* No comment provided by engineer. */ "You can start chat via app Settings / Database or by restarting the app" = "Voit aloittaa keskustelun sovelluksen Asetukset / Tietokanta kautta tai käynnistämällä sovelluksen uudelleen"; @@ -3398,10 +3299,10 @@ "you changed role of %@ to %@" = "olet vaihtanut %1$@:n roolin %2$@:ksi"; /* No comment provided by engineer. */ -"You control through which server(s) **to receive** the messages, your contacts – the servers you use to message them." = "Sinä hallitset, minkä palvelim(i)en kautta **viestit vastaanotetaan**, kontaktisi - palvelimet, joita käytät viestien lähettämiseen niille."; +"You could not be verified; please try again." = "Sinua ei voitu todentaa; yritä uudelleen."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "Sinua ei voitu todentaa; yritä uudelleen."; +"You decide who can connect." = "Kimin bağlanabileceğine siz karar verirsiniz."; /* No comment provided by engineer. */ "You have to enter passphrase every time the app starts - it is not stored on the device." = "Sinun on annettava tunnuslause aina, kun sovellus käynnistyy - sitä ei tallenneta laitteeseen."; @@ -3469,9 +3370,6 @@ /* 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" = "Käytät tässä ryhmässä incognito-profiilia. Kontaktien kutsuminen ei ole sallittua, jotta pääprofiilisi ei tule jaetuksi"; -/* No comment provided by engineer. */ -"Your %@ servers" = "%@-palvelimesi"; - /* No comment provided by engineer. */ "Your calls" = "Puhelusi"; @@ -3512,7 +3410,7 @@ "Your profile **%@** will be shared." = "Profiilisi **%@** jaetaan."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa.\nSimpleX-palvelimet eivät näe profiiliasi."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Profiilisi tallennetaan laitteeseesi ja jaetaan vain yhteystietojesi kanssa. SimpleX-palvelimet eivät näe profiiliasi."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Profiilisi, kontaktisi ja toimitetut viestit tallennetaan laitteellesi."; @@ -3520,9 +3418,6 @@ /* No comment provided by engineer. */ "Your random profile" = "Satunnainen profiilisi"; -/* No comment provided by engineer. */ -"Your server" = "Palvelimesi"; - /* No comment provided by engineer. */ "Your server address" = "Palvelimesi osoite"; @@ -3535,6 +3430,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "SMP-palvelimesi"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "XFTP-palvelimesi"; - diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index bfa94e35a4..6b973e75d0 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -65,10 +56,7 @@ "[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."; +"**Create 1-time link**: to create and share a new invitation link." = "**Ajouter un contact** : pour créer un nouveau lien d'invitation."; /* No comment provided by engineer. */ "**Create group**: to create a new group." = "**Créer un groupe** : pour créer un nouveau groupe."; @@ -80,10 +68,10 @@ "**e2e encrypted** video call" = "appel vidéo **chiffré de bout en bout**"; /* 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." = "**Vie privée** : vérification de nouveaux messages toute les 20 minutes. Le token de l'appareil est partagé avec le serveur SimpleX, mais pas le nombre de messages ou de contacts."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Vie privée** : vérification de nouveaux messages toute les 20 minutes. Le token de l'appareil est partagé avec le serveur SimpleX, mais pas le nombre de messages ou de contacts."; /* 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)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending 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. */ "**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Remarque** : l'utilisation de la même base de données sur deux appareils interrompt le déchiffrement des messages provenant de vos connexions, par mesure de sécurité."; @@ -92,7 +80,7 @@ "**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."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see 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. */ "**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."; @@ -160,6 +148,9 @@ /* notification title */ "%@ wants to connect!" = "%@ veut se connecter !"; +/* format for date separator in chat */ +"%@, %@" = "%1$@, %2$@"; + /* No comment provided by engineer. */ "%@, %@ and %lld members" = "%@, %@ et %lld membres"; @@ -172,9 +163,24 @@ /* time interval */ "%d days" = "%d jours"; +/* forward confirmation reason */ +"%d file(s) are still being downloaded." = "%d fichier(s) en cours de téléchargement."; + +/* forward confirmation reason */ +"%d file(s) failed to download." = "Le téléchargement de %d fichier(s) a échoué."; + +/* forward confirmation reason */ +"%d file(s) were deleted." = "Le(s) fichier(s) %d a(ont) été supprimé(s)."; + +/* forward confirmation reason */ +"%d file(s) were not downloaded." = "Le(s) fichier(s) %d n'a (n'ont) pas été téléchargé(s)."; + /* time interval */ "%d hours" = "%d heures"; +/* alert title */ +"%d messages not forwarded" = "%d messages non transférés"; + /* time interval */ "%d min" = "%d min"; @@ -314,7 +320,7 @@ "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." = "Une connexion TCP distincte sera utilisée **pour chaque contact et membre de groupe**.\n**Veuillez noter** : si vous avez de nombreuses connexions, votre consommation de batterie et de réseau peut être nettement plus élevée et certaines liaisons peuvent échouer."; /* No comment provided by engineer. */ -"Abort" = "Annuler"; +"Abort" = "Abandonner"; /* No comment provided by engineer. */ "Abort changing address" = "Annuler le changement d'adresse"; @@ -322,12 +328,6 @@ /* No comment provided by engineer. */ "Abort changing address?" = "Abandonner le changement d'adresse ?"; -/* No comment provided by engineer. */ -"About SimpleX" = "À propos de SimpleX"; - -/* No comment provided by engineer. */ -"About SimpleX address" = "À propos de l'adresse SimpleX"; - /* No comment provided by engineer. */ "About SimpleX Chat" = "À propos de SimpleX Chat"; @@ -367,12 +367,6 @@ /* 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"; - /* No comment provided by engineer. */ "Add profile" = "Ajouter un profil"; @@ -437,7 +431,7 @@ "All data is erased when it is entered." = "Toutes les données sont effacées lorsqu'il est saisi."; /* No comment provided by engineer. */ -"All data is private to your device." = "Toutes les données restent confinées dans votre appareil."; +"All data is kept private on your device." = "Toutes les données restent confinées dans votre appareil."; /* No comment provided by engineer. */ "All group members will remain connected." = "Tous les membres du groupe resteront connectés."; @@ -454,7 +448,7 @@ /* No comment provided by engineer. */ "All new messages from %@ will be hidden!" = "Tous les nouveaux messages de %@ seront cachés !"; -/* No comment provided by engineer. */ +/* profile dropdown */ "All profiles" = "Tous les profiles"; /* No comment provided by engineer. */ @@ -472,6 +466,9 @@ /* No comment provided by engineer. */ "Allow calls only if your contact allows them." = "Autoriser les appels que si votre contact les autorise."; +/* No comment provided by engineer. */ +"Allow calls?" = "Autoriser les appels ?"; + /* No comment provided by engineer. */ "Allow disappearing messages only if your contact allows it to you." = "Autorise les messages éphémères seulement si votre contact vous l’autorise."; @@ -556,6 +553,9 @@ /* No comment provided by engineer. */ "Answer call" = "Répondre à l'appel"; +/* No comment provided by engineer. */ +"Anybody can host servers." = "N'importe qui peut heberger un serveur."; + /* No comment provided by engineer. */ "App build: %@" = "Build de l'app : %@"; @@ -574,6 +574,9 @@ /* No comment provided by engineer. */ "App passcode is replaced with self-destruct passcode." = "Le code d'accès de l'application est remplacé par un code d'autodestruction."; +/* No comment provided by engineer. */ +"App session" = "Session de l'app"; + /* No comment provided by engineer. */ "App version" = "Version de l'app"; @@ -590,7 +593,13 @@ "Apply to" = "Appliquer à"; /* No comment provided by engineer. */ -"Archive and upload" = "Archiver et transférer"; +"Archive and upload" = "Archiver et téléverser"; + +/* No comment provided by engineer. */ +"Archive contacts to chat later." = "Archiver les contacts pour discuter plus tard."; + +/* No comment provided by engineer. */ +"Archived contacts" = "Contacts archivés"; /* No comment provided by engineer. */ "Archiving database" = "Archivage de la base de données"; @@ -640,6 +649,9 @@ /* No comment provided by engineer. */ "Auto-accept images" = "Images auto-acceptées"; +/* alert title */ +"Auto-accept settings" = "Paramètres de réception automatique"; + /* No comment provided by engineer. */ "Back" = "Retour"; @@ -661,12 +673,30 @@ /* No comment provided by engineer. */ "Bad message ID" = "Mauvais ID de message"; +/* No comment provided by engineer. */ +"Better calls" = "Appels améliorés"; + /* No comment provided by engineer. */ "Better groups" = "Des groupes plus performants"; +/* No comment provided by engineer. */ +"Better message dates." = "Meilleures dates de messages."; + /* No comment provided by engineer. */ "Better messages" = "Meilleurs messages"; +/* No comment provided by engineer. */ +"Better networking" = "Meilleure gestion de réseau"; + +/* No comment provided by engineer. */ +"Better notifications" = "Notifications améliorées"; + +/* No comment provided by engineer. */ +"Better security ✅" = "Sécurité accrue ✅"; + +/* No comment provided by engineer. */ +"Better user experience" = "Une meilleure expérience pour l'utilisateur"; + /* No comment provided by engineer. */ "Black" = "Noir"; @@ -700,6 +730,9 @@ /* No comment provided by engineer. */ "Blocked by admin" = "Bloqué par l'administrateur"; +/* No comment provided by engineer. */ +"Blur for better privacy." = "Rendez les images floues et protégez-les contre les regards indiscrets."; + /* No comment provided by engineer. */ "Blur media" = "Flouter les médias"; @@ -727,6 +760,9 @@ /* 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)." = "Par profil de chat (par défaut) ou [par connexion](https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation) (BETA)."; +/* No comment provided by engineer. */ +"call" = "appeler"; + /* No comment provided by engineer. */ "Call already ended!" = "Appel déjà terminé !"; @@ -742,9 +778,18 @@ /* No comment provided by engineer. */ "Calls" = "Appels"; +/* No comment provided by engineer. */ +"Calls prohibited!" = "Les appels ne sont pas autorisés !"; + /* No comment provided by engineer. */ "Camera not available" = "Caméra non disponible"; +/* No comment provided by engineer. */ +"Can't call contact" = "Impossible d'appeler le contact"; + +/* No comment provided by engineer. */ +"Can't call member" = "Impossible d'appeler le membre"; + /* No comment provided by engineer. */ "Can't invite contact!" = "Impossible d'inviter le contact !"; @@ -752,6 +797,10 @@ "Can't invite contacts!" = "Impossible d'inviter les contacts !"; /* No comment provided by engineer. */ +"Can't message member" = "Impossible d'envoyer un message à ce membre"; + +/* alert action + alert button */ "Cancel" = "Annuler"; /* No comment provided by engineer. */ @@ -766,7 +815,7 @@ /* No comment provided by engineer. */ "Cannot forward message" = "Impossible de transférer le message"; -/* No comment provided by engineer. */ +/* alert title */ "Cannot receive file" = "Impossible de recevoir le fichier"; /* snd error text */ @@ -821,9 +870,6 @@ /* chat item text */ "changing address…" = "changement d'adresse…"; -/* No comment provided by engineer. */ -"Chat archive" = "Archives du chat"; - /* No comment provided by engineer. */ "Chat colors" = "Couleurs de chat"; @@ -836,6 +882,9 @@ /* No comment provided by engineer. */ "Chat database deleted" = "Base de données du chat supprimée"; +/* No comment provided by engineer. */ +"Chat database exported" = "Exportation de la base de données des discussions"; + /* No comment provided by engineer. */ "Chat database imported" = "Base de données du chat importée"; @@ -848,19 +897,28 @@ /* 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 list" = "Liste de discussion"; + /* No comment provided by engineer. */ "Chat migrated!" = "Messagerie transférée !"; /* No comment provided by engineer. */ "Chat preferences" = "Préférences de chat"; +/* alert message */ +"Chat preferences were changed." = "Les préférences de discussion ont été modifiées."; + +/* No comment provided by engineer. */ +"Chat profile" = "Profil d'utilisateur"; + /* No comment provided by engineer. */ "Chat theme" = "Thème de chat"; /* No comment provided by engineer. */ "Chats" = "Discussions"; -/* No comment provided by engineer. */ +/* alert title */ "Check server address and try again." = "Vérifiez l'adresse du serveur et réessayez."; /* No comment provided by engineer. */ @@ -899,6 +957,9 @@ /* No comment provided by engineer. */ "Clear verification" = "Retirer la vérification"; +/* No comment provided by engineer. */ +"Color chats with the new themes." = "Colorez vos discussions avec les nouveaux thèmes."; + /* No comment provided by engineer. */ "Color mode" = "Mode de couleur"; @@ -915,16 +976,16 @@ "complete" = "complet"; /* No comment provided by engineer. */ -"Completed" = "Complété"; +"Completed" = "Complétées"; /* No comment provided by engineer. */ "Configure ICE servers" = "Configurer les serveurs ICE"; /* No comment provided by engineer. */ -"Configured %@ servers" = "%@ serveurs configurés"; +"Confirm" = "Confirmer"; /* No comment provided by engineer. */ -"Confirm" = "Confirmer"; +"Confirm contact deletion?" = "Confirmer la suppression du contact ?"; /* No comment provided by engineer. */ "Confirm database upgrades" = "Confirmer la mise à niveau de la base de données"; @@ -965,6 +1026,9 @@ /* No comment provided by engineer. */ "connect to SimpleX Chat developers." = "se connecter aux developpeurs de SimpleX Chat."; +/* No comment provided by engineer. */ +"Connect to your friends faster." = "Connectez-vous à vos amis plus rapidement."; + /* No comment provided by engineer. */ "Connect to yourself?" = "Se connecter à soi-même ?"; @@ -1031,15 +1095,21 @@ /* No comment provided by engineer. */ "Connecting server… (error: %@)" = "Connexion au serveur… (erreur : %@)"; +/* No comment provided by engineer. */ +"Connecting to contact, please wait or check later!" = "Connexion au contact, veuillez patienter ou vérifier plus tard !"; + /* No comment provided by engineer. */ "Connecting to desktop" = "Connexion au bureau"; -/* chat list item title */ +/* No comment provided by engineer. */ "connecting…" = "connexion…"; /* No comment provided by engineer. */ "Connection" = "Connexion"; +/* No comment provided by engineer. */ +"Connection and servers status." = "État de la connexion et des serveurs."; + /* No comment provided by engineer. */ "Connection error" = "Erreur de connexion"; @@ -1079,6 +1149,9 @@ /* No comment provided by engineer. */ "Contact already exists" = "Contact déjà existant"; +/* No comment provided by engineer. */ +"Contact deleted!" = "Contact supprimé !"; + /* No comment provided by engineer. */ "contact has e2e encryption" = "Ce contact a le chiffrement de bout en bout"; @@ -1091,12 +1164,18 @@ /* notification */ "Contact is connected" = "Le contact est connecté"; +/* No comment provided by engineer. */ +"Contact is deleted." = "Le contact est supprimé."; + /* No comment provided by engineer. */ "Contact name" = "Nom du contact"; /* No comment provided by engineer. */ "Contact preferences" = "Préférences de contact"; +/* No comment provided by engineer. */ +"Contact will be deleted - this cannot be undone!" = "Le contact sera supprimé - il n'est pas possible de revenir en arrière !"; + /* No comment provided by engineer. */ "Contacts" = "Contacts"; @@ -1106,6 +1185,9 @@ /* No comment provided by engineer. */ "Continue" = "Continuer"; +/* No comment provided by engineer. */ +"Conversation deleted!" = "Conversation supprimée !"; + /* No comment provided by engineer. */ "Copy" = "Copier"; @@ -1115,6 +1197,9 @@ /* No comment provided by engineer. */ "Core version: v%@" = "Version du cœur : v%@"; +/* No comment provided by engineer. */ +"Corner" = "Coin"; + /* No comment provided by engineer. */ "Correct name to %@?" = "Corriger le nom pour %@ ?"; @@ -1124,9 +1209,6 @@ /* No comment provided by engineer. */ "Create a group using a random profile." = "Création de groupes via un profil aléatoire."; -/* No comment provided by engineer. */ -"Create an address to let people connect with you." = "Vous pouvez créer une adresse pour permettre aux autres utilisateurs de vous contacter."; - /* server test step */ "Create file" = "Créer un fichier"; @@ -1158,7 +1240,7 @@ "Create your profile" = "Créez votre profil"; /* No comment provided by engineer. */ -"Created" = "Créé"; +"Created" = "Créées"; /* No comment provided by engineer. */ "Created at" = "Créé à"; @@ -1166,9 +1248,6 @@ /* copied message info */ "Created at: %@" = "Créé à : %@"; -/* No comment provided by engineer. */ -"Created on %@" = "Créé le %@"; - /* No comment provided by engineer. */ "Creating archive link" = "Création d'un lien d'archive"; @@ -1196,6 +1275,9 @@ /* No comment provided by engineer. */ "Custom time" = "Délai personnalisé"; +/* No comment provided by engineer. */ +"Customizable message shape." = "Forme des messages personnalisable."; + /* No comment provided by engineer. */ "Customize theme" = "Personnaliser le thème"; @@ -1286,7 +1368,8 @@ /* No comment provided by engineer. */ "default (yes)" = "par défaut (oui)"; -/* chat item action +/* alert action + chat item action swipe action */ "Delete" = "Supprimer"; @@ -1311,12 +1394,6 @@ /* No comment provided by engineer. */ "Delete and notify contact" = "Supprimer et en informer le contact"; -/* No comment provided by engineer. */ -"Delete archive" = "Supprimer l'archive"; - -/* No comment provided by engineer. */ -"Delete chat archive?" = "Supprimer l'archive du chat ?"; - /* No comment provided by engineer. */ "Delete chat profile" = "Supprimer le profil de chat"; @@ -1329,6 +1406,9 @@ /* No comment provided by engineer. */ "Delete contact" = "Supprimer le contact"; +/* No comment provided by engineer. */ +"Delete contact?" = "Supprimer le contact ?"; + /* No comment provided by engineer. */ "Delete database" = "Supprimer la base de données"; @@ -1383,6 +1463,9 @@ /* No comment provided by engineer. */ "Delete old database?" = "Supprimer l'ancienne base de données ?"; +/* No comment provided by engineer. */ +"Delete or moderate up to 200 messages." = "Supprimer ou modérer jusqu'à 200 messages."; + /* No comment provided by engineer. */ "Delete pending connection?" = "Supprimer la connexion en attente ?"; @@ -1392,14 +1475,20 @@ /* server test step */ "Delete queue" = "Supprimer la file d'attente"; +/* No comment provided by engineer. */ +"Delete up to 20 messages at once." = "Supprimez jusqu'à 20 messages à la fois."; + /* No comment provided by engineer. */ "Delete user profile?" = "Supprimer le profil utilisateur ?"; +/* No comment provided by engineer. */ +"Delete without notification" = "Supprimer sans notification"; + /* deleted chat item */ "deleted" = "supprimé"; /* No comment provided by engineer. */ -"Deleted" = "Supprimé"; +"Deleted" = "Supprimées"; /* No comment provided by engineer. */ "Deleted at" = "Supprimé à"; @@ -1455,6 +1544,9 @@ /* No comment provided by engineer. */ "Develop" = "Développer"; +/* No comment provided by engineer. */ +"Developer options" = "Options pour les développeurs"; + /* No comment provided by engineer. */ "Developer tools" = "Outils du développeur"; @@ -1480,7 +1572,7 @@ "Direct messages" = "Messages directs"; /* No comment provided by engineer. */ -"Direct messages between members are prohibited in this group." = "Les messages directs entre membres sont interdits dans ce groupe."; +"Direct messages between members are prohibited." = "Les messages directs entre membres sont interdits dans ce groupe."; /* No comment provided by engineer. */ "Disable (keep overrides)" = "Désactiver (conserver les remplacements)"; @@ -1507,7 +1599,7 @@ "Disappearing messages are prohibited in this chat." = "Les messages éphémères sont interdits dans cette discussion."; /* No comment provided by engineer. */ -"Disappearing messages are prohibited in this group." = "Les messages éphémères sont interdits dans ce groupe."; +"Disappearing messages are prohibited." = "Les messages éphémères sont interdits dans ce groupe."; /* No comment provided by engineer. */ "Disappears at" = "Disparaîtra le"; @@ -1536,6 +1628,9 @@ /* No comment provided by engineer. */ "Do NOT send messages directly, even if your or destination server does not support private routing." = "Ne pas envoyer de messages directement, même si votre serveur ou le serveur de destination ne prend pas en charge le routage privé."; +/* No comment provided by engineer. */ +"Do not use credentials with proxy." = "Ne pas utiliser d'identifiants avec le proxy."; + /* No comment provided by engineer. */ "Do NOT use private routing." = "Ne pas utiliser de routage privé."; @@ -1554,7 +1649,8 @@ /* No comment provided by engineer. */ "Downgrade and open chat" = "Rétrograder et ouvrir le chat"; -/* chat item action */ +/* alert button + chat item action */ "Download" = "Télécharger"; /* No comment provided by engineer. */ @@ -1566,6 +1662,9 @@ /* server test step */ "Download file" = "Télécharger le fichier"; +/* alert action */ +"Download files" = "Télécharger les fichiers"; + /* No comment provided by engineer. */ "Downloaded" = "Téléchargé"; @@ -1773,21 +1872,24 @@ /* No comment provided by engineer. */ "Error accepting contact request" = "Erreur de validation de la demande de contact"; -/* No comment provided by engineer. */ -"Error accessing database file" = "Erreur d'accès au fichier de la base de données"; - /* No comment provided by engineer. */ "Error adding member(s)" = "Erreur lors de l'ajout de membre·s"; /* No comment provided by engineer. */ "Error changing address" = "Erreur de changement d'adresse"; +/* No comment provided by engineer. */ +"Error changing connection profile" = "Erreur lors du changement de profil de connexion"; + /* No comment provided by engineer. */ "Error changing role" = "Erreur lors du changement de rôle"; /* No comment provided by engineer. */ "Error changing setting" = "Erreur de changement de paramètre"; +/* No comment provided by engineer. */ +"Error changing to incognito!" = "Erreur lors du passage en mode incognito !"; + /* No comment provided by engineer. */ "Error connecting to forwarding server %@. Please try later." = "Erreur de connexion au serveur de redirection %@. Veuillez réessayer plus tard."; @@ -1858,12 +1960,12 @@ "Error joining group" = "Erreur lors de la liaison avec le groupe"; /* No comment provided by engineer. */ -"Error loading %@ servers" = "Erreur lors du chargement des serveurs %@"; +"Error migrating settings" = "Erreur lors de la migration des paramètres"; /* No comment provided by engineer. */ "Error opening chat" = "Erreur lors de l'ouverture du chat"; -/* No comment provided by engineer. */ +/* alert title */ "Error receiving file" = "Erreur lors de la réception du fichier"; /* No comment provided by engineer. */ @@ -1878,9 +1980,6 @@ /* No comment provided by engineer. */ "Error resetting statistics" = "Erreur de réinitialisation des statistiques"; -/* No comment provided by engineer. */ -"Error saving %@ servers" = "Erreur lors de la sauvegarde des serveurs %@"; - /* No comment provided by engineer. */ "Error saving group profile" = "Erreur lors de la sauvegarde du profil de groupe"; @@ -1921,6 +2020,9 @@ "Error stopping chat" = "Erreur lors de l'arrêt du chat"; /* No comment provided by engineer. */ +"Error switching profile" = "Erreur lors du changement de profil"; + +/* alertTitle */ "Error switching profile!" = "Erreur lors du changement de profil !"; /* No comment provided by engineer. */ @@ -1947,8 +2049,7 @@ /* No comment provided by engineer. */ "Error: " = "Erreur : "; -/* file error text - snd error text */ +/* alert message */ "Error: %@" = "Erreur : %@"; /* No comment provided by engineer. */ @@ -2008,6 +2109,9 @@ /* No comment provided by engineer. */ "File error" = "Erreur de fichier"; +/* alert message */ +"File errors:\n%@" = "Erreurs de fichier :\n%@"; + /* file error text */ "File not found - most likely file was deleted or cancelled." = "Fichier introuvable - le fichier a probablement été supprimé ou annulé."; @@ -2042,7 +2146,7 @@ "Files and media" = "Fichiers et médias"; /* No comment provided by engineer. */ -"Files and media are prohibited in this group." = "Les fichiers et les médias sont interdits dans ce groupe."; +"Files and media are prohibited." = "Les fichiers et les médias sont interdits dans ce groupe."; /* No comment provided by engineer. */ "Files and media not allowed" = "Fichiers et médias non autorisés"; @@ -2089,9 +2193,21 @@ /* chat item action */ "Forward" = "Transférer"; +/* alert title */ +"Forward %d message(s)?" = "Transférer %d message(s) ?"; + /* No comment provided by engineer. */ "Forward and save messages" = "Transférer et sauvegarder des messages"; +/* alert action */ +"Forward messages" = "Transférer les messages"; + +/* alert message */ +"Forward messages without files?" = "Transférer les messages sans les fichiers ?"; + +/* No comment provided by engineer. */ +"Forward up to 20 messages at once." = "Transférez jusqu'à 20 messages à la fois."; + /* No comment provided by engineer. */ "forwarded" = "transféré"; @@ -2101,6 +2217,9 @@ /* No comment provided by engineer. */ "Forwarded from" = "Transféré depuis"; +/* No comment provided by engineer. */ +"Forwarding %lld messages" = "Transfert des %lld messages"; + /* No comment provided by engineer. */ "Forwarding server %@ failed to connect to destination server %@. Please try later." = "Le serveur de redirection %@ n'a pas réussi à se connecter au serveur de destination %@. Veuillez réessayer plus tard."; @@ -2128,9 +2247,6 @@ /* No comment provided by engineer. */ "Full name (optional)" = "Nom complet (optionnel)"; -/* No comment provided by engineer. */ -"Full name:" = "Nom complet :"; - /* No comment provided by engineer. */ "Fully decentralized – visible only to members." = "Entièrement décentralisé – visible que par ses membres."; @@ -2185,27 +2301,6 @@ /* No comment provided by engineer. */ "Group links" = "Liens de groupe"; -/* No comment provided by engineer. */ -"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. (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."; - -/* No comment provided by engineer. */ -"Group members can send disappearing messages." = "Les membres du groupes peuvent envoyer des messages éphémères."; - -/* No comment provided by engineer. */ -"Group members can send files and media." = "Les membres du groupe peuvent envoyer des fichiers et des médias."; - -/* No comment provided by engineer. */ -"Group members can send SimpleX links." = "Les membres du groupe peuvent envoyer des liens SimpleX."; - -/* No comment provided by engineer. */ -"Group members can send voice messages." = "Les membres du groupe peuvent envoyer des messages vocaux."; - /* notification */ "Group message:" = "Message du groupe :"; @@ -2266,9 +2361,6 @@ /* time unit */ "hours" = "heures"; -/* No comment provided by engineer. */ -"How it works" = "Comment ça fonctionne"; - /* No comment provided by engineer. */ "How SimpleX works" = "Comment SimpleX fonctionne"; @@ -2312,7 +2404,7 @@ "Immediately" = "Immédiatement"; /* No comment provided by engineer. */ -"Immune to spam and abuse" = "Protégé du spam et des abus"; +"Immune to spam" = "Protégé du spam et des abus"; /* No comment provided by engineer. */ "Import" = "Importer"; @@ -2332,6 +2424,9 @@ /* No comment provided by engineer. */ "Importing archive" = "Importation de l'archive"; +/* No comment provided by engineer. */ +"Improved delivery, reduced traffic usage.\nMore improvements are coming soon!" = "Amélioration de la distribution, réduction de l'utilisation du trafic.\nD'autres améliorations sont à venir !"; + /* No comment provided by engineer. */ "Improved message delivery" = "Amélioration de la transmission des messages"; @@ -2408,10 +2503,10 @@ "Install [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat)" = "Installer [SimpleX Chat pour terminal](https://github.com/simplex-chat/simplex-chat)"; /* No comment provided by engineer. */ -"Instant push notifications will be hidden!\n" = "Les notifications push instantanées vont être cachées !\n"; +"Instant" = "Instantané"; /* No comment provided by engineer. */ -"Instantly" = "Instantané"; +"Instant push notifications will be hidden!\n" = "Les notifications push instantanées vont être cachées !\n"; /* No comment provided by engineer. */ "Interface" = "Interface"; @@ -2449,7 +2544,7 @@ /* No comment provided by engineer. */ "Invalid response" = "Réponse invalide"; -/* No comment provided by engineer. */ +/* alert title */ "Invalid server address!" = "Adresse de serveur invalide !"; /* item status text */ @@ -2461,6 +2556,9 @@ /* group name */ "invitation to group %@" = "invitation au groupe %@"; +/* No comment provided by engineer. */ +"invite" = "inviter"; + /* No comment provided by engineer. */ "Invite friends" = "Inviter des amis"; @@ -2488,6 +2586,9 @@ /* 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." = "La keychain d'iOS sera utilisée pour stocker en toute sécurité la phrase secrète après le redémarrage de l'app ou la modification de la phrase secrète - il permettra de recevoir les notifications push."; +/* No comment provided by engineer. */ +"IP address" = "Adresse IP"; + /* No comment provided by engineer. */ "Irreversible message deletion" = "Suppression irréversible des messages"; @@ -2495,7 +2596,7 @@ "Irreversible message deletion is prohibited in this chat." = "La suppression irréversible de message est interdite dans ce chat."; /* No comment provided by engineer. */ -"Irreversible message deletion is prohibited in this group." = "La suppression irréversible de messages est interdite dans ce groupe."; +"Irreversible message deletion is prohibited." = "La suppression irréversible de messages est interdite dans ce groupe."; /* No comment provided by engineer. */ "It allows having many anonymous connections without any shared data between them in a single chat profile." = "Cela permet d'avoir plusieurs connections anonymes sans aucune données partagées entre elles sur un même profil."; @@ -2506,6 +2607,9 @@ /* 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." = "Cela peut arriver quand :\n1. Les messages ont expiré dans le client expéditeur après 2 jours ou sur le serveur après 30 jours.\n2. Le déchiffrement du message a échoué, car vous ou votre contact avez utilisé une ancienne sauvegarde de base de données.\n3. La connexion a été compromise."; +/* No comment provided by engineer. */ +"It protects your IP address and connections." = "Il protège votre adresse IP et vos connexions."; + /* 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 (%@)." = "Il semblerait que vous êtes déjà connecté via ce lien. Si ce n'est pas le cas, il y a eu une erreur (%@)."; @@ -2545,13 +2649,16 @@ /* No comment provided by engineer. */ "Joining group" = "Entrain de rejoindre le groupe"; -/* No comment provided by engineer. */ +/* alert action */ "Keep" = "Conserver"; +/* No comment provided by engineer. */ +"Keep conversation" = "Garder la conversation"; + /* 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. */ +/* alert title */ "Keep unused invitation?" = "Conserver l'invitation inutilisée ?"; /* No comment provided by engineer. */ @@ -2608,9 +2715,6 @@ /* 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"; @@ -2623,24 +2727,15 @@ /* No comment provided by engineer. */ "Lock mode" = "Mode de verrouillage"; -/* No comment provided by engineer. */ -"Make a private connection" = "Établir une connexion privée"; - /* No comment provided by engineer. */ "Make one message disappear" = "Rendre un message éphémère"; /* No comment provided by engineer. */ "Make profile private!" = "Rendre un profil privé !"; -/* No comment provided by engineer. */ -"Make sure %@ server addresses are in correct format, line separated and are not duplicated (%@)." = "Assurez-vous que les adresses des serveurs %@ sont au bon format et ne sont pas dupliquées, un par ligne (%@)."; - /* No comment provided by engineer. */ "Make sure WebRTC ICE server addresses are in correct format, line separated and are not duplicated." = "Assurez-vous que les adresses des serveurs WebRTC ICE sont au bon format et ne sont pas dupliquées, un par ligne."; -/* No comment provided by engineer. */ -"Many people asked: *if SimpleX has no user identifiers, how can it deliver messages?*" = "Beaucoup se demandent : *si SimpleX n'a pas d'identifiant d'utilisateur, comment peut-il délivrer des messages ?*"; - /* No comment provided by engineer. */ "Mark deleted for everyone" = "Marquer comme supprimé pour tout le monde"; @@ -2659,6 +2754,9 @@ /* No comment provided by engineer. */ "Max 30 seconds, received instantly." = "Max 30 secondes, réception immédiate."; +/* No comment provided by engineer. */ +"Media & file servers" = "Serveurs de fichiers et de médias"; + /* blur media */ "Medium" = "Modéré"; @@ -2686,9 +2784,33 @@ /* No comment provided by engineer. */ "Member will be removed from group - this cannot be undone!" = "Ce membre sera retiré du groupe - impossible de revenir en arrière !"; +/* No comment provided by engineer. */ +"Members can add message reactions." = "Les membres du groupe peuvent ajouter des réactions aux messages."; + +/* No comment provided by engineer. */ +"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. */ +"Members can send direct messages." = "Les membres du groupe peuvent envoyer des messages directs."; + +/* No comment provided by engineer. */ +"Members can send disappearing messages." = "Les membres du groupes peuvent envoyer des messages éphémères."; + +/* No comment provided by engineer. */ +"Members can send files and media." = "Les membres du groupe peuvent envoyer des fichiers et des médias."; + +/* No comment provided by engineer. */ +"Members can send SimpleX links." = "Les membres du groupe peuvent envoyer des liens SimpleX."; + +/* No comment provided by engineer. */ +"Members can send voice messages." = "Les membres du groupe peuvent envoyer des messages vocaux."; + /* No comment provided by engineer. */ "Menus" = "Menus"; +/* No comment provided by engineer. */ +"message" = "message"; + /* item status text */ "Message delivery error" = "Erreur de distribution du message"; @@ -2717,7 +2839,7 @@ "Message reactions are prohibited in this chat." = "Les réactions aux messages sont interdites dans ce chat."; /* No comment provided by engineer. */ -"Message reactions are prohibited in this group." = "Les réactions aux messages sont interdites dans ce groupe."; +"Message reactions are prohibited." = "Les réactions aux messages sont interdites dans ce groupe."; /* notification */ "message received" = "message reçu"; @@ -2725,6 +2847,12 @@ /* No comment provided by engineer. */ "Message reception" = "Réception de message"; +/* No comment provided by engineer. */ +"Message servers" = "Serveurs de messages"; + +/* No comment provided by engineer. */ +"Message shape" = "Forme du message"; + /* No comment provided by engineer. */ "Message source remains private." = "La source du message reste privée."; @@ -2755,6 +2883,9 @@ /* No comment provided by engineer. */ "Messages sent" = "Messages envoyés"; +/* alert message */ +"Messages were deleted after you selected them." = "Les messages ont été supprimés après avoir été sélectionnés."; + /* No comment provided by engineer. */ "Messages, files and calls are protected by **end-to-end encryption** with perfect forward secrecy, repudiation and break-in recovery." = "Les messages, fichiers et appels sont protégés par un chiffrement **de bout en bout** avec une confidentialité persistante, une répudiation et une récupération en cas d'effraction."; @@ -2795,7 +2926,7 @@ "Migration is completed" = "La migration est terminée"; /* No comment provided by engineer. */ -"Migrations: %@" = "Migrations : %@"; +"Migrations:" = "Migrations :"; /* time unit */ "minutes" = "minutes"; @@ -2833,6 +2964,9 @@ /* No comment provided by engineer. */ "Multiple chat profiles" = "Différents profils de chat"; +/* No comment provided by engineer. */ +"mute" = "muet"; + /* swipe action */ "Mute" = "Muet"; @@ -2866,15 +3000,15 @@ /* No comment provided by engineer. */ "New chat" = "Nouveau chat"; +/* No comment provided by engineer. */ +"New chat experience 🎉" = "Nouvelle expérience de discussion 🎉"; + /* notification */ "New contact request" = "Nouvelle demande de contact"; /* notification */ "New contact:" = "Nouveau contact :"; -/* No comment provided by engineer. */ -"New database archive" = "Nouvelle archive de base de données"; - /* No comment provided by engineer. */ "New desktop app!" = "Nouvelle application de bureau !"; @@ -2884,6 +3018,9 @@ /* No comment provided by engineer. */ "New in %@" = "Nouveautés de la %@"; +/* No comment provided by engineer. */ +"New media options" = "Nouvelles options de médias"; + /* No comment provided by engineer. */ "New member role" = "Nouveau rôle"; @@ -2899,6 +3036,12 @@ /* No comment provided by engineer. */ "New passphrase…" = "Nouvelle phrase secrète…"; +/* No comment provided by engineer. */ +"New SOCKS credentials will be used every time you start the app." = "De nouveaux identifiants SOCKS seront utilisés chaque fois que vous démarrerez l'application."; + +/* No comment provided by engineer. */ +"New SOCKS credentials will be used for each server." = "De nouveaux identifiants SOCKS seront utilisées pour chaque serveur."; + /* pref value */ "no" = "non"; @@ -2941,21 +3084,36 @@ /* No comment provided by engineer. */ "No network connection" = "Pas de connexion au réseau"; +/* No comment provided by engineer. */ +"No permission to record speech" = "Enregistrement des conversations non autorisé"; + +/* No comment provided by engineer. */ +"No permission to record video" = "Enregistrement de la vidéo non autorisé"; + /* No comment provided by engineer. */ "No permission to record voice message" = "Pas l'autorisation d'enregistrer un message vocal"; +/* No comment provided by engineer. */ +"No push server" = "No push server"; + /* No comment provided by engineer. */ "No received or sent files" = "Aucun fichier reçu ou envoyé"; /* copied message info in history */ "no text" = "aucun texte"; +/* No comment provided by engineer. */ +"No user identifiers." = "Aucun identifiant d'utilisateur."; + /* No comment provided by engineer. */ "Not compatible!" = "Non compatible !"; /* No comment provided by engineer. */ "Nothing selected" = "Aucune sélection"; +/* alert title */ +"Nothing to forward!" = "Rien à transférer !"; + /* No comment provided by engineer. */ "Notifications" = "Notifications"; @@ -2982,7 +3140,7 @@ /* feature offered item */ "offered %@: %@" = "propose %1$@ : %2$@"; -/* No comment provided by engineer. */ +/* alert button */ "Ok" = "Ok"; /* No comment provided by engineer. */ @@ -2991,9 +3149,6 @@ /* No comment provided by engineer. */ "Old database" = "Ancienne base de données"; -/* No comment provided by engineer. */ -"Old database archive" = "Archives de l'ancienne base de données"; - /* group pref value */ "on" = "on"; @@ -3010,7 +3165,10 @@ "Onion hosts will not be used." = "Les hôtes .onion ne seront pas utilisés."; /* No comment provided by engineer. */ -"Only client devices store user profiles, contacts, groups, and messages sent with **2-layer end-to-end encryption**." = "Seuls les appareils clients stockent les profils des utilisateurs, les contacts, les groupes et les messages envoyés avec un **chiffrement de bout en bout à deux couches**."; +"Only client devices store user profiles, contacts, groups, and messages." = "Seuls les appareils clients stockent les profils des utilisateurs, les contacts, les groupes et les messages envoyés avec un **chiffrement de bout en bout à deux couches**."; + +/* No comment provided by engineer. */ +"Only delete conversation" = "Ne supprimer que la conversation"; /* No comment provided by engineer. */ "Only group owners can change group preferences." = "Seuls les propriétaires du groupe peuvent modifier les préférences du groupe."; @@ -3066,18 +3224,9 @@ /* authentication reason */ "Open migration to another device" = "Ouvrir le transfert vers un autre appareil"; -/* No comment provided by engineer. */ -"Open server settings" = "Ouvrir les paramètres du serveur"; - /* No comment provided by engineer. */ "Open Settings" = "Ouvrir les Paramètres"; -/* authentication reason */ -"Open user profiles" = "Ouvrir les profils d'utilisateurs"; - -/* No comment provided by engineer. */ -"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 app…" = "Ouverture de l'app…"; @@ -3091,7 +3240,7 @@ "Or securely share this file link" = "Ou partagez en toute sécurité le lien de ce fichier"; /* No comment provided by engineer. */ -"Or show this code" = "Ou présenter ce code"; +"Or show this code" = "Ou montrez ce code"; /* No comment provided by engineer. */ "other" = "autre"; @@ -3099,12 +3248,12 @@ /* No comment provided by engineer. */ "Other" = "Autres"; -/* No comment provided by engineer. */ -"Other %@ servers" = "Autres serveurs %@"; - /* No comment provided by engineer. */ "other errors" = "autres erreurs"; +/* alert message */ +"Other file errors:\n%@" = "Autres erreurs de fichiers :\n%@"; + /* member role */ "owner" = "propriétaire"; @@ -3126,6 +3275,9 @@ /* No comment provided by engineer. */ "Passcode set!" = "Code d'accès défini !"; +/* No comment provided by engineer. */ +"Password" = "Mot de passe"; + /* No comment provided by engineer. */ "Password to show" = "Mot de passe à entrer"; @@ -3151,10 +3303,7 @@ "Pending" = "En attente"; /* No comment provided by engineer. */ -"People can connect to you only via the links you share." = "On ne peut se connecter à vous qu’avec les liens que vous partagez."; - -/* No comment provided by engineer. */ -"Periodically" = "Périodique"; +"Periodic" = "Périodique"; /* message decrypt error item */ "Permanent decryption error" = "Erreur de déchiffrement"; @@ -3168,6 +3317,12 @@ /* No comment provided by engineer. */ "PING interval" = "Intervalle de PING"; +/* No comment provided by engineer. */ +"Play from the chat list." = "Aperçu depuis la liste de conversation."; + +/* No comment provided by engineer. */ +"Please ask your contact to enable calls." = "Veuillez demander à votre contact d'autoriser les appels."; + /* No comment provided by engineer. */ "Please ask your contact to enable sending voice messages." = "Veuillez demander à votre contact de permettre l'envoi de messages vocaux."; @@ -3216,15 +3371,15 @@ /* No comment provided by engineer. */ "Polish interface" = "Interface en polonais"; +/* No comment provided by engineer. */ +"Port" = "Port"; + /* server test error */ "Possibly, certificate fingerprint in server address is incorrect" = "Il est possible que l'empreinte du certificat dans l'adresse du serveur soit incorrecte"; /* No comment provided by engineer. */ "Preserve the last message draft, with attachments." = "Conserver le brouillon du dernier message, avec les pièces jointes."; -/* No comment provided by engineer. */ -"Preset server" = "Serveur prédéfini"; - /* No comment provided by engineer. */ "Preset server address" = "Adresse du serveur prédéfinie"; @@ -3267,19 +3422,13 @@ /* No comment provided by engineer. */ "Profile images" = "Images de profil"; -/* No comment provided by engineer. */ -"Profile name" = "Nom du profil"; - -/* No comment provided by engineer. */ -"Profile name:" = "Nom du profil :"; - /* No comment provided by engineer. */ "Profile password" = "Mot de passe de profil"; /* No comment provided by engineer. */ "Profile theme" = "Thème de profil"; -/* No comment provided by engineer. */ +/* alert message */ "Profile update will be sent to your contacts." = "La mise à jour du profil sera envoyée à vos contacts."; /* No comment provided by engineer. */ @@ -3333,6 +3482,9 @@ /* No comment provided by engineer. */ "Proxied servers" = "Serveurs routés via des proxy"; +/* No comment provided by engineer. */ +"Proxy requires password" = "Le proxy est protégé par un mot de passe"; + /* No comment provided by engineer. */ "Push notifications" = "Notifications push"; @@ -3348,6 +3500,9 @@ /* No comment provided by engineer. */ "Rate the app" = "Évaluer l'app"; +/* No comment provided by engineer. */ +"Reachable chat toolbar" = "Barre d'outils accessible"; + /* chat item menu */ "React…" = "Réagissez…"; @@ -3358,10 +3513,10 @@ "Read more" = "En savoir plus"; /* 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)."; +"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/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)."; +"Read more in [User Guide](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)." = "Pour en savoir plus, consultez le [Guide de l'utilisateur](https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses)."; /* 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)."; @@ -3369,9 +3524,6 @@ /* No comment provided by engineer. */ "Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme)." = "Pour en savoir plus, consultez notre [dépôt GitHub](https://github.com/simplex-chat/simplex-chat#readme)."; -/* No comment provided by engineer. */ -"Read more in our GitHub repository." = "Plus d'informations sur notre GitHub."; - /* No comment provided by engineer. */ "Receipts are disabled" = "Les accusés de réception sont désactivés"; @@ -3475,6 +3627,9 @@ /* No comment provided by engineer. */ "Remove" = "Supprimer"; +/* No comment provided by engineer. */ +"Remove archive?" = "Supprimer l'archive ?"; + /* No comment provided by engineer. */ "Remove image" = "Enlever l'image"; @@ -3535,6 +3690,9 @@ /* No comment provided by engineer. */ "Reset" = "Réinitialisation"; +/* No comment provided by engineer. */ +"Reset all hints" = "Rétablir tous les conseils"; + /* No comment provided by engineer. */ "Reset all statistics" = "Réinitialiser toutes les statistiques"; @@ -3598,27 +3756,25 @@ /* No comment provided by engineer. */ "Safer groups" = "Groupes plus sûrs"; -/* chat item action */ +/* alert button + chat item action */ "Save" = "Enregistrer"; -/* No comment provided by engineer. */ +/* alert button */ "Save (and notify contacts)" = "Enregistrer (et en informer les contacts)"; -/* No comment provided by engineer. */ +/* alert button */ "Save and notify contact" = "Enregistrer et en informer le contact"; /* No comment provided by engineer. */ "Save and notify group members" = "Enregistrer et en informer les membres du groupe"; +/* No comment provided by engineer. */ +"Save and reconnect" = "Sauvegarder et se reconnecter"; + /* No comment provided by engineer. */ "Save and update group profile" = "Enregistrer et mettre à jour le profil du groupe"; -/* No comment provided by engineer. */ -"Save archive" = "Enregistrer l'archive"; - -/* No comment provided by engineer. */ -"Save auto-accept settings" = "Enregistrer les paramètres de validation automatique"; - /* No comment provided by engineer. */ "Save group profile" = "Enregistrer le profil du groupe"; @@ -3628,7 +3784,7 @@ /* No comment provided by engineer. */ "Save passphrase in Keychain" = "Enregistrer la phrase secrète dans la Keychain"; -/* No comment provided by engineer. */ +/* alert title */ "Save preferences?" = "Enregistrer les préférences ?"; /* No comment provided by engineer. */ @@ -3637,15 +3793,15 @@ /* No comment provided by engineer. */ "Save servers" = "Enregistrer les serveurs"; -/* No comment provided by engineer. */ +/* alert title */ "Save servers?" = "Enregistrer les serveurs ?"; -/* No comment provided by engineer. */ -"Save settings?" = "Enregistrer les paramètres ?"; - /* No comment provided by engineer. */ "Save welcome message?" = "Enregistrer le message d'accueil ?"; +/* alert title */ +"Save your profile?" = "Sauvegarder votre profil ?"; + /* No comment provided by engineer. */ "saved" = "enregistré"; @@ -3664,11 +3820,14 @@ /* No comment provided by engineer. */ "Saved WebRTC ICE servers will be removed" = "Les serveurs WebRTC ICE sauvegardés seront supprimés"; +/* No comment provided by engineer. */ +"Saving %lld messages" = "Sauvegarde de %lld messages"; + /* No comment provided by engineer. */ "Scale" = "Échelle"; /* No comment provided by engineer. */ -"Scan / Paste link" = "Scanner / Coller le lien"; +"Scan / Paste link" = "Scanner / Coller un lien"; /* No comment provided by engineer. */ "Scan code" = "Scanner le code"; @@ -3685,6 +3844,9 @@ /* No comment provided by engineer. */ "Scan server QR code" = "Scanner un code QR de serveur"; +/* No comment provided by engineer. */ +"search" = "rechercher"; + /* No comment provided by engineer. */ "Search" = "Rechercher"; @@ -3710,7 +3872,7 @@ "Secure queue" = "File d'attente sécurisée"; /* No comment provided by engineer. */ -"Secured" = "Sécurisé"; +"Secured" = "Sécurisées"; /* No comment provided by engineer. */ "Security assessment" = "Évaluation de sécurité"; @@ -3724,6 +3886,9 @@ /* chat item action */ "Select" = "Choisir"; +/* No comment provided by engineer. */ +"Select chat profile" = "Sélectionner un profil de discussion"; + /* No comment provided by engineer. */ "Selected %lld" = "%lld sélectionné(s)"; @@ -3764,11 +3929,14 @@ "Send errors" = "Erreurs d'envoi"; /* No comment provided by engineer. */ -"Send link previews" = "Envoi d'aperçus de liens"; +"Send link previews" = "Aperçu des liens"; /* No comment provided by engineer. */ "Send live message" = "Envoyer un message dynamique"; +/* No comment provided by engineer. */ +"Send message to enable calls." = "Envoyer un message pour activer les appels."; + /* No comment provided by engineer. */ "Send messages directly when IP address is protected and your or destination server does not support private routing." = "Envoyer les messages de manière directe lorsque l'adresse IP est protégée et que votre serveur ou le serveur de destination ne prend pas en charge le routage privé."; @@ -3778,9 +3946,6 @@ /* No comment provided by engineer. */ "Send notifications" = "Envoi de notifications"; -/* No comment provided by engineer. */ -"Send notifications:" = "Envoi de notifications :"; - /* No comment provided by engineer. */ "Send questions and ideas" = "Envoyez vos questions et idées"; @@ -3793,7 +3958,7 @@ /* 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. */ +/* alert message */ "Sender cancelled file transfer." = "L'expéditeur a annulé le transfert de fichiers."; /* No comment provided by engineer. */ @@ -3853,6 +4018,9 @@ /* No comment provided by engineer. */ "Sent via proxy" = "Envoyé via le proxy"; +/* No comment provided by engineer. */ +"Server" = "Serveur"; + /* No comment provided by engineer. */ "Server address" = "Adresse du serveur"; @@ -3869,7 +4037,7 @@ "Server requires authorization to create queues, check password" = "Le serveur requiert une autorisation pour créer des files d'attente, vérifiez le mot de passe"; /* server test error */ -"Server requires authorization to upload, check password" = "Le serveur requiert une autorisation pour uploader, vérifiez le mot de passe"; +"Server requires authorization to upload, check password" = "Le serveur requiert une autorisation pour téléverser, vérifiez le mot de passe"; /* No comment provided by engineer. */ "Server test failed!" = "Échec du test du serveur !"; @@ -3934,10 +4102,14 @@ /* No comment provided by engineer. */ "Settings" = "Paramètres"; +/* alert message */ +"Settings were changed." = "Les paramètres ont été modifiés."; + /* No comment provided by engineer. */ "Shape profile images" = "Images de profil modelable"; -/* chat item action */ +/* alert action + chat item action */ "Share" = "Partager"; /* No comment provided by engineer. */ @@ -3946,14 +4118,20 @@ /* No comment provided by engineer. */ "Share address" = "Partager l'adresse"; -/* No comment provided by engineer. */ +/* alert title */ "Share address with contacts?" = "Partager l'adresse avec vos contacts ?"; +/* No comment provided by engineer. */ +"Share from other apps." = "Partager depuis d'autres applications."; + /* No comment provided by engineer. */ "Share link" = "Partager le lien"; /* No comment provided by engineer. */ -"Share this 1-time invite link" = "Partager ce lien d'invitation unique"; +"Share profile" = "Partager le profil"; + +/* No comment provided by engineer. */ +"Share this 1-time invite link" = "Partagez ce lien d'invitation unique"; /* No comment provided by engineer. */ "Share to SimpleX" = "Partager sur SimpleX"; @@ -3971,7 +4149,7 @@ "Show developer options" = "Afficher les options pour les développeurs"; /* No comment provided by engineer. */ -"Show last messages" = "Voir les derniers messages"; +"Show last messages" = "Aperçu des derniers messages"; /* No comment provided by engineer. */ "Show message status" = "Afficher le statut du message"; @@ -3980,7 +4158,7 @@ "Show percentage" = "Afficher le pourcentage"; /* No comment provided by engineer. */ -"Show preview" = "Afficher l'aperçu"; +"Show preview" = "Aperçu affiché"; /* No comment provided by engineer. */ "Show QR code" = "Afficher le code QR"; @@ -4013,7 +4191,7 @@ "SimpleX links" = "Liens SimpleX"; /* No comment provided by engineer. */ -"SimpleX links are prohibited in this group." = "Les liens SimpleX sont interdits dans ce groupe."; +"SimpleX links are prohibited." = "Les liens SimpleX sont interdits dans ce groupe."; /* No comment provided by engineer. */ "SimpleX links not allowed" = "Les liens SimpleX ne sont pas autorisés"; @@ -4033,6 +4211,9 @@ /* simplex link type */ "SimpleX one-time invitation" = "Invitation unique SimpleX"; +/* No comment provided by engineer. */ +"SimpleX protocols reviewed by Trail of Bits." = "Protocoles SimpleX audité par Trail of Bits."; + /* No comment provided by engineer. */ "Simplified incognito mode" = "Mode incognito simplifié"; @@ -4051,12 +4232,24 @@ /* No comment provided by engineer. */ "SMP server" = "Serveur SMP"; +/* No comment provided by engineer. */ +"SOCKS proxy" = "proxy SOCKS"; + /* blur media */ "Soft" = "Léger"; +/* No comment provided by engineer. */ +"Some app settings were not migrated." = "Certains paramètres de l'application n'ont pas été migrés."; + +/* No comment provided by engineer. */ +"Some file(s) were not exported:" = "Certains fichiers n'ont pas été exportés :"; + /* No comment provided by engineer. */ "Some non-fatal errors occurred during import - you may see Chat console for more details." = "Des erreurs non fatales se sont produites lors de l'importation - vous pouvez consulter la console de chat pour plus de détails."; +/* No comment provided by engineer. */ +"Some non-fatal errors occurred during import:" = "L'importation a entraîné des erreurs non fatales :"; + /* notification title */ "Somebody" = "Quelqu'un"; @@ -4090,9 +4283,6 @@ /* No comment provided by engineer. */ "Stop chat" = "Arrêter le chat"; -/* No comment provided by engineer. */ -"Stop chat to enable database actions" = "Arrêter le chat pour permettre des actions sur la base de données"; - /* 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." = "Arrêtez le chat pour exporter, importer ou supprimer la base de données du chat. Vous ne pourrez pas recevoir et envoyer de messages pendant que le chat est arrêté."; @@ -4108,10 +4298,10 @@ /* No comment provided by engineer. */ "Stop sending file?" = "Arrêter l'envoi du fichier ?"; -/* No comment provided by engineer. */ +/* alert action */ "Stop sharing" = "Cesser le partage"; -/* No comment provided by engineer. */ +/* alert title */ "Stop sharing address?" = "Cesser le partage d'adresse ?"; /* authentication reason */ @@ -4130,7 +4320,7 @@ "Submit" = "Soumettre"; /* No comment provided by engineer. */ -"Subscribed" = "Inscrit"; +"Subscribed" = "Inscriptions"; /* No comment provided by engineer. */ "Subscription errors" = "Erreurs d'inscription"; @@ -4141,12 +4331,21 @@ /* No comment provided by engineer. */ "Support SimpleX Chat" = "Supporter SimpleX Chat"; +/* No comment provided by engineer. */ +"Switch audio and video during the call." = "Passer de l'audio à la vidéo pendant l'appel."; + +/* No comment provided by engineer. */ +"Switch chat profile for 1-time invitations." = "Changer de profil de chat pour les invitations à usage unique."; + /* No comment provided by engineer. */ "System" = "Système"; /* No comment provided by engineer. */ "System authentication" = "Authentification du système"; +/* No comment provided by engineer. */ +"Tail" = "Queue"; + /* No comment provided by engineer. */ "Take picture" = "Prendre une photo"; @@ -4171,6 +4370,9 @@ /* No comment provided by engineer. */ "Tap to scan" = "Appuyez pour scanner"; +/* No comment provided by engineer. */ +"TCP connection" = "Connexion TCP"; + /* No comment provided by engineer. */ "TCP connection timeout" = "Délai de connexion TCP"; @@ -4195,7 +4397,7 @@ /* No comment provided by engineer. */ "Test servers" = "Tester les serveurs"; -/* No comment provided by engineer. */ +/* alert title */ "Tests failed!" = "Échec des tests !"; /* No comment provided by engineer. */ @@ -4207,9 +4409,6 @@ /* No comment provided by engineer. */ "Thanks to the users – contribute via Weblate!" = "Merci aux utilisateurs - contribuez via Weblate !"; -/* No comment provided by engineer. */ -"The 1st platform without any user identifiers – private by design." = "La 1ère plateforme sans aucun identifiant d'utilisateur – privée par design."; - /* No comment provided by engineer. */ "The app can notify you when you receive messages or contact requests - please open settings to enable." = "L'application peut vous avertir lorsque vous recevez des messages ou des demandes de contact - veuillez ouvrir les paramètres pour les activer."; @@ -4234,6 +4433,9 @@ /* No comment provided by engineer. */ "The encryption is working and the new encryption agreement is not required. It may result in connection errors!" = "Le chiffrement fonctionne et le nouvel accord de chiffrement n'est pas nécessaire. Cela peut provoquer des erreurs de connexion !"; +/* No comment provided by engineer. */ +"The future of messaging" = "La nouvelle génération de messagerie privée"; + /* No comment provided by engineer. */ "The hash of the previous message is different." = "Le hash du message précédent est différent."; @@ -4252,9 +4454,6 @@ /* No comment provided by engineer. */ "The messages will be marked as moderated for all members." = "Les messages seront marqués comme modérés pour tous les membres."; -/* No comment provided by engineer. */ -"The next generation of private messaging" = "La nouvelle génération de messagerie privée"; - /* No comment provided by engineer. */ "The old database was not removed during the migration, it can be deleted." = "L'ancienne base de données n'a pas été supprimée lors de la migration, elle peut être supprimée."; @@ -4273,6 +4472,9 @@ /* 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. */ +"The uploaded database archive will be permanently removed from the servers." = "L'archive de la base de données envoyée sera définitivement supprimée des serveurs."; + /* No comment provided by engineer. */ "Themes" = "Thèmes"; @@ -4331,7 +4533,7 @@ "To ask any questions and to receive updates:" = "Si vous avez des questions et que vous souhaitez des réponses :"; /* No comment provided by engineer. */ -"To connect, your contact can scan QR code or use the link in the app." = "Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application."; +"To connect, your contact can scan QR code or use the link in the app." = "Pour se connecter, votre contact peut scanner un code QR ou utiliser un lien dans l'app."; /* No comment provided by engineer. */ "To hide unwanted messages." = "Pour cacher les messages indésirables."; @@ -4339,9 +4541,6 @@ /* No comment provided by engineer. */ "To make a new connection" = "Pour établir une nouvelle connexion"; -/* 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." = "Pour protéger votre vie privée, au lieu d’IDs utilisés par toutes les autres plateformes, SimpleX a des IDs pour les queues de messages, distinctes pour chacun de vos contacts."; - /* No comment provided by engineer. */ "To protect timezone, image/voice files use UTC." = "Pour préserver le fuseau horaire, les fichiers image/voix utilisent le système UTC."; @@ -4351,6 +4550,15 @@ /* No comment provided by engineer. */ "To protect your IP address, private routing uses your SMP servers to deliver messages." = "Pour protéger votre adresse IP, le routage privé utilise vos serveurs SMP pour délivrer les messages."; +/* No comment provided by engineer. */ +"To protect your privacy, SimpleX uses separate IDs for each of your contacts." = "Pour protéger votre vie privée, au lieu d’IDs utilisés par toutes les autres plateformes, SimpleX a des IDs pour les queues de messages, distinctes pour chacun de vos contacts."; + +/* No comment provided by engineer. */ +"To record speech please grant permission to use Microphone." = "Si vous souhaitez enregistrer une conversation, veuillez autoriser l'utilisation du microphone."; + +/* No comment provided by engineer. */ +"To record video please grant permission to use Camera." = "Si vous souhaitez enregistrer une vidéo, veuillez autoriser l'utilisation de la caméra."; + /* No comment provided by engineer. */ "To record voice message please grant permission to use Microphone." = "Pour enregistrer un message vocal, veuillez accorder la permission d'utiliser le microphone."; @@ -4363,9 +4571,15 @@ /* No comment provided by engineer. */ "To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Pour vérifier le chiffrement de bout en bout avec votre contact, comparez (ou scannez) le code sur vos appareils."; +/* No comment provided by engineer. */ +"Toggle chat list:" = "Afficher la liste des conversations :"; + /* No comment provided by engineer. */ "Toggle incognito when connecting." = "Basculer en mode incognito lors de la connexion."; +/* No comment provided by engineer. */ +"Toolbar opacity" = "Opacité de la barre d'outils"; + /* No comment provided by engineer. */ "Total" = "Total"; @@ -4444,7 +4658,7 @@ /* No comment provided by engineer. */ "unknown servers" = "relais inconnus"; -/* No comment provided by engineer. */ +/* alert title */ "Unknown servers!" = "Serveurs inconnus !"; /* No comment provided by engineer. */ @@ -4468,6 +4682,9 @@ /* authentication reason */ "Unlock app" = "Déverrouiller l'app"; +/* No comment provided by engineer. */ +"unmute" = "démuter"; + /* swipe action */ "Unmute" = "Démute"; @@ -4489,6 +4706,9 @@ /* No comment provided by engineer. */ "Update network settings?" = "Mettre à jour les paramètres réseau ?"; +/* No comment provided by engineer. */ +"Update settings?" = "Mettre à jour les paramètres ?"; + /* rcv group event chat item */ "updated group profile" = "mise à jour du profil de groupe"; @@ -4508,7 +4728,7 @@ "Upload failed" = "Échec de l'envoi"; /* server test step */ -"Upload file" = "Transférer le fichier"; +"Upload file" = "Téléverser le fichier"; /* No comment provided by engineer. */ "Uploaded" = "Téléversé"; @@ -4555,15 +4775,21 @@ /* No comment provided by engineer. */ "Use SimpleX Chat servers?" = "Utiliser les serveurs SimpleX Chat ?"; +/* No comment provided by engineer. */ +"Use SOCKS proxy" = "Utiliser un proxy SOCKS"; + /* No comment provided by engineer. */ "Use the app while in the call." = "Utiliser l'application pendant l'appel."; /* No comment provided by engineer. */ -"User profile" = "Profil d'utilisateur"; +"Use the app with one hand." = "Utiliser l'application d'une main."; /* No comment provided by engineer. */ "User selection" = "Sélection de l'utilisateur"; +/* No comment provided by engineer. */ +"Username" = "Nom d'utilisateur"; + /* No comment provided by engineer. */ "Using SimpleX Chat servers." = "Vous utilisez les serveurs SimpleX."; @@ -4612,6 +4838,9 @@ /* No comment provided by engineer. */ "Via secure quantum resistant protocol." = "Via un protocole sécurisé de cryptographie post-quantique."; +/* No comment provided by engineer. */ +"video" = "vidéo"; + /* No comment provided by engineer. */ "Video call" = "Appel vidéo"; @@ -4619,7 +4848,7 @@ "video call (not e2e encrypted)" = "appel vidéo (sans chiffrement)"; /* No comment provided by engineer. */ -"Video will be received when your contact completes uploading it." = "La vidéo ne sera reçue que lorsque votre contact aura fini de la transférer."; +"Video will be received when your contact completes uploading it." = "La vidéo ne sera reçue que lorsque votre contact aura fini la mettre en ligne."; /* No comment provided by engineer. */ "Video will be received when your contact is online, please wait or check later!" = "La vidéo ne sera reçue que lorsque votre contact sera en ligne. Veuillez patienter ou vérifier plus tard !"; @@ -4643,7 +4872,7 @@ "Voice messages are prohibited in this chat." = "Les messages vocaux sont interdits dans ce chat."; /* No comment provided by engineer. */ -"Voice messages are prohibited in this group." = "Les messages vocaux sont interdits dans ce groupe."; +"Voice messages are prohibited." = "Les messages vocaux sont interdits dans ce groupe."; /* No comment provided by engineer. */ "Voice messages not allowed" = "Les messages vocaux ne sont pas autorisés"; @@ -4711,9 +4940,6 @@ /* No comment provided by engineer. */ "when IP hidden" = "lorsque l'IP est masquée"; -/* No comment provided by engineer. */ -"When people request to connect, you can accept or reject it." = "Vous pouvez accepter ou refuser les demandes de contacts."; - /* 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."; @@ -4738,7 +4964,7 @@ /* No comment provided by engineer. */ "Without Tor or VPN, your IP address will be visible to file servers." = "Sans Tor ou un VPN, votre adresse IP sera visible par les serveurs de fichiers."; -/* No comment provided by engineer. */ +/* alert message */ "Without Tor or VPN, your IP address will be visible to these XFTP relays: %@." = "Sans Tor ni VPN, votre adresse IP sera visible par ces relais XFTP : %@."; /* No comment provided by engineer. */ @@ -4762,9 +4988,6 @@ /* No comment provided by engineer. */ "you" = "vous"; -/* No comment provided by engineer. */ -"You" = "Vous"; - /* No comment provided by engineer. */ "You **must not** use the same database on two devices." = "Vous **ne devez pas** utiliser la même base de données sur deux appareils."; @@ -4822,6 +5045,9 @@ /* 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 change it in Appearance settings." = "Vous pouvez choisir de le modifier dans les paramètres d'apparence."; + /* No comment provided by engineer. */ "You can create it later" = "Vous pouvez la créer plus tard"; @@ -4843,6 +5069,9 @@ /* notification body */ "You can now chat with %@" = "Vous pouvez maintenant envoyer des messages à %@"; +/* No comment provided by engineer. */ +"You can send messages to %@ from Archived contacts." = "Vous pouvez envoyer des messages à %@ à partir des contacts archivés."; + /* No comment provided by engineer. */ "You can set lock screen notification preview via settings." = "Vous pouvez configurer l'aperçu des notifications sur l'écran de verrouillage via les paramètres."; @@ -4853,10 +5082,10 @@ "You can share this address with your contacts to let them connect with **%@**." = "Vous pouvez partager cette adresse avec vos contacts pour leur permettre de se connecter avec **%@**."; /* No comment provided by engineer. */ -"You can share your address as a link or QR code - anybody can connect to you." = "Vous pouvez partager votre adresse sous la forme d'un lien ou d'un code QR - tout le monde peut l'utiliser pour vous contacter."; +"You can start chat via app Settings / Database or by restarting the app" = "Vous pouvez lancer le chat via Paramètres / Base de données ou en redémarrant l'app"; /* No comment provided by engineer. */ -"You can start chat via app Settings / Database or by restarting the app" = "Vous pouvez lancer le chat via Paramètres / Base de données ou en redémarrant l'app"; +"You can still view conversation with %@ in the list of chats." = "Vous pouvez toujours voir la conversation avec %@ dans la liste des discussions."; /* No comment provided by engineer. */ "You can turn on SimpleX Lock via Settings." = "Vous pouvez activer SimpleX Lock dans les Paramètres."; @@ -4864,7 +5093,7 @@ /* 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. */ +/* alert message */ "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. */ @@ -4883,10 +5112,10 @@ "you changed role of %@ to %@" = "vous avez modifié le rôle de %1$@ pour %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." = "Vous contrôlez par quel·s serveur·s vous pouvez **transmettre** ainsi que par quel·s serveur·s vous pouvez **recevoir** les messages de vos contacts."; +"You could not be verified; please try again." = "Vous n'avez pas pu être vérifié·e ; veuillez réessayer."; /* No comment provided by engineer. */ -"You could not be verified; please try again." = "Vous n'avez pas pu être vérifié·e ; veuillez réessayer."; +"You decide who can connect." = "Vous choisissez qui peut se connecter."; /* No comment provided by engineer. */ "You have already requested connection via this address!" = "Vous avez déjà demandé une connexion via cette adresse !"; @@ -4909,9 +5138,18 @@ /* snd group event chat item */ "you left" = "vous avez quitté"; +/* No comment provided by engineer. */ +"You may migrate the exported database." = "Vous pouvez migrer la base de données exportée."; + +/* No comment provided by engineer. */ +"You may save the exported archive." = "Vous pouvez enregistrer l'archive exportée."; + /* 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." = "Vous devez utiliser la version la plus récente de votre base de données de chat sur un seul appareil UNIQUEMENT, sinon vous risquez de ne plus recevoir les messages de certains contacts."; +/* No comment provided by engineer. */ +"You need to allow your contact to call to be able to call them." = "Vous devez autoriser votre contact à appeler pour pouvoir l'appeler."; + /* No comment provided by engineer. */ "You need to allow your contact to send voice messages to be able to send them." = "Vous devez autoriser votre contact à envoyer des messages vocaux pour pouvoir en envoyer."; @@ -4969,9 +5207,6 @@ /* 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" = "Vous utilisez un profil incognito pour ce groupe - pour éviter de partager votre profil principal ; inviter des contacts n'est pas possible"; -/* No comment provided by engineer. */ -"Your %@ servers" = "Vos serveurs %@"; - /* No comment provided by engineer. */ "Your calls" = "Vos appels"; @@ -4981,9 +5216,15 @@ /* No comment provided by engineer. */ "Your chat database is not encrypted - set passphrase to encrypt it." = "Votre base de données de chat n'est pas chiffrée - définisez une phrase secrète."; +/* alert title */ +"Your chat preferences" = "Vos préférences de discussion"; + /* No comment provided by engineer. */ "Your chat profiles" = "Vos profils de chat"; +/* No comment provided by engineer. */ +"Your connection was moved to %@ but an unexpected error occurred while redirecting you to the profile." = "Votre connexion a été déplacée vers %@ mais une erreur inattendue s'est produite lors de la redirection vers le profil."; + /* No comment provided by engineer. */ "Your contact sent a file that is larger than currently supported maximum size (%@)." = "Votre contact a envoyé un fichier plus grand que la taille maximale supportée actuellement(%@)."; @@ -4993,6 +5234,9 @@ /* No comment provided by engineer. */ "Your contacts will remain connected." = "Vos contacts resteront connectés."; +/* No comment provided by engineer. */ +"Your credentials may be sent unencrypted." = "Vos informations d'identification peuvent être envoyées non chiffrées."; + /* No comment provided by engineer. */ "Your current chat database will be DELETED and REPLACED with the imported one." = "Votre base de données de chat actuelle va être SUPPRIMEE et REMPLACEE par celle importée."; @@ -5015,7 +5259,10 @@ "Your profile **%@** will be shared." = "Votre profil **%@** sera partagé."; /* No comment provided by engineer. */ -"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts.\nLes serveurs SimpleX ne peuvent pas voir votre profil."; +"Your profile is stored on your device and shared only with your contacts. SimpleX servers cannot see your profile." = "Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil."; + +/* alert message */ +"Your profile was changed. If you save it, the updated profile will be sent to all your contacts." = "Votre profil a été modifié. Si vous l'enregistrez, le profil mis à jour sera envoyé à tous vos contacts."; /* No comment provided by engineer. */ "Your profile, contacts and delivered messages are stored on your device." = "Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil."; @@ -5023,9 +5270,6 @@ /* No comment provided by engineer. */ "Your random profile" = "Votre profil aléatoire"; -/* No comment provided by engineer. */ -"Your server" = "Votre serveur"; - /* No comment provided by engineer. */ "Your server address" = "Votre adresse de serveur"; @@ -5038,6 +5282,3 @@ /* No comment provided by engineer. */ "Your SMP servers" = "Vos serveurs SMP"; -/* No comment provided by engineer. */ -"Your XFTP servers" = "Vos serveurs XFTP"; - diff --git a/apps/ios/hu.lproj/Localizable.strings b/apps/ios/hu.lproj/Localizable.strings index b5d0b8b895..2ba51d1e13 100644 --- a/apps/ios/hu.lproj/Localizable.strings +++ b/apps/ios/hu.lproj/Localizable.strings @@ -1,15 +1,6 @@ /* 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. */ " (" = " ("; @@ -26,10 +17,10 @@ "- more stable message delivery.\n- a bit better groups.\n- and more!" = "- stabilabb üzenetkézbesítés.\n- valamivel jobb csoportok.\n- és még sok más!"; /* No comment provided by engineer. */ -"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- opcionális értesítés a törölt kapcsolatokról.\n- profilnevek szóközökkel.\n- és még sok más!"; +"- optionally notify deleted contacts.\n- profile names with spaces.\n- and more!" = "- értesíti az ismerősöket a törlésről (nem kötelező)\n- profil nevek szóközökkel\n- és még sok más!"; /* No comment provided by engineer. */ -"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- hangüzenetek legfeljebb 5 perces időtartamig.\n- egyedi eltűnési időhatár megadása.\n- előzmények szerkesztése."; +"- voice messages up to 5 minutes.\n- custom time to disappear.\n- editing history." = "- 5 perc hosszúságú hangüzenetek.\n- egyedi üzenet-eltűnési időkorlát.\n- előzmények szerkesztése."; /* No comment provided by engineer. */ ", " = ", "; @@ -62,16 +53,13 @@ "[Send us email](mailto:chat@simplex.chat)" = "[Küldjön nekünk e-mailt](mailto:chat@simplex.chat)"; /* No comment provided by engineer. */ -"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Csillag a GitHubon](https://github.com/simplex-chat/simplex-chat)"; +"[Star on GitHub](https://github.com/simplex-chat/simplex-chat)" = "[Csillagozás a GitHubon](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." = "**Ismerős hozzáadása**: új meghívó hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz."; +"**Create 1-time link**: to create and share a new invitation link." = "**Ismerős hozzáadása:** új meghívó-hivatkozás létrehozásához, vagy egy kapott hivatkozáson keresztül történő kapcsolódáshoz."; /* No comment provided by engineer. */ -"**Add new contact**: to create your one-time QR Code for your contact." = "**Új ismerős hozzáadása**: egyszer használatos QR-kód vagy hivatkozás létrehozása az ismerőse számára."; - -/* No comment provided by engineer. */ -"**Create group**: to create a new group." = "**Csoport létrehozása**: új csoport létrehozásához."; +"**Create group**: to create a new group." = "**Csoport létrehozása:** új csoport létrehozásához."; /* No comment provided by engineer. */ "**e2e encrypted** audio call" = "**e2e titkosított** hanghívás"; @@ -80,25 +68,28 @@ "**e2e encrypted** video call" = "**e2e titkosított** videóhívás"; /* 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." = "**Privátabb**: 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken megosztásra kerül a SimpleX Chat kiszolgálóval, de az nem, hogy hány ismerőse vagy üzenete van."; +"**More private**: check new messages every 20 minutes. Only device token is shared with our push server. It doesn't see how many contacts you have, or any message metadata." = "**Privátabb:** 20 percenként ellenőrzi az új üzeneteket. Az eszköztoken megosztásra kerül a SimpleX Chat-kiszolgálóval, de az nem, hogy hány ismerőse vagy üzenete van."; /* 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)." = "**Legprivátabb**: ne használja a SimpleX Chat értesítési kiszolgálót, rendszeresen ellenőrizze az üzeneteket a háttérben (attól függően, hogy milyen gyakran használja az alkalmazást)."; +"**Most private**: do not use SimpleX Chat push server. The app will check messages in background, when the system allows it, depending on how often you use the app." = "**Legprivátabb:** ne használja a SimpleX Chat értesítési kiszolgálót, rendszeresen ellenőrizze az üzeneteket a háttérben (attól függően, hogy milyen gyakran használja az alkalmazást)."; /* No comment provided by engineer. */ -"**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Megjegyzés**: ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja az ismerőseitől érkező üzenetek visszafejtését."; +"**Please note**: using the same database on two devices will break the decryption of messages from your connections, as a security protection." = "**Megjegyzés:** ha két eszközön is ugyanazt az adatbázist használja, akkor biztonsági védelemként megszakítja az ismerőseitől érkező üzenetek visszafejtését."; /* No comment provided by engineer. */ -"**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Figyelem**: NEM tudja visszaállítani vagy megváltoztatni jelmondatát, ha elveszíti azt."; +"**Please note**: you will NOT be able to recover or change passphrase if you lose it." = "**Megjegyzés:** NEM tudja visszaállítani vagy megváltoztatni jelmondatát, ha elveszíti azt."; /* 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." = "**Javasolt**: az eszköztoken és az értesítések elküldésre kerülnek a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik."; +"**Recommended**: device token and end-to-end encrypted notifications are sent to SimpleX Chat push server, but it does not see the message content, size or who it is from." = "**Megjegyzés:** az eszköztoken és az értesítések elküldésre kerülnek a SimpleX Chat értesítési kiszolgálóra, kivéve az üzenet tartalma, mérete vagy az, hogy kitől származik."; /* No comment provided by engineer. */ -"**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Figyelmeztetés**: Az azonnali push-értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges."; +"**Scan / Paste link**: to connect via a link you received." = "**Hivatkozás beolvasása / beillesztése**: egy kapott hivatkozáson keresztüli kapcsolódáshoz."; /* No comment provided by engineer. */ -"**Warning**: the archive will be removed." = "**Figyelem**: az archívum törlésre kerül."; +"**Warning**: Instant push notifications require passphrase saved in Keychain." = "**Figyelmeztetés:** Az azonnali push-értesítésekhez a kulcstartóban tárolt jelmondat megadása szükséges."; + +/* No comment provided by engineer. */ +"**Warning**: the archive will be removed." = "**Figyelmeztetés:** az archívum eltávolításra kerül."; /* No comment provided by engineer. */ "*bold*" = "\\*félkövér*"; @@ -113,7 +104,7 @@ "## In reply to" = "## Válaszul erre:"; /* No comment provided by engineer. */ -"#secret#" = "#titkos#"; +"#secret#" = "#titok#"; /* No comment provided by engineer. */ "%@" = "%@"; @@ -137,7 +128,7 @@ "%@ and %@ connected" = "%@ és %@ kapcsolódott"; /* copied message info, at