Compare commits

..

145 Commits

Author SHA1 Message Date
Morgan Pretty 6a9ffdd22b
Merge pull request #940 from oxen-io/dev
Release 2.4.4
2023-12-11 17:39:59 +11:00
Morgan Pretty f532496ee4 Increased build and version numbers 2023-12-11 17:04:57 +11:00
Morgan Pretty d8dc801e5f
Merge pull request #939 from RyanRory/turn-server-fix
TURN server fix
2023-12-11 17:01:38 +11:00
Ryan ZHAO 6d2e0b457e fix: wrong server removed 2023-12-08 10:28:46 +11:00
Ryan ZHAO e6cf75dd3f remove frigg&fenrir turn servers for now 2023-12-08 10:26:48 +11:00
Morgan Pretty 109a81f33f
Merge pull request #929 from mpretty-cyro/fix/media-interactions
Fixed a few bugs and crashes around media interactions
2023-10-18 08:53:26 +11:00
Morgan Pretty 05460ca2b3 Fixed a bug where the play button wouldn't appear when swiping attachments 2023-10-13 15:18:02 +11:00
Morgan Pretty de7d85f4cb Merge remote-tracking branch 'upstream/dev' into fix/media-interactions 2023-10-13 15:03:57 +11:00
Morgan Pretty 89b38dc2f5
Merge pull request #928 from mpretty-cyro/fix/blocked-contacts-crash
Fixed a crash on the blocked contacts screen and refactoring
2023-10-12 16:15:54 +11:00
Morgan Pretty 638685a8cc
Merge pull request #925 from mpretty-cyro/fix/blank-display-name-handling
Fixed a bug where profiles with blank name values wouldn't fallback correctly
2023-10-12 16:15:36 +11:00
Morgan Pretty e427e59544
Merge pull request #926 from mpretty-cyro/fix/rare-multi-threading-crash
Fixed a crash which could occur when scrolling conversation messages
2023-10-12 16:15:10 +11:00
Morgan Pretty aec2aed81f
Merge pull request #927 from mpretty-cyro/fix/snode-info-deduping
Fixed an issue where the messages might not get reprocessed when they should
2023-10-12 16:14:30 +11:00
Morgan Pretty 4b9e15e5c1
Merge pull request #924 from mpretty-cyro/fix/theme-nav-issue
Fixed an issue where theme changes stopped updating nav styling
2023-10-12 16:13:42 +11:00
Morgan Pretty bd98db2612 Fixed a few bugs and crashes around media interactions
Fixed a crash when trying to grant permission to access additional photos
Fixed a bug where audio files would incorrectly get recognised as voice messages
Replaced our custom video/audio players with the native ones (which have additional built-in controls)
Updated the errors from SSKKeychainStorage to include useful information
Updated layout for audio attachments
2023-10-12 16:03:00 +11:00
Morgan Pretty b3eb78aaee Fixed the broken tests 2023-10-11 18:00:52 +11:00
Morgan Pretty f97170fdcd Fixed a crash on the blocked contacts screen and refactoring
Refactored the SessionThreadViewModel to reduce boilerplate and clean up the interface a little
Refactored the MessageRequestsViewController to use the SessionTableViewController
Fixed a crash when returning from the background on the BlockedContactsViewModel
Fixed some minor lag on the NotificationSoundViewModel
Added an optional initial loading message to the SessionTableViewController
2023-10-11 15:18:39 +11:00
Morgan Pretty 085a1a59aa Fixed an issue where the messages might not get reprocessed when they should
Dropped the auto-incrementing id from the SnodeReceivedMessageInfo
Changed the 'key, hash' from a uniqueKey to a primaryKey to allow "upsert" behaviours to work
2023-10-06 18:03:12 +11:00
Morgan Pretty 658240e549 Fixed a crash which could occur when scrolling conversation messages 2023-10-06 17:40:52 +11:00
Morgan Pretty 819106b0f2 Fixed a bug where profiles with blank name values wouldn't fallback correctly 2023-10-05 11:58:56 +11:00
Morgan Pretty 3a9ada581d Fixed an issue where theme changes stopped updating nav styling 2023-10-05 10:30:49 +11:00
Morgan Pretty 6d57523ede
Merge pull request #923 from mpretty-cyro/fix/apple-required-copy-change
Change the 'Grant Camera Access' copy to 'Continue' at Apple's request & Updated translations
2023-10-04 10:53:59 +11:00
Morgan Pretty 06f12a58b0 Change the 'Grant Camera Access' copy to 'Continue' at Apple's request
Updated translations again
2023-10-04 10:52:40 +11:00
Morgan Pretty 187902e48a
Merge pull request #861 from KeeJef/master
Update Session iOS screenshot
2023-10-04 09:35:00 +11:00
Morgan Pretty c81616c145
Merge pull request #922 from mpretty-cyro/fix/string-linter-for-archives
Fixed an issue where string validation was failing on archive builds
2023-10-04 09:31:44 +11:00
Morgan Pretty 8346a2e610 Fixed an issue where string validation was failing on archive builds 2023-10-04 09:31:08 +11:00
Morgan Pretty edfe0c35be
Merge pull request #921 from oxen-io/dev
Release 2.4.3
2023-10-03 14:09:54 +11:00
Morgan Pretty bd64d182f8
Merge pull request #920 from mpretty-cyro/fix/blocked-contacts-issues
Fix contacts missing from blocked contact list issue
2023-10-03 14:09:07 +11:00
Morgan Pretty ed33e1f2e2 Merge remote-tracking branch 'upstream/dev' into fix/blocked-contacts-issues 2023-10-03 13:43:57 +11:00
Morgan Pretty 2cff251e8d Fixed a bug with the blocked contacts list
Fixed a bug where blocked contacts without profile information wouldn't be included in the blocked contacts list
Fixed broken test build issues
Increased build and version numbers
2023-10-03 13:43:09 +11:00
Morgan Pretty 74f32e9ea3
Merge pull request #919 from mpretty-cyro/fix/add-migration-tests
Add migration tests
2023-10-03 13:41:20 +11:00
Morgan Pretty 9dd2e896bb Merge remote-tracking branch 'upstream/dev' into fix/add-migration-tests
# Conflicts:
#	SessionMessagingKit/SessionUtil/SessionUtil.swift
2023-10-03 12:53:35 +11:00
Morgan Pretty 4a95b4c921
Merge pull request #918 from mpretty-cyro/fix/onboarding-bugs
Fixed a couple of onboarding bugs and tweaks some logs
2023-10-03 12:52:45 +11:00
Morgan Pretty 42b49e0227 Added unit tests to verify migrations between all versions work
Fixed a busted test import
2023-10-03 12:52:29 +11:00
Morgan Pretty f9dc85b7ab Fixed a couple of onboarding bugs and tweaks some logs
Fixed an issue where starting and then restarting onboarding would get the app into an invalid state
Fixed an issue where newline characters could cause issues with parsing the recovery phrase
Added additional logs to better be able to understand the database state
2023-10-02 12:59:52 +11:00
Morgan Pretty 3dd626fa28
Merge pull request #915 from oxen-io/dev
Release 2.4.2 - RC 2
2023-09-26 08:59:56 +10:00
Morgan Pretty 0c5f3f2db9
Merge pull request #914 from mpretty-cyro/feature/rework-localized-string-validation
Refactored the LintLocalizableStrings
2023-09-26 08:58:40 +10:00
Morgan Pretty 655fcb5808 Minor log tweak 2023-09-26 08:57:12 +10:00
Morgan Pretty 5917cf103f Refactored the LintLocalizableStrings
Added inline errors & warnings (regex could use some work to remove invalid cases)
Added a build step to validate the strings are included in the app and it's extensions
2023-09-25 18:32:56 +10:00
Morgan Pretty bfc5375a30
Merge pull request #913 from mpretty-cyro/featutre/additional-strings-2
Added a couple of missing strings
2023-09-22 18:51:52 +10:00
Morgan Pretty cf159bdd77 Added a couple of missing strings 2023-09-22 18:51:26 +10:00
Morgan Pretty 34481b7f1d
Merge pull request #912 from mpretty-cyro/feature/additional-strings
Added additional new disappearing messages strings
2023-09-22 16:31:36 +10:00
Morgan Pretty 1d0733baa7 Added additional new disappearing messages strings 2023-09-22 16:30:55 +10:00
Morgan Pretty 9411d803cb
Merge pull request #911 from oxen-io/dev
Release 2.4.2
2023-09-22 15:34:28 +10:00
Morgan Pretty a6bd2676b0
Merge pull request #908 from mpretty-cyro/fix/xcode-15-build-issues
Started work fixing XCode 15 build issues
2023-09-22 15:05:46 +10:00
Morgan Pretty b280c0a852 Increased Build and Version Numbers and removed extra strings 2023-09-22 15:00:49 +10:00
Morgan Pretty 7628edbb1c Merge remote-tracking branch 'upstream/dev' into fix/xcode-15-build-issues 2023-09-22 14:52:45 +10:00
Morgan Pretty e6494d3432
Merge pull request #910 from mpretty-cyro/feature/translations-update
Updated to the latest translations from Crowdin
2023-09-22 14:52:13 +10:00
Morgan Pretty c4aadaff1c Fixed the broken tests and updated test dependencies
Properly fixed the busted migration issue
Updated to the latest version of Quick and Nimble (unit testing libraries)
Updated the tests based on the above
2023-09-22 14:49:39 +10:00
Morgan Pretty 20ce1deb23 Merge remote-tracking branch 'upstream/dev' into fix/xcode-15-build-issues 2023-09-22 12:16:02 +10:00
Morgan Pretty 323a7a1bce
Merge pull request #906 from mpretty-cyro/feature/add-timestamps-to-notification-metadata
Added additional notification metadata and rate-limited PN subscriptions
2023-09-22 11:33:57 +10:00
Morgan Pretty 134d257faf
Merge pull request #907 from mpretty-cyro/fix/incorrect-screen-popping
Fixed an issue where the conversation screen was dismissed incorrectly
2023-09-22 11:33:42 +10:00
Morgan Pretty dbfeaef006
Merge pull request #904 from RyanRory/fix-link-preview-image
Fix link preview
2023-09-22 11:00:58 +10:00
Morgan Pretty 8fee4edf34 Updated to the latest translations from Crowdin 2023-09-22 09:28:51 +10:00
Morgan Pretty 2310652407
Merge pull request #905 from vlzuykov/master
Add Ukrainian translation from Crowdin
2023-09-21 16:00:16 +10:00
Morgan Pretty 52836cff91 Fixed a couple more issues
Fixed an issue with the Emoji generation
Fixed the SessionThread 'isPinned' property
Fixed an issue when migrating from a pre 2.3.0 version to the latest version
2023-09-21 15:55:26 +10:00
Morgan Pretty cdf918194a Fixed an issue where XCode 15 would hang on launch due to being unable to retrieve a read lock 2023-09-21 13:43:11 +10:00
Morgan Pretty 4c934d2fda [WIP] Started work fixing XCode 15 build issues
Reworked the EmojiGenerator to structure the 'EmojiWithSkinTones+String" file as the original structure was causing XCode 15 to build forever
Reworked the seed node certificate loading in an effort to fix a crash
Updated to the latest version of webp
Commented out a line causing build issues
Fixed a number of build warnings
Fixed an issue which could cause migration issues when upgrading from certain old versions
2023-09-20 16:57:59 +10:00
Morgan Pretty f92579db07 Fixed a couple more bugs with link previews
Fixed an issue where sending a link with a preview wouldn't work if you have a previous "failed" preview for the same link
Fixed an issue where receiving a link with a preview could update all existing previews to an invalid state
2023-09-19 15:40:58 +10:00
Morgan Pretty 8cbd318cca Fixed an issue where the conversation screen was dismissed incorrectly
Fixed a bug where going to the settings screen in a conversation with no messages would pop to the conversation list
2023-09-19 10:27:49 +10:00
Morgan Pretty 8b1a4aaba0 Added additional notification metadata and rate-limited PN subscriptions
Fixed an issue where the PN subscription API call wasn't taking the frequency rate limit into account
Added the timestamp and expiration timestamp to the notification metadata
2023-09-19 10:15:57 +10:00
vlzuykov b9a5e0befb
Add files via upload 2023-09-16 12:45:41 +03:00
Ryan Zhao 5f25abc213 add paged database observer for link preview attachment 2023-09-14 15:12:37 +10:00
ryanzhao 5088e394f2 clean 2023-09-13 17:23:18 +10:00
Morgan Pretty 3cbe749d3c
Merge pull request #903 from oxen-io/dev
Release 4.2.1
2023-09-08 17:46:08 +10:00
Morgan Pretty 67ab1e5194 Increased the build number for RC build 2023-09-08 17:45:45 +10:00
Morgan Pretty 65acd79812
Merge pull request #902 from mpretty-cyro/fix/notification-extension-issues
Fixed a number of issues with the Notification Service Extension
2023-09-08 13:25:00 +10:00
Morgan Pretty a2f1f36d2c Fixed a number of issues with the Notification Service Extension
Fixed an issue where receiving a PN for outgoing messages could break the NotificationServiceExtension
Fixed an issue where the NotificationServiceExtension could startup in an invalid way resulting in subsequent PNs failing to process
Fixed an issue where you could incorrectly receive multiple generic notifications after receiving an incoming call notification
Fixed an issue where the read state syncing might not clear notifications from the notification center
Fixed an issue with parsing Bencoded data
Updated the PN subscription to subscribe to CONVO_INFO_VOLATILE notifications (update read state)
Updated the NotificationServiceExtension to use standard message processing where possible
Updated the NotificationServiceExtension to update the app badge based on a database query
2023-09-08 11:42:04 +10:00
Morgan Pretty fbae340bda
Merge pull request #901 from mpretty-cyro/fix/call-messages-not-marking-as-read
Fixed an issue where call messages wouldn't get marked as read when the last message in a conversation
2023-09-08 11:30:38 +10:00
Morgan Pretty b79de0cf32 Fixed an issue where call messages wouldn't get marked as read when the last message in a conversation 2023-09-08 11:04:47 +10:00
Morgan Pretty ab610578e6
Merge pull request #900 from mpretty-cyro/fix/media-detail-to-all-media-transition
Fixed an issue where tapping All Media on the media detail screen wasn't working
2023-09-08 10:28:58 +10:00
Morgan Pretty eaceabe217
Merge pull request #899 from mpretty-cyro/fix/media-picker-reload
Fixed an issue where the media picker wouldn't reload when changing image access
2023-09-08 10:28:41 +10:00
Morgan Pretty 5bdfd0e93c
Merge pull request #898 from mpretty-cyro/fix/quote-preview-x-alignment
Fixed a bug where the quote preview width could be too small
2023-09-08 10:28:21 +10:00
Morgan Pretty cbc1ab437b Fixed an issue where tapping All Media on the media detail screen wasn't working 2023-09-08 09:09:28 +10:00
Morgan Pretty c98af2386c Fixed an issue where the media picker wouldn't reload when changing image access 2023-09-08 08:50:41 +10:00
Morgan Pretty 260e9b0a43 Fixed a bug where the quote preview width could be too small 2023-09-07 17:39:46 +10:00
Morgan Pretty 862a6a8898
Merge pull request #887 from oxen-io/dev
Release 2.4.0
2023-09-05 16:15:08 +10:00
Morgan Pretty 45bee6fdf9
Merge pull request #897 from mpretty-cyro/fix/silly-build-issues
Fixed a few silly build issues
2023-09-04 11:55:21 +10:00
Morgan Pretty dc15586dd1 Fixed a few silly build issues 2023-09-04 11:20:15 +10:00
Morgan Pretty 1a10049f39
Merge pull request #895 from mpretty-cyro/fix/config-processing-issues
Fixed a couple of config handling bugs
2023-09-04 09:54:28 +10:00
Morgan Pretty 7a8941db5c Fixed a couple of config handling bugs
Fixed an bug where config messages could be processed in the wrong order
Tweaked the behaviour or removing threads (this would cause issues with future config-based settings changes that live on the thread getting lost)
2023-09-01 16:16:13 +10:00
Morgan Pretty 6d990559b7
Merge pull request #888 from mpretty-cyro/fix/minor-outgoing-quote-bugs
Fix a couple of minor bugs and clean up query interface
2023-08-30 13:57:49 +10:00
Morgan Pretty d71d07c430
Merge pull request #893 from mpretty-cyro/fix/acknowledgements
Added Cocoapod Acknowledgements
2023-08-30 13:38:16 +10:00
Morgan Pretty f3b2cc577c Fixed the settings bundle and added Cocoapod acknowledgements 2023-08-23 10:30:21 +10:00
Morgan Pretty dfdf843f66 Fixed a few more issues
Fixed an issue where tapping a remote notification wasn't opening the conversation
Fixed an issue where the Share Extension could fail due to not having a snode pool loaded
Fixed an issue where the Theme may not be applied at the right time in the Share extension
2023-08-21 16:13:17 +10:00
Morgan Pretty 252e85fef9 Fixed a bug where the swipe-to-reply wasn't moving the message status text 2023-08-18 16:14:25 +10:00
Morgan Pretty 8e28726fa7 Fixed a bug where unwritable conversations appeared in the share extension 2023-08-17 18:06:06 +10:00
Morgan Pretty e6c26e7ff4 Cleaned up the GRDB interface for complex queries 2023-08-17 16:39:47 +10:00
Morgan Pretty 42853a08c9 Fixed a couple of minor outgoing quote bugs
Added a nicer mechanism for using table aliases
Fixed a bug where the quote preview view close button could overlap the content
Fixed a bug where an outgoing quote wouldn't show it's thumbnail in some cases
Fixed a bug where quoting a link preview wouldn't show the link preview attachment
2023-08-17 11:28:03 +10:00
Morgan Pretty 968f50f2fc
Merge pull request #886 from mpretty-cyro/feature/blinded-message-request-setting
Community message request setting
2023-08-11 18:58:35 +10:00
Morgan Pretty 382b466ded Fixed a bug where conversations without messages could display invalid dates 2023-08-11 18:58:04 +10:00
Morgan Pretty ef5aa927a0 Added logic to use the setting if it's already been sent in a config
Added the ability to define requirements for migrations (in case some data or state needs to be loaded for a migration to be able to be performed correctly)
2023-08-11 18:48:14 +10:00
Morgan Pretty 9c9fb09254 Merge remote-tracking branch 'upstream/dev' into feature/blinded-message-request-setting
# Conflicts:
#	SessionMessagingKit/Configuration.swift
2023-08-11 18:29:33 +10:00
Morgan Pretty 26c6df78ab Fixed test compilation issues 2023-08-11 18:04:15 +10:00
Morgan Pretty 32527d7e83
Merge pull request #856 from mpretty-cyro/feature/updated-push-server
Updated Push Notification API Integration
2023-08-11 18:02:20 +10:00
Morgan Pretty d863004e6d Added a setting to control community message request polling
Added logic to broadcast the community message request acceptance to SOGS so we can communicate it to message request senders
Fixed an issue where database setting changes wouldn't trigger a live update on a settings screen
Fixed an issue where some setting toggles wouldn't animate the state change
Fixed a rarw force-unwrap crash
2023-08-11 18:02:06 +10:00
Morgan Pretty 9eb7a6af6d
Merge pull request #881 from mpretty-cyro/feature/make-user-config-permanent
Make Updated User Config Permanent
2023-08-11 17:59:38 +10:00
Morgan Pretty c63a9d3994 Fixed an issue preventing notifications from working
Fixed an issue where Storage could be left in an invalid state when it was completed silently before properly getting setup
2023-08-10 16:44:28 +10:00
Morgan Pretty 5285d81177 Fixed a few more PN logic issues
Sorted out some more threading issues
Removed a redundant SyncPushTokensJob run
Fixed an issue where the NotificationServiceExtension could incorrectly setup the database before setting up it's context
Fixed a few warnings
Removed a bunch of legacy code
Refactored the MainAppContext from Objective C into Swift
2023-08-10 14:43:40 +10:00
Morgan Pretty 49f2d3bfe2 Removed another couple of main thread assertions 2023-08-09 15:31:07 +10:00
Morgan Pretty 1a383ea850 Fixed a crash due to an assertion for encryption on the main thread
Removed some commented out code
2023-08-09 15:22:42 +10:00
Morgan Pretty 0e952b40bb Removed 'useSharedUtilForUserConfig' flag and most legacy config logic 2023-08-03 09:09:33 +10:00
Morgan Pretty 87668d86a1 Fixed an issue where the device might not reregister for push notifications 2023-08-02 14:35:59 +10:00
Morgan Pretty 18ee9d34fa Merge remote-tracking branch 'upstream/dev' into feature/updated-push-server
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	SessionMessagingKit/Open Groups/Types/SodiumProtocols.swift
#	SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift
#	SessionMessagingKitTests/_TestUtilities/MockAeadXChaCha20Poly1305Ietf.swift
#	SessionUtilitiesKit/JobRunner/JobRunner.swift
2023-08-02 14:35:16 +10:00
Morgan Pretty 4d098914b2
Merge pull request #813 from oxen-io/feature/job-runner-unit-tests
JobRunner unit tests
2023-08-02 14:13:04 +10:00
Morgan Pretty 0ac7f7b339 Remove double dash from suffix 2023-08-02 10:36:40 +10:00
Morgan Pretty ae0597a50f Attempt alternate config base approach 2023-08-02 10:02:54 +10:00
Morgan Pretty 3d755e7125 More CI debugging 2023-08-02 09:45:10 +10:00
Morgan Pretty b04867705f Testing values 2023-08-02 09:42:16 +10:00
Morgan Pretty a2c75465c1 Further CI logic tweaks 2023-08-02 09:39:52 +10:00
Morgan Pretty b9512d8c4f Tweaks to PR checking logic 2023-08-02 09:35:42 +10:00
Morgan Pretty eb3af31f0c Updated pipelines to be conditional based on logic instead of config 2023-08-02 09:34:02 +10:00
Morgan Pretty c76b391d68 CI structure tweak 2023-08-02 09:23:22 +10:00
Morgan Pretty 76b37c2ad6 Further tweaks to CI setup
Added a suffix to distinguish the output files for upload
Attempting to exclude the Sim and AppStore builds from PR builds (they can't upload anyway)
2023-08-02 09:16:39 +10:00
Morgan Pretty bf98199800 Another incorrect statement in the upload script 2023-08-01 17:07:21 +10:00
Morgan Pretty 66b94778e0 Fixed the build issues and a bug where a new legacy group wasn't subscribile 2023-08-01 16:30:34 +10:00
Morgan Pretty 635a5182bc Fixed a typo in the upload script 2023-08-01 16:21:02 +10:00
Morgan Pretty 1b0fda56ad Merge remote-tracking branch 'upstream/dev' into feature/updated-push-server
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Meta/AppDelegate.swift
#	Session/Meta/Translations/de.lproj/Localizable.strings
#	Session/Meta/Translations/en.lproj/Localizable.strings
#	Session/Meta/Translations/es.lproj/Localizable.strings
#	Session/Meta/Translations/fa.lproj/Localizable.strings
#	Session/Meta/Translations/fi.lproj/Localizable.strings
#	Session/Meta/Translations/fr.lproj/Localizable.strings
#	Session/Meta/Translations/hi.lproj/Localizable.strings
#	Session/Meta/Translations/hr.lproj/Localizable.strings
#	Session/Meta/Translations/id-ID.lproj/Localizable.strings
#	Session/Meta/Translations/it.lproj/Localizable.strings
#	Session/Meta/Translations/ja.lproj/Localizable.strings
#	Session/Meta/Translations/nl.lproj/Localizable.strings
#	Session/Meta/Translations/pl.lproj/Localizable.strings
#	Session/Meta/Translations/pt_BR.lproj/Localizable.strings
#	Session/Meta/Translations/ru.lproj/Localizable.strings
#	Session/Meta/Translations/si.lproj/Localizable.strings
#	Session/Meta/Translations/sk.lproj/Localizable.strings
#	Session/Meta/Translations/sv.lproj/Localizable.strings
#	Session/Meta/Translations/th.lproj/Localizable.strings
#	Session/Meta/Translations/vi-VN.lproj/Localizable.strings
#	Session/Meta/Translations/zh-Hant.lproj/Localizable.strings
#	Session/Meta/Translations/zh_CN.lproj/Localizable.strings
#	Session/Notifications/SyncPushTokensJob.swift
#	SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ClosedGroups.swift
#	SessionMessagingKit/Sending & Receiving/Message Handling/MessageSender+ClosedGroups.swift
#	SessionShareExtension/ShareNavController.swift
2023-08-01 16:05:36 +10:00
Morgan Pretty 2f05f3f3a2 Fixed a couple of invalid checks 2023-08-01 15:43:23 +10:00
Morgan Pretty 715a5b583f Fix a CI script typo 2023-08-01 15:38:23 +10:00
Morgan Pretty 2341fbf59f Further tweaks to CI scripts 2023-08-01 15:27:40 +10:00
Morgan Pretty 00aef6ca97 Attempt to handle an invalid pod manifest file 2023-08-01 15:01:16 +10:00
Morgan Pretty 15104da58e More CI tweaks 2023-08-01 14:48:02 +10:00
Morgan Pretty c29827356c Attempt to fix the cocoapods_cache lock logic to handle failures 2023-08-01 14:43:41 +10:00
Morgan Pretty b471a32209 Merge remote-tracking branch 'upstream/dev' into feature/job-runner-unit-tests
# Conflicts:
#	Session/Conversations/ConversationVC+Interaction.swift
#	SessionMessagingKit/Open Groups/OpenGroupAPI.swift
#	SessionMessagingKit/Open Groups/OpenGroupManager.swift
2023-08-01 14:39:00 +10:00
Morgan Pretty a41f1c1366 Fixed the broken tests
Cleaned up the Dependencies so that tests can run synchronously without having to custom set queues as much
Sorted out the crypto and network dependencies to avoid needing weird dependency inheritance
Fixed the flaky tests so they are no longer flaky
Fixed some unexpected JobRunner behaviours
Updated the CI config to use a local build directory for derivedData (now works with build tweaks)
2023-08-01 14:27:41 +10:00
ryanzhao 5464d9c97a fix import 2023-07-26 17:02:48 +10:00
RyanZhao 19beff509b
Merge pull request #864 from f-person/feat/all-orientations-for-ipad
feat: Enable upside down orientation for iPad
2023-07-25 16:54:54 +10:00
Morgan Pretty e768bebe6d Merge remote-tracking branch 'upstream/dev' into feature/job-runner-unit-tests
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Meta/Session-Prefix.pch
#	Session/Notifications/SyncPushTokensJob.swift
#	Session/Utilities/BackgroundPoller.swift
#	SessionMessagingKit/Configuration.swift
#	SessionMessagingKit/Database/Models/Profile.swift
#	SessionMessagingKit/Jobs/Types/AttachmentDownloadJob.swift
#	SessionMessagingKit/Jobs/Types/AttachmentUploadJob.swift
#	SessionMessagingKit/Jobs/Types/DisappearingMessagesJob.swift
#	SessionMessagingKit/Jobs/Types/FailedAttachmentDownloadsJob.swift
#	SessionMessagingKit/Jobs/Types/FailedMessageSendsJob.swift
#	SessionMessagingKit/Jobs/Types/GroupLeavingJob.swift
#	SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift
#	SessionMessagingKit/Jobs/Types/MessageSendJob.swift
#	SessionMessagingKit/Jobs/Types/NotifyPushServerJob.swift
#	SessionMessagingKit/Jobs/Types/RetrieveDefaultOpenGroupRoomsJob.swift
#	SessionMessagingKit/Jobs/Types/SendReadReceiptsJob.swift
#	SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift
#	SessionMessagingKit/Sending & Receiving/MessageSender.swift
#	SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift
#	SessionMessagingKit/Utilities/AppReadiness.m
#	SessionMessagingKitTests/Open Groups/OpenGroupManagerSpec.swift
#	SessionMessagingKitTests/_TestUtilities/TestOnionRequestAPI.swift
#	SessionShareExtension/ShareNavController.swift
#	SessionSnodeKit/Jobs/GetSnodePoolJob.swift
#	SessionUtilitiesKit/Configuration.swift
#	SessionUtilitiesKit/Database/Utilities/Database+Utilities.swift
#	SessionUtilitiesKit/JobRunner/JobRunner.swift
#	SignalUtilitiesKit/Meta/SignalUtilitiesKit.h
#	SignalUtilitiesKit/Utilities/SSKAsserts.h
2023-07-18 10:02:51 +10:00
Arshak Aghakaryan 57dbad7e2e fix: Initial glitch when picking a photo in upside-down orientation
This was caused by OWSViewController.IsLandscapeOrientationEnabled being
hard-coded to return `NO`. Now, whether or not landscape orientation is
enabled will be based on whether the current device is an iPad.
2023-07-10 07:42:28 +04:00
Arshak Aghakaryan fbdb1ad690 feat: Enable upside down orientation for iPad
The "upside down" orientation for iPad devices was disabled in
05814add86d765b83c91baa3120ba65569803906b55b159fbd091a95876e40a70d.
However, as an iPad user, not having all orientations is quite
uncomfortable and sometimes annoying. Most apps support all
orientations on iPad nowadays. This commit brings back the upside down
orientation in all places where it was disabled.
2023-07-10 07:17:24 +04:00
Morgan Pretty 0a638bf37b Fixed the broken JobRunner tests
Cleaned up the 'isRunningTests' logic so it isn't dependant on having an AppContext
2023-06-20 16:33:06 +10:00
Morgan Pretty c7d090251a Fixed an issue where subscribing to a new legacy group wouldn't have worked 2023-06-20 15:21:30 +10:00
Morgan Pretty 01d77a515c Fixed a signature generation issue 2023-06-20 12:42:54 +10:00
Morgan Pretty b3cad3e709 Added in the new legacy endpoint 2023-06-20 12:31:03 +10:00
Kee Jefferys 9f3d9cf7ab
Update Session iOS screenshot 2023-06-07 11:27:53 +10:00
Morgan Pretty 09ab977861 Updated the code to decode and use updated notifications
Made the JobQueue execution type explicit
Fixed a bug where legacy group's might not be unsubscribed from
2023-05-26 14:27:14 +10:00
Morgan Pretty fc94d24ddf Fixed up and added more unit tests to the JobRunner 2023-05-23 17:38:54 +10:00
Morgan Pretty 77b6faccb3 Merge remote-tracking branch 'upstream/dev' into feature/job-runner-unit-tests
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	SessionUtilitiesKit/Database/Models/Job.swift
#	SessionUtilitiesKit/Database/Models/JobDependencies.swift
#	SessionUtilitiesKit/JobRunner/JobRunner.swift
2023-05-23 09:52:42 +10:00
Morgan Pretty 61ad85b97b Added logic to unsubscribe for legacy one-to-one PNs 2023-05-22 10:57:16 +10:00
Morgan Pretty 4330a40f6f Started working on integrating the updated push APIs
Updated the PushNotificationAPI to be more consistent with the SnodeAPI and OpenGroupAPI structures
Updated the logic so if the database key can't be retrieved the app will no longer throw a fatalError (now just fail to initialise Storage and rely on the App/Extensions to properly handle this case)
Fixed a couple of bugs where the share extension wouldn't populate correctly
2023-05-19 17:26:14 +10:00
Morgan Pretty 4801ebd7c2 Merge remote-tracking branch 'upstream/dev' into feature/job-runner-unit-tests
# Conflicts:
#	SessionMessagingKit/Configuration.swift
#	SessionMessagingKit/Jobs/Types/AttachmentDownloadJob.swift
#	SessionMessagingKit/Jobs/Types/AttachmentUploadJob.swift
#	SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift
#	SessionMessagingKit/Jobs/Types/MessageSendJob.swift
#	SessionMessagingKit/Jobs/Types/NotifyPushServerJob.swift
#	SessionMessagingKit/Jobs/Types/SendReadReceiptsJob.swift
#	SessionUtilitiesKit/JobRunner/JobRunner.swift
2023-04-05 16:52:31 +10:00
Morgan Pretty ffdc59b704 Fixed a few issues with the JobRunner
Updated the JobRunner to support dependency injection
Updated the DataExtractionNotification to take a 'sentTimestamp' when created to reduce the chance for duplicates being sent
Fixed an issue where checking current and pending jobs wasn't including blocking jobs
Fixed an issue where the 'hasPendingOrRunningJob' check didn't actually include running jobs
Fixed some odd behaviours with job dependencies
Fixed an incorrect failure count check
2023-04-05 16:49:38 +10:00
Morgan Pretty cd00975e56 Merge remote-tracking branch 'origin/fix/xcode-14-3-compile-issue' into feature/job-runner-unit-tests 2023-04-04 12:14:02 +10:00
Morgan Pretty 3c526645a0 Merge remote-tracking branch 'upstream/dev' into feature/job-runner-unit-tests 2023-04-04 12:11:07 +10:00
Morgan Pretty a7af1ca768 Started laying the ground work for unit testing the JobRunnner
Starting injecting dependencies for the JobRunner
Turned the JobRunner into a singleton instance
2023-04-03 17:35:46 +10:00
483 changed files with 53063 additions and 30456 deletions

View File

@ -13,7 +13,9 @@ local ci_dep_mirror(want_mirror) = (if want_mirror then ' -DLOCAL_MIRROR=https:/
// 'LANG' env var so we need to work around the with https://github.com/CocoaPods/CocoaPods/issues/6333
local install_cocoapods = {
name: 'Install CocoaPods',
commands: ['LANG=en_US.UTF-8 pod install']
commands: ['
LANG=en_US.UTF-8 pod install || rm -rf ./Pods && LANG=en_US.UTF-8 pod install
']
};
// Load from the cached CocoaPods directory (to speed up the build)
@ -21,8 +23,14 @@ local load_cocoapods_cache = {
name: 'Load CocoaPods Cache',
commands: [
|||
LOOP_BREAK=0
while test -e /Users/drone/.cocoapods_cache.lock; do
sleep 1
LOOP_BREAK=$((LOOP_BREAK + 1))
if [[ $LOOP_BREAK -ge 600 ]]; then
rm -f /Users/drone/.cocoapods_cache.lock
fi
done
|||,
'touch /Users/drone/.cocoapods_cache.lock',
@ -31,7 +39,7 @@ local load_cocoapods_cache = {
cp -r /Users/drone/.cocoapods_cache ./Pods
fi
|||,
'rm /Users/drone/.cocoapods_cache.lock'
'rm -f /Users/drone/.cocoapods_cache.lock'
]
};
@ -40,8 +48,14 @@ local update_cocoapods_cache = {
name: 'Update CocoaPods Cache',
commands: [
|||
LOOP_BREAK=0
while test -e /Users/drone/.cocoapods_cache.lock; do
sleep 1
LOOP_BREAK=$((LOOP_BREAK + 1))
if [[ $LOOP_BREAK -ge 600 ]]; then
rm -f /Users/drone/.cocoapods_cache.lock
fi
done
|||,
'touch /Users/drone/.cocoapods_cache.lock',
@ -51,7 +65,7 @@ local update_cocoapods_cache = {
cp -r ./Pods /Users/drone/.cocoapods_cache
fi
|||,
'rm /Users/drone/.cocoapods_cache.lock'
'rm -f /Users/drone/.cocoapods_cache.lock'
]
};
@ -71,7 +85,7 @@ local update_cocoapods_cache = {
name: 'Run Unit Tests',
commands: [
'mkdir build',
'NSUnbufferedIO=YES set -o pipefail && xcodebuild test -workspace Session.xcworkspace -scheme Session -destination "platform=iOS Simulator,name=iPhone 14" -destination "platform=iOS Simulator,name=iPhone 14 Pro Max" -parallel-testing-enabled YES -test-timeouts-enabled YES -maximum-test-execution-time-allowance 2 -collect-test-diagnostics never 2>&1 | ./Pods/xcbeautify/xcbeautify --is-ci --report junit --report-path ./build/reports --junit-report-filename junit2.xml'
'NSUnbufferedIO=YES set -o pipefail && xcodebuild test -workspace Session.xcworkspace -scheme Session -derivedDataPath ./build/derivedData -destination "platform=iOS Simulator,name=iPhone 14" -destination "platform=iOS Simulator,name=iPhone 14 Pro Max" -parallel-testing-enabled YES -test-timeouts-enabled YES -maximum-test-execution-time-allowance 2 -collect-test-diagnostics never 2>&1 | ./Pods/xcbeautify/xcbeautify --is-ci --report junit --report-path ./build/reports --junit-report-filename junit2.xml'
],
},
update_cocoapods_cache
@ -83,6 +97,7 @@ local update_cocoapods_cache = {
type: 'exec',
name: 'Simulator Build',
platform: { os: 'darwin', arch: 'amd64' },
trigger: { event: { exclude: [ 'pull_request' ] } },
steps: [
clone_submodules,
load_cocoapods_cache,
@ -91,7 +106,7 @@ local update_cocoapods_cache = {
name: 'Build',
commands: [
'mkdir build',
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration "App Store Release" -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | ./Pods/xcbeautify/xcbeautify --is-ci'
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -derivedDataPath ./build/derivedData -configuration "App Store Release" -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | ./Pods/xcbeautify/xcbeautify --is-ci'
],
},
update_cocoapods_cache,
@ -110,6 +125,7 @@ local update_cocoapods_cache = {
type: 'exec',
name: 'AppStore Build',
platform: { os: 'darwin', arch: 'amd64' },
trigger: { event: { exclude: [ 'pull_request' ] } },
steps: [
clone_submodules,
load_cocoapods_cache,
@ -118,7 +134,7 @@ local update_cocoapods_cache = {
name: 'Build',
commands: [
'mkdir build',
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -configuration "App Store Release" -sdk iphoneos -archivePath ./build/Session.xcarchive -destination "generic/platform=iOS" -allowProvisioningUpdates'
'xcodebuild archive -workspace Session.xcworkspace -scheme Session -derivedDataPath ./build/derivedData -configuration "App Store Release" -sdk iphoneos -archivePath ./build/Session.xcarchive -destination "generic/platform=iOS" -allowProvisioningUpdates CODE_SIGNING_ALLOWED=NO | ./Pods/xcbeautify/xcbeautify --is-ci'
],
},
update_cocoapods_cache,

@ -1 +1 @@
Subproject commit d8f07fa92c12c5c2409774e03e03395d7847d1c2
Subproject commit e3ccf29db08aaf0b9bb6bbe72ae5967cd183a78d

View File

@ -13,22 +13,25 @@ PODS:
- DifferenceKit/Core
- GRDB.swift/SQLCipher (6.13.0):
- SQLCipher (>= 3.4.2)
- libwebp (1.2.1):
- libwebp/demux (= 1.2.1)
- libwebp/mux (= 1.2.1)
- libwebp/webp (= 1.2.1)
- libwebp/demux (1.2.1):
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp/webp
- libwebp/mux (1.2.1):
- libwebp/mux (1.3.2):
- libwebp/demux
- libwebp/webp (1.2.1)
- Nimble (10.0.0)
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- Nimble (12.3.0)
- NVActivityIndicatorView (5.1.1):
- NVActivityIndicatorView/Base (= 5.1.1)
- NVActivityIndicatorView/Base (5.1.1)
- OpenSSL-Universal (1.1.1300)
- PureLayout (3.1.9)
- Quick (5.0.1)
- Quick (7.3.0)
- Reachability (3.2)
- SAMKeychain (1.5.3)
- SignalCoreKit (1.0.0):
@ -134,18 +137,18 @@ SPEC REPOS:
- CocoaLumberjack
- DifferenceKit
- GRDB.swift
- libwebp
- Nimble
- NVActivityIndicatorView
- OpenSSL-Universal
- PureLayout
- Quick
- Reachability
- SAMKeychain
- SQLCipher
- SwiftProtobuf
- WebRTC-lib
trunk:
- libwebp
- Nimble
- Quick
- xcbeautify
EXTERNAL SOURCES:
@ -186,12 +189,12 @@ SPEC CHECKSUMS:
Curve25519Kit: e63f9859ede02438ae3defc5e1a87e09d1ec7ee6
DifferenceKit: ab185c4d7f9cef8af3fcf593e5b387fb81e999ca
GRDB.swift: fe420b1af49ec519c7e96e07887ee44f5dfa2b78
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
Nimble: 5316ef81a170ce87baf72dd961f22f89a602ff84
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
Nimble: f8a8219d16f176429b951e8f7e72df5c23ceddc0
NVActivityIndicatorView: 1f6c5687f1171810aa27a3296814dc2d7dec3667
OpenSSL-Universal: e7311447fd2419f57420c79524b641537387eff2
PureLayout: 5fb5e5429519627d60d079ccb1eaa7265ce7cf88
Quick: 749aa754fd1e7d984f2000fe051e18a3a9809179
Quick: d32871931c05547cb4e0bc9009d66a18b50d8558
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
SignalCoreKit: 1fbd8732163ef76de16cd1107d1fa3684b607e5d

View File

@ -6,7 +6,7 @@
Session integrates directly with [Oxen Service Nodes](https://docs.oxen.io/about-the-oxen-blockchain/oxen-service-nodes), which are a set of distributed, decentralized and Sybil resistant nodes. Service Nodes act as servers which store messages, and a set of nodes which allow for onion routing functionality obfuscating users' IP addresses. For a full understanding of how Session works, read the [Session Whitepaper](https://getsession.org/whitepaper).
<img src="https://i.imgur.com/SocRFTh.jpg" width="320" />
<img src="https://i.imgur.com/Ioub5bx.png" width="320" />
## Want to contribute? Found a bug or have a feature request?

View File

@ -1,4 +1,6 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
import CryptoKit

View File

@ -1,5 +1,11 @@
#!/usr/bin/env xcrun --sdk macosx swift
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
//
// This script is used to generate/update the set of Emoji used for reactions
//
// stringlint:disable
import Foundation
// OWSAssertionError but for this script
@ -250,6 +256,7 @@ extension EmojiGenerator {
// e.g. case grinning = "😀"
writeBlock(fileName: "Emoji.swift") { fileHandle in
fileHandle.writeLine("// swiftlint:disable all")
fileHandle.writeLine("// stringlint:disable")
fileHandle.writeLine("")
fileHandle.writeLine("/// A sorted representation of all available emoji")
fileHandle.writeLine("enum Emoji: String, CaseIterable, Equatable {")
@ -263,61 +270,186 @@ extension EmojiGenerator {
}
}
static func writeStringConversionsFile(from emojiModel: EmojiModel) {
// Inline helpers:
var firstItem = true
func conditionalCheckForEmojiItem(_ item: EmojiModel.EmojiDefinition.Emoji) -> String {
let isFirst = (firstItem == true)
firstItem = false
let prefix = isFirst ? "" : "} else "
let suffix = "if rawValue == \"\(item.emojiChar)\" {"
return prefix + suffix
}
func conversionForEmojiItem(_ item: EmojiModel.EmojiDefinition.Emoji, definition: EmojiModel.EmojiDefinition) -> String {
let skinToneString: String
if item.skintoneSequence.isEmpty {
skinToneString = "nil"
} else {
skinToneString = "[\(item.skintoneSequence.map { ".\($0)" }.joined(separator: ", "))]"
indirect enum Structure {
enum ChunkType {
case firstScalar
case scalarSum
func chunk(_ character: Character, into size: UInt32) -> UInt32 {
guard size > 0 else { return 0 }
let scalarValues: [UInt32] = character.unicodeScalars.map { $0.value }
switch self {
case .firstScalar: return (scalarValues.first.map { $0 / size } ?? 0)
case .scalarSum: return (scalarValues.reduce(0, +) / size)
}
}
func switchString(with variableName: String = "rawValue", size: UInt32) -> String {
switch self {
case .firstScalar: return "rawValue.unicodeScalars.map({ $0.value }).first.map({ $0 / \(size) })"
case .scalarSum: return "(rawValue.unicodeScalars.map({ $0.value }).reduce(0, +) / \(size))"
}
}
return "self.init(baseEmoji: .\(definition.enumName), skinTones: \(skinToneString))"
}
case ifElse // XCode 15 taking over 10 min with M1 Pro (gave up)
case switchStatement // XCode 15 taking over 10 min with M1 Pro (gave up)
case directLookup // XCode 15 taking 93 sec with M1 Pro
case chunked(UInt32, Structure, ChunkType) // XCode 15 taking <10 sec with M1 Pro (chunk by 100)
}
typealias ChunkedEmojiInfo = (
variant: EmojiModel.EmojiDefinition.Emoji,
baseName: String
)
static func writeStringConversionsFile(from emojiModel: EmojiModel) {
// This combination seems to have the smallest compile time (~2.2 sec out of all of the combinations)
let desiredStructure: Structure = .chunked(100, .directLookup, .scalarSum)
// Conversion from String: Creates an initializer mapping a single character emoji string to an EmojiWithSkinTones
// e.g.
// if rawValue == "😀" { self.init(baseEmoji: .grinning, skinTones: nil) }
// else if rawValue == "🦻🏻" { self.init(baseEmoji: .earWithHearingAid, skinTones: [.light])
writeBlock(fileName: "EmojiWithSkinTones+String.swift") { fileHandle in
fileHandle.writeLine("// swiftlint:disable all")
fileHandle.writeLine("// stringlint:disable")
fileHandle.writeLine("")
fileHandle.writeLine("extension EmojiWithSkinTones {")
fileHandle.indent {
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
emojiModel.definitions.forEach { definition in
definition.variants.forEach { emoji in
fileHandle.writeLine(conditionalCheckForEmojiItem(emoji))
fileHandle.indent {
fileHandle.writeLine(conversionForEmojiItem(emoji, definition: definition))
switch desiredStructure {
case .chunked(let chunkSize, let childStructure, let chunkType):
let chunkedEmojiInfo = emojiModel.definitions
.reduce(into: [UInt32: [ChunkedEmojiInfo]]()) { result, next in
next.variants.forEach { emoji in
let chunk: UInt32 = chunkType.chunk(emoji.emojiChar, into: chunkSize)
result[chunk] = ((result[chunk] ?? []) + [(emoji, next.enumName)])
.sorted { lhs, rhs in lhs.variant < rhs.variant }
}
}
.sorted { lhs, rhs in lhs.key < rhs.key }
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
fileHandle.writeLine("switch \(chunkType.switchString(size: chunkSize)) {")
fileHandle.indent {
chunkedEmojiInfo.forEach { chunk, _ in
fileHandle.writeLine("case \(chunk): self = EmojiWithSkinTones.emojiFrom\(chunk)(rawValue)")
}
fileHandle.writeLine("default: self = EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
}
}
fileHandle.writeLine("} else {")
fileHandle.indent {
fileHandle.writeLine("self.init(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
fileHandle.writeLine("}")
chunkedEmojiInfo.forEach { chunk, emojiInfo in
fileHandle.writeLine("")
fileHandle.writeLine("private static func emojiFrom\(chunk)(_ rawValue: String) -> EmojiWithSkinTones {")
fileHandle.indent {
switch emojiInfo.count {
case 0:
fileHandle.writeLine("return EmojiWithSkinTones(unsupportedValue: rawValue)")
default:
writeStructure(
childStructure,
for: emojiInfo,
using: fileHandle,
assignmentPrefix: "return "
)
}
}
fileHandle.writeLine("}")
}
default:
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
writeStructure(
desiredStructure,
for: emojiModel.definitions
.flatMap { definition in
definition.variants.map { ($0, definition.enumName) }
},
using: fileHandle
)
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
fileHandle.writeLine("// swiftlint:disable all")
}
}
private static func writeStructure(
_ structure: Structure,
for emojiInfo: [ChunkedEmojiInfo],
using fileHandle: WriteHandle,
assignmentPrefix: String = "self = "
) {
func initItem(_ info: ChunkedEmojiInfo) -> String {
let skinToneString: String = {
guard !info.variant.skintoneSequence.isEmpty else { return "nil" }
return "[\(info.variant.skintoneSequence.map { ".\($0)" }.joined(separator: ", "))]"
}()
return "EmojiWithSkinTones(baseEmoji: .\(info.baseName), skinTones: \(skinToneString))"
}
switch structure {
case .ifElse:
emojiInfo.enumerated().forEach { index, info in
switch index {
case 0: fileHandle.writeLine("if rawValue == \"\(info.variant.emojiChar)\" {")
default: fileHandle.writeLine("} else if rawValue == \"\(info.variant.emojiChar)\" {")
}
fileHandle.indent {
fileHandle.writeLine("\(assignmentPrefix)\(initItem(info))")
}
}
fileHandle.writeLine("} else {")
fileHandle.indent {
fileHandle.writeLine("\(assignmentPrefix)EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
case .switchStatement:
fileHandle.writeLine("switch rawValue {")
fileHandle.indent {
emojiInfo.forEach { info in
fileHandle.writeLine("case \"\(info.variant.emojiChar)\": \(assignmentPrefix)\(initItem(info))")
}
fileHandle.writeLine("default: \(assignmentPrefix)EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
case .directLookup:
fileHandle.writeLine("let lookup: [String: EmojiWithSkinTones] = [")
fileHandle.indent {
emojiInfo.enumerated().forEach { index, info in
let isLast: Bool = (index == (emojiInfo.count - 1))
fileHandle.writeLine("\"\(info.variant.emojiChar)\": \(initItem(info))\(isLast ? "" : ",")")
}
}
fileHandle.writeLine("]")
fileHandle.writeLine("\(assignmentPrefix)(lookup[rawValue] ?? EmojiWithSkinTones(unsupportedValue: rawValue))")
case .chunked: break // Provide one of the other types
}
}
static func writeSkinToneLookupFile(from emojiModel: EmojiModel) {
writeBlock(fileName: "Emoji+SkinTones.swift") { fileHandle in
fileHandle.writeLine("// swiftlint:disable all")
fileHandle.writeLine("// stringlint:disable")
fileHandle.writeLine("")
fileHandle.writeLine("extension Emoji {")
fileHandle.indent {
// SkinTone enum
@ -380,6 +512,7 @@ extension EmojiGenerator {
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
fileHandle.writeLine("// swiftlint:disable all")
}
}
@ -396,6 +529,9 @@ extension EmojiGenerator {
]
writeBlock(fileName: "Emoji+Category.swift") { fileHandle in
fileHandle.writeLine("// swiftlint:disable all")
fileHandle.writeLine("// stringlint:disable")
fileHandle.writeLine("")
fileHandle.writeLine("extension Emoji {")
fileHandle.indent {
@ -501,6 +637,7 @@ extension EmojiGenerator {
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
fileHandle.writeLine("// swiftlint:disable all")
}
}
@ -508,19 +645,23 @@ extension EmojiGenerator {
// Name lookup: Create a computed property mapping an Emoji enum element to the raw Emoji name string
// e.g. case .grinning: return "GRINNING FACE"
writeBlock(fileName: "Emoji+Name.swift") { fileHandle in
fileHandle.writeLine("// swiftlint:disable all")
fileHandle.writeLine("// stringlint:disable")
fileHandle.writeLine("")
fileHandle.writeLine("extension Emoji {")
fileHandle.indent {
fileHandle.writeLine("var name: String {")
fileHandle.indent {
fileHandle.writeLine("switch self {")
emojiModel.definitions.forEach {
fileHandle.writeLine("case .\($0.enumName): return \"\($0.shortNames.joined(separator:", "))\"")
fileHandle.writeLine("case .\($0.enumName): return \"\($0.shortNames.sorted().joined(separator:", "))\"")
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
fileHandle.writeLine("// swiftlint:disable all")
}
}
}

View File

@ -1,264 +1,573 @@
#!/usr/bin/xcrun --sdk macosx swift
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
//
// This script is based on https://github.com/ginowu7/CleanSwiftLocalizableExample the main difference
// is canges to the localized usage regex
//
// stringlint:disable
import Foundation
let fileManager = FileManager.default
let currentPath = (
ProcessInfo.processInfo.environment["PROJECT_DIR"] ?? fileManager.currentDirectoryPath
extension ProjectState {
/// Adding `// stringlint:disable` to the top of a source file (before imports) or after a string will mean that file/line gets
/// ignored by this script (good for some things like the auto-generated emoji strings or debug strings)
static let lintSuppression: String = "stringlint:disable"
static let primaryLocalisationFile: String = "en"
static let validLocalisationSuffixes: Set<String> = ["Localizable.strings"]
static let validSourceSuffixes: Set<String> = [".swift", ".m"]
static let excludedPaths: Set<String> = [
"build/", // Files under the build folder (CI)
"Pods/", // The pods folder
"Protos/", // The protobuf files
".xcassets/", // Asset bundles
".app/", // App build directories
".appex/", // Extension build directories
"tests/", // Exclude test directories
"_SharedTestUtilities/", // Exclude shared test directory
"external/" // External dependencies
]
static let excludedPhrases: Set<String> = [ "", " ", ",", ", ", "null" ]
static let excludedUnlocalisedStringLineMatching: Set<MatchType> = [
.contains(ProjectState.lintSuppression),
.prefix("#import"),
.prefix("@available("),
.contains("fatalError("),
.contains("precondition("),
.contains("preconditionFailure("),
.contains("print("),
.contains("NSLog("),
.contains("SNLog("),
.contains("SNLogNotTests("),
.contains("owsFailDebug("),
.contains("#imageLiteral(resourceName:"),
.contains("UIImage(named:"),
.contains("UIImage(systemName:"),
.contains("[UIImage imageNamed:"),
.contains("UIFont(name:"),
.contains(".dateFormat ="),
.contains(".accessibilityLabel ="),
.contains(".accessibilityValue ="),
.contains(".accessibilityIdentifier ="),
.contains("accessibilityIdentifier:"),
.contains("accessibilityLabel:"),
.contains("Accessibility(identifier:"),
.contains("Accessibility(label:"),
.contains("NSAttributedString.Key("),
.contains("Notification.Name("),
.contains("Notification.Key("),
.contains("DispatchQueue("),
.containsAnd("identifier:", .previousLine(numEarlier: 1, .contains("Accessibility("))),
.containsAnd("label:", .previousLine(numEarlier: 1, .contains("Accessibility("))),
.containsAnd("label:", .previousLine(numEarlier: 2, .contains("Accessibility("))),
.contains("SQL("),
.regex(".*static var databaseTableName: String"),
.regex("Logger\\..*\\("),
.regex("OWSLogger\\..*\\("),
.regex("case .* = "),
.regex("Error.*\\(")
]
}
// Execute the desired actions
let targetActions: Set<ScriptAction> = {
let args = CommandLine.arguments
// The first argument is the file name
guard args.count > 1 else { return [.lintStrings] }
return Set(args.suffix(from: 1).map { (ScriptAction(rawValue: $0) ?? .lintStrings) })
}()
print("------------ Searching Through Files ------------")
let projectState: ProjectState = ProjectState(
path: (
ProcessInfo.processInfo.environment["PROJECT_DIR"] ??
FileManager.default.currentDirectoryPath
),
loadSourceFiles: targetActions.contains(.lintStrings)
)
print("------------ Processing \(projectState.localizationFiles.count) Localization File(s) ------------")
targetActions.forEach { $0.perform(projectState: projectState) }
/// List of files in currentPath - recursive
var pathFiles: [String] = {
guard
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(
at: URL(fileURLWithPath: currentPath),
includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles]
),
let fileUrls: [URL] = enumerator.allObjects as? [URL]
else { fatalError("Could not locate files in path directory: \(currentPath)") }
// MARK: - ScriptAction
enum ScriptAction: String {
case validateFilesCopied = "validate"
case lintStrings = "lint"
return fileUrls
.filter {
((try? $0.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == false) && // No directories
!$0.path.contains("build/") && // Exclude files under the build folder (CI)
!$0.path.contains("Pods/") && // Exclude files under the pods folder
!$0.path.contains(".xcassets") && // Exclude asset bundles
!$0.path.contains(".app/") && // Exclude files in the app build directories
!$0.path.contains(".appex/") && // Exclude files in the extension build directories
!$0.path.localizedCaseInsensitiveContains("tests/") && // Exclude files under test directories
!$0.path.localizedCaseInsensitiveContains("external/") && ( // Exclude files under external directories
// Only include relevant files
$0.path.hasSuffix("Localizable.strings") ||
NSString(string: $0.path).pathExtension == "swift" ||
NSString(string: $0.path).pathExtension == "m"
)
}
.map { $0.path }
}()
/// List of localizable files - not including Localizable files in the Pods
var localizableFiles: [String] = {
return pathFiles.filter { $0.hasSuffix("Localizable.strings") }
}()
/// List of executable files
var executableFiles: [String] = {
return pathFiles.filter {
$0.hasSuffix(".swift") ||
$0.hasSuffix(".m")
}
}()
/// Reads contents in path
///
/// - Parameter path: path of file
/// - Returns: content in file
func contents(atPath path: String) -> String {
guard let data = fileManager.contents(atPath: path), let content = String(data: data, encoding: .utf8) else {
fatalError("Could not read from path: \(path)")
}
return content
}
/// Returns a list of strings that match regex pattern from content
///
/// - Parameters:
/// - pattern: regex pattern
/// - content: content to match
/// - Returns: list of results
func regexFor(_ pattern: String, content: String) -> [String] {
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
fatalError("Regex not formatted correctly: \(pattern)")
}
let matches = regex.matches(in: content, options: [], range: NSRange(location: 0, length: content.utf16.count))
return matches.map {
guard let range = Range($0.range(at: 0), in: content) else {
fatalError("Incorrect range match")
}
return String(content[range])
}
}
func create() -> [LocalizationStringsFile] {
return localizableFiles.map(LocalizationStringsFile.init(path:))
}
///
///
/// - Returns: A list of LocalizationCodeFile - contains path of file and all keys in it
func localizedStringsInCode() -> [LocalizationCodeFile] {
return executableFiles.compactMap {
let content = contents(atPath: $0)
// Note: Need to exclude escaped quotation marks from strings
let matchesOld = regexFor("(?<=NSLocalizedString\\()\\s*\"(?!.*?%d)(.*?)\"", content: content)
let matchesNew = regexFor("\"(?!.*?%d)([^(\\\")]*?)\"(?=\\s*)(?=\\.localized)", content: content)
let allMatches = (matchesOld + matchesNew)
return allMatches.isEmpty ? nil : LocalizationCodeFile(path: $0, keys: Set(allMatches))
}
}
/// Throws error if ALL localizable files does not have matching keys
///
/// - Parameter files: list of localizable files to validate
func validateMatchKeys(_ files: [LocalizationStringsFile]) {
guard let base = files.first, files.count > 1 else { return }
let files = Array(files.dropFirst())
files.forEach {
guard let extraKey = Set(base.keys).symmetricDifference($0.keys).first else { return }
let incorrectFile = $0.keys.contains(extraKey) ? $0 : base
printPretty("error: Found extra key: \(extraKey) in file: \(incorrectFile.path)")
}
}
/// Throws error if localizable files are missing keys
///
/// - Parameters:
/// - codeFiles: Array of LocalizationCodeFile
/// - localizationFiles: Array of LocalizableStringFiles
func validateMissingKeys(_ codeFiles: [LocalizationCodeFile], localizationFiles: [LocalizationStringsFile]) {
guard let baseFile = localizationFiles.first else {
fatalError("Could not locate base localization file")
}
let baseKeys = Set(baseFile.keys)
codeFiles.forEach {
let extraKeys = $0.keys.subtracting(baseKeys)
if !extraKeys.isEmpty {
printPretty("error: Found keys in code missing in strings file: \(extraKeys) from \($0.path)")
}
}
}
/// Throws warning if keys exist in localizable file but are not being used
///
/// - Parameters:
/// - codeFiles: Array of LocalizationCodeFile
/// - localizationFiles: Array of LocalizableStringFiles
func validateDeadKeys(_ codeFiles: [LocalizationCodeFile], localizationFiles: [LocalizationStringsFile]) {
guard let baseFile = localizationFiles.first else {
fatalError("Could not locate base localization file")
}
let baseKeys: Set<String> = Set(baseFile.keys)
let allCodeFileKeys: [String] = codeFiles.flatMap { $0.keys }
let deadKeys: [String] = Array(baseKeys.subtracting(allCodeFileKeys))
.sorted()
.map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) }
if !deadKeys.isEmpty {
printPretty("warning: \(deadKeys) - Suggest cleaning dead keys")
}
}
protocol Pathable {
var path: String { get }
}
struct LocalizationStringsFile: Pathable {
let path: String
let kv: [String: String]
let duplicates: [(key: String, path: String)]
var keys: [String] {
return Array(kv.keys)
}
init(path: String) {
let result = ContentParser.parse(path)
self.path = path
self.kv = result.kv
self.duplicates = result.duplicates
}
/// Writes back to localizable file with sorted keys and removed whitespaces and new lines
func cleanWrite() {
print("------------ Sort and remove whitespaces: \(path) ------------")
let content = kv.keys.sorted().map { "\($0) = \(kv[$0]!);" }.joined(separator: "\n")
try! content.write(toFile: path, atomically: true, encoding: .utf8)
}
}
struct LocalizationCodeFile: Pathable {
let path: String
let keys: Set<String>
}
struct ContentParser {
/// Parses contents of a file to localizable keys and values - Throws error if localizable file have duplicated keys
///
/// - Parameter path: Localizable file paths
/// - Returns: localizable key and value for content at path
static func parse(_ path: String) -> (kv: [String: String], duplicates: [(key: String, path: String)]) {
let content = contents(atPath: path)
let trimmed = content
.replacingOccurrences(of: "\n+", with: "", options: .regularExpression, range: nil)
.trimmingCharacters(in: .whitespacesAndNewlines)
let keys = regexFor("\"([^\"]*?)\"(?= =)", content: trimmed)
let values = regexFor("(?<== )\"(.*?)\"(?=;)", content: trimmed)
if keys.count != values.count {
fatalError("Error parsing contents: Make sure all keys and values are in correct format (this could be due to extra spaces between keys and values)")
}
var duplicates: [(key: String, path: String)] = []
let kv: [String: String] = zip(keys, values)
.reduce(into: [:]) { results, keyValue in
guard results[keyValue.0] == nil else {
duplicates.append((keyValue.0, path))
return
func perform(projectState: ProjectState) {
// Perform the action
switch self {
case .validateFilesCopied:
print("------------ Checking Copied Files ------------")
guard
let builtProductsPath: String = ProcessInfo.processInfo.environment["BUILT_PRODUCTS_DIR"],
let productName: String = ProcessInfo.processInfo.environment["FULL_PRODUCT_NAME"],
let productPathInfo = try? URL(fileURLWithPath: "\(builtProductsPath)/\(productName)")
.resourceValues(forKeys: [.isSymbolicLinkKey, .isAliasFileKey]),
let finalProductUrl: URL = try? { () -> URL in
let possibleAliasUrl: URL = URL(fileURLWithPath: "\(builtProductsPath)/\(productName)")
guard productPathInfo.isSymbolicLink == true || productPathInfo.isAliasFile == true else {
return possibleAliasUrl
}
return try URL(resolvingAliasFileAt: possibleAliasUrl, options: URL.BookmarkResolutionOptions())
}(),
let enumerator: FileManager.DirectoryEnumerator = FileManager.default.enumerator(
at: finalProductUrl,
includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles]
),
let fileUrls: [URL] = enumerator.allObjects as? [URL]
else { return Output.error("Could not retrieve list of files within built product") }
let localizationFiles: Set<String> = Set(fileUrls
.filter { $0.path.hasSuffix(".lproj") }
.map { $0.lastPathComponent.replacingOccurrences(of: ".lproj", with: "") })
let missingFiles: Set<String> = Set(projectState.localizationFiles
.map { $0.name })
.subtracting(localizationFiles)
guard missingFiles.isEmpty else {
return Output.error("Translations missing from \(productName): \(missingFiles.joined(separator: ", "))")
}
break
case .lintStrings:
guard !projectState.localizationFiles.isEmpty else {
return print("------------ Nothing to lint ------------")
}
results[keyValue.0] = keyValue.1
}
// Add warnings for any duplicate keys
projectState.localizationFiles.forEach { file in
// Show errors for any duplicates
file.duplicates.forEach { phrase, original in Output.duplicate(phrase, original: original) }
// Show warnings for any phrases missing from the file
let allKeys: Set<String> = Set(file.keyPhrase.keys)
let missingKeysFromOtherFiles: [String: [String]] = projectState.localizationFiles.reduce(into: [:]) { result, otherFile in
guard otherFile.path != file.path else { return }
let missingKeys: Set<String> = Set(otherFile.keyPhrase.keys)
.subtracting(allKeys)
missingKeys.forEach { missingKey in
result[missingKey] = ((result[missingKey] ?? []) + [otherFile.name])
}
}
missingKeysFromOtherFiles.forEach { missingKey, namesOfFilesItWasFound in
Output.warning(file, "Phrase '\(missingKey)' is missing (found in: \(namesOfFilesItWasFound.joined(separator: ", ")))")
}
}
// Process the source code
print("------------ Processing \(projectState.sourceFiles.count) Source File(s) ------------")
let allKeys: Set<String> = Set(projectState.primaryLocalizationFile.keyPhrase.keys)
projectState.sourceFiles.forEach { file in
// Add logs for unlocalised strings
file.unlocalizedPhrases.forEach { phrase in
Output.warning(phrase, "Found unlocalized string '\(phrase.key)'")
}
// Add errors for missing localised strings
let missingKeys: Set<String> = Set(file.keyPhrase.keys).subtracting(allKeys)
missingKeys.forEach { key in
switch file.keyPhrase[key] {
case .some(let phrase): Output.error(phrase, "Localized phrase '\(key)' missing from strings files")
case .none: Output.error(file, "Localized phrase '\(key)' missing from strings files")
}
}
}
break
}
return (kv, duplicates)
print("------------ Complete ------------")
}
}
func printPretty(_ string: String) {
print(string.replacingOccurrences(of: "\\", with: ""))
// MARK: - Functionality
enum Regex {
/// Returns a list of strings that match regex pattern from content
///
/// - Parameters:
/// - pattern: regex pattern
/// - content: content to match
/// - Returns: list of results
static func matches(_ pattern: String, content: String) -> [String] {
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
fatalError("Regex not formatted correctly: \(pattern)")
}
let matches = regex.matches(in: content, options: [], range: NSRange(location: 0, length: content.utf16.count))
return matches.map {
guard let range = Range($0.range(at: 0), in: content) else {
fatalError("Incorrect range match")
}
return String(content[range])
}
}
}
// MARK: - Processing
// MARK: - Output
let stringFiles: [LocalizationStringsFile] = create()
if !stringFiles.isEmpty {
print("------------ Found \(stringFiles.count) file(s) - checking for duplicate, extra, missing and dead keys ------------")
enum Output {
static func error(_ error: String) {
print("error: \(error)")
}
stringFiles.forEach { file in
file.duplicates.forEach { key, path in
printPretty("error: Found duplicate key: \(key) in file: \(path)")
static func error(_ location: Locatable, _ error: String) {
print("\(location.location): error: \(error)")
}
static func warning(_ location: Locatable, _ warning: String) {
print("\(location.location): warning: \(warning)")
}
static func duplicate(
_ duplicate: KeyedLocatable,
original: KeyedLocatable
) {
print("\(duplicate.location): error: duplicate key '\(original.key)'")
// Looks like the `note:` doesn't work the same as when XCode does it unfortunately so we can't
// currently include the reference to the original entry
// print("\(original.location): note: previously found here")
}
}
// MARK: - ProjectState
struct ProjectState {
let primaryLocalizationFile: LocalizationStringsFile
let localizationFiles: [LocalizationStringsFile]
let sourceFiles: [SourceFile]
init(path: String, loadSourceFiles: Bool) {
guard
let enumerator: FileManager.DirectoryEnumerator = FileManager.default.enumerator(
at: URL(fileURLWithPath: path),
includingPropertiesForKeys: [.isDirectoryKey],
options: [.skipsHiddenFiles]
),
let fileUrls: [URL] = enumerator.allObjects as? [URL]
else { fatalError("Could not locate files in path directory: \(path)") }
// Get a list of valid URLs
let lowerCaseExcludedPaths: Set<String> = Set(ProjectState.excludedPaths.map { $0.lowercased() })
let validFileUrls: [URL] = fileUrls.filter { fileUrl in
((try? fileUrl.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == false) &&
!lowerCaseExcludedPaths.contains { fileUrl.path.lowercased().contains($0) }
}
// Localization files
let targetFileSuffixes: Set<String> = Set(ProjectState.validLocalisationSuffixes.map { $0.lowercased() })
self.localizationFiles = validFileUrls
.filter { fileUrl in targetFileSuffixes.contains { fileUrl.path.lowercased().contains($0) } }
.map { LocalizationStringsFile(path: $0.path) }
guard let primaryLocalizationFile: LocalizationStringsFile = self.localizationFiles.first(where: { $0.name == ProjectState.primaryLocalisationFile }) else {
fatalError("Could not locate primary localization file: \(ProjectState.primaryLocalisationFile)")
}
self.primaryLocalizationFile = primaryLocalizationFile
guard loadSourceFiles else {
self.sourceFiles = []
return
}
// Source files
let lowerCaseSourceSuffixes: Set<String> = Set(ProjectState.validSourceSuffixes.map { $0.lowercased() })
self.sourceFiles = validFileUrls
.filter { fileUrl in lowerCaseSourceSuffixes.contains(".\(fileUrl.pathExtension)") }
.compactMap { SourceFile(path: $0.path) }
}
}
protocol Locatable {
var location: String { get }
}
protocol KeyedLocatable: Locatable {
var key: String { get }
}
extension ProjectState {
// MARK: - LocalizationStringsFile
struct LocalizationStringsFile: Locatable {
struct Phrase: KeyedLocatable {
let key: String
let value: String
let filePath: String
let lineNumber: Int
var location: String { "\(filePath):\(lineNumber)" }
}
let name: String
let path: String
let keyPhrase: [String: Phrase]
let duplicates: [(Phrase, original: Phrase)]
var location: String { path }
init(path: String) {
let result = LocalizationStringsFile.parse(path)
self.name = (path
.replacingOccurrences(of: "/Localizable.strings", with: "")
.replacingOccurrences(of: ".lproj", with: "")
.components(separatedBy: "/")
.last ?? "Unknown")
self.path = path
self.keyPhrase = result.keyPhrase
self.duplicates = result.duplicates
}
static func parse(_ path: String) -> (keyPhrase: [String: Phrase], duplicates: [(Phrase, original: Phrase)]) {
guard
let data: Data = FileManager.default.contents(atPath: path),
let content: String = String(data: data, encoding: .utf8)
else { fatalError("Could not read from path: \(path)") }
let lines: [String] = content.components(separatedBy: .newlines)
var duplicates: [(Phrase, original: Phrase)] = []
var keyPhrase: [String: Phrase] = [:]
lines.enumerated().forEach { lineNumber, line in
guard
let key: String = Regex.matches("\"([^\"]*?)\"(?= =)", content: line).first,
let value: String = Regex.matches("(?<== )\"(.*?)\"(?=;)", content: line).first
else { return }
// Remove the quotation marks around the key
let trimmedKey: String = String(key
.prefix(upTo: key.index(before: key.endIndex))
.suffix(from: key.index(after: key.startIndex)))
// Files are 1-indexed but arrays are 0-indexed so add 1 to the lineNumber
let result: Phrase = Phrase(
key: trimmedKey,
value: value,
filePath: path,
lineNumber: (lineNumber + 1)
)
switch keyPhrase[trimmedKey] {
case .some(let original): duplicates.append((result, original))
case .none: keyPhrase[trimmedKey] = result
}
}
return (keyPhrase, duplicates)
}
}
validateMatchKeys(stringFiles)
// Note: Uncomment the below file to clean out all comments from the localizable file (we don't want this because comments make it readable...)
// stringFiles.forEach { $0.cleanWrite() }
let codeFiles: [LocalizationCodeFile] = localizedStringsInCode()
validateMissingKeys(codeFiles, localizationFiles: stringFiles)
validateDeadKeys(codeFiles, localizationFiles: stringFiles)
// MARK: - SourceFile
struct SourceFile: Locatable {
struct Phrase: KeyedLocatable {
let term: String
let filePath: String
let lineNumber: Int
var key: String { term }
var location: String { "\(filePath):\(lineNumber)" }
}
let path: String
let keyPhrase: [String: Phrase]
let unlocalizedKeyPhrase: [String: Phrase]
let phrases: [Phrase]
let unlocalizedPhrases: [Phrase]
var location: String { path }
init?(path: String) {
guard let result = SourceFile.parse(path) else { return nil }
self.path = path
self.keyPhrase = result.keyPhrase
self.unlocalizedKeyPhrase = result.unlocalizedKeyPhrase
self.phrases = result.phrases
self.unlocalizedPhrases = result.unlocalizedPhrases
}
static func parse(_ path: String) -> (keyPhrase: [String: Phrase], phrases: [Phrase], unlocalizedKeyPhrase: [String: Phrase], unlocalizedPhrases: [Phrase])? {
guard
let data: Data = FileManager.default.contents(atPath: path),
let content: String = String(data: data, encoding: .utf8)
else { fatalError("Could not read from path: \(path)") }
// If the file has the lint supression before the first import then ignore the file
let preImportContent: String = (content.components(separatedBy: "import").first ?? "")
guard !preImportContent.contains(ProjectState.lintSuppression) else {
print("Explicitly ignoring \(path)")
return nil
}
// Otherwise continue and process the file
let lines: [String] = content.components(separatedBy: .newlines)
var keyPhrase: [String: Phrase] = [:]
var unlocalizedKeyPhrase: [String: Phrase] = [:]
var phrases: [Phrase] = []
var unlocalizedPhrases: [Phrase] = []
lines.enumerated().forEach { lineNumber, line in
let trimmedLine: String = line.trimmingCharacters(in: .whitespacesAndNewlines)
// Ignore the line if it doesn't contain a quotation character (optimisation), it's
// been suppressed or it's explicitly excluded due to the rules at the top of the file
guard
trimmedLine.contains("\"") &&
!ProjectState.excludedUnlocalisedStringLineMatching
.contains(where: { $0.matches(trimmedLine, lineNumber, lines) })
else { return }
// Split line based on commented out content and exclude the comment from the linting
let commentMatches: [String] = Regex.matches(
"//[^\\\"]*(?:\\\"[^\\\"]*\\\"[^\\\"]*)*",
content: line
)
let targetLine: String = (commentMatches.isEmpty ? line :
line.components(separatedBy: commentMatches[0])[0]
)
// Use regex to find `NSLocalizedString("", "")`, `"".localised()` and any other `""`
// values in the source code
//
// Note: It's more complex because we need to exclude escaped quotation marks from
// strings and also want to ignore any strings that have been commented out, Swift
// also doesn't support "lookbehind" in regex so we can use that approach
var isUnlocalized: Bool = false
var allMatches: Set<String> = Set(
Regex
.matches(
"NSLocalizedString\\(@{0,1}\\\"[^\\\"\\\\]*(?:\\\\.[^\\\"\\\\]*)*(?:\\\")",
content: targetLine
)
.map { match in
match
.removingPrefixIfPresent("NSLocalizedString(@\"")
.removingPrefixIfPresent("NSLocalizedString(\"")
.removingSuffixIfPresent("\")")
.removingSuffixIfPresent("\"")
}
)
// If we didn't get any matches for the standard `NSLocalizedString` then try our
// custom extension `"".localized()`
if allMatches.isEmpty {
allMatches = allMatches.union(Set(
Regex
.matches(
"\\\"[^\\\"\\\\]*(?:\\\\.[^\\\"\\\\]*)*\\\"\\.localized",
content: targetLine
)
.map { match in
match
.removingPrefixIfPresent("\"")
.removingSuffixIfPresent("\".localized")
}
))
}
/// If we still don't have any matches then try to match any strings as unlocalized strings (handling
/// nested `"Test\"string\" value"`, empty strings and strings only composed of quotes `"""""""`)
///
/// **Note:** While it'd be nice to have the regex automatically exclude the quotes doing so makes it _far_ less
/// efficient (approx. by a factor of 8 times) so we remove those ourselves)
if allMatches.isEmpty {
// Find strings which are just not localised
let potentialUnlocalizedStrings: [String] = Regex
.matches("\\\"[^\\\"\\\\]*(?:\\\\.[^\\\"\\\\]*)*(?:\\\")", content: targetLine)
// Remove the leading and trailing quotation marks
.map { $0.removingPrefixIfPresent("\"").removingSuffixIfPresent("\"") }
// Remove any empty strings
.filter { !$0.isEmpty }
// Remove any string conversations (ie. `.map { "\($0)" }`
.filter { value in !value.hasPrefix("\\(") || !value.hasSuffix(")") }
allMatches = allMatches.union(Set(potentialUnlocalizedStrings))
isUnlocalized = true
}
// Remove any excluded phrases from the matches
allMatches = allMatches.subtracting(ProjectState.excludedPhrases.map { "\($0)" })
allMatches.forEach { match in
// Files are 1-indexed but arrays are 0-indexed so add 1 to the lineNumber
let result: Phrase = Phrase(
term: match,
filePath: path,
lineNumber: (lineNumber + 1)
)
if !isUnlocalized {
keyPhrase[match] = result
phrases.append(result)
}
else {
unlocalizedKeyPhrase[match] = result
unlocalizedPhrases.append(result)
}
}
}
return (keyPhrase, phrases, unlocalizedKeyPhrase, unlocalizedPhrases)
}
}
}
print("------------ Complete ------------")
indirect enum MatchType: Hashable {
case prefix(String)
case contains(String)
case containsAnd(String, MatchType)
case regex(String)
case previousLine(numEarlier: Int, MatchType)
func matches(_ value: String, _ index: Int, _ lines: [String]) -> Bool {
switch self {
case .prefix(let prefix):
return value
.trimmingCharacters(in: .whitespacesAndNewlines)
.hasPrefix(prefix)
case .contains(let other): return value.contains(other)
case .containsAnd(let other, let otherMatch):
guard value.contains(other) else { return false }
return otherMatch.matches(value, index, lines)
case .regex(let regex): return !Regex.matches(regex, content: value).isEmpty
case .previousLine(let numEarlier, let type):
guard index >= numEarlier else { return false }
let targetIndex: Int = (index - numEarlier)
return type.matches(lines[targetIndex], targetIndex, lines)
}
}
}
extension String {
func removingPrefixIfPresent(_ value: String) -> String {
guard hasPrefix(value) else { return self }
return String(self.suffix(from: self.index(self.startIndex, offsetBy: value.count)))
}
func removingSuffixIfPresent(_ value: String) -> String {
guard hasSuffix(value) else { return self }
return String(self.prefix(upTo: self.index(self.endIndex, offsetBy: -value.count)))
}
}

View File

@ -572,7 +572,7 @@ public func serializedData() throws -> Data {
# if self.can_field_be_optional(field):
writer.add('guard proto.%s else {' % field.has_accessor_name() )
writer.push_indent()
writer.add('throw %s.invalidProtobuf(description: "\(logTag) missing required field: %s")' % ( writer.invalid_protobuf_error_name, field.name_swift, ) )
writer.add('throw %s.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: %s")' % ( writer.invalid_protobuf_error_name, field.name_swift, ) )
writer.pop_indent()
writer.add('}')

View File

@ -3,8 +3,6 @@
# Script used with Drone CI to upload build artifacts (because specifying all this in
# .drone.jsonnet is too painful).
set -o errexit
if [ -z "$SSH_KEY" ]; then
@ -19,33 +17,36 @@ set -o xtrace # Don't start tracing until *after* we write the ssh key
chmod 600 ssh_key
if [ -n "$DRONE_TAG" ]; then
# For a tag build use something like `session-ios-v1.2.3`
base="session-ios-$DRONE_TAG"
else
# Otherwise build a length name from the datetime and commit hash, such as:
# session-ios-20200522T212342Z-04d7dcc54
base="session-ios-$(date --date=@$DRONE_BUILD_CREATED +%Y%m%dT%H%M%SZ)-${DRONE_COMMIT:0:9}"
fi
mkdir -v "$base"
# Copy over the build products
# Define the output paths
prod_path="build/Session.xcarchive"
sim_path="build/Session_sim.xcarchive/Products/Applications/Session.app"
mkdir build
echo "Test" > "build/test.txt"
if [ ! -d $prod_path ]; then
cp -av $prod_path "$base"
else if [ ! -d $sim_path ]; then
cp -av $sim_path "$base"
# Validate the paths exist
if [ -d $prod_path ]; then
suffix="store"
target_path=$prod_path
elif [ -d $sim_path ]; then
suffix="sim"
target_path=$sim_path
else
echo "Expected a file to upload, found none" >&2
echo -e "\n\n\n\e[31;1mExpected a file to upload, found none\e[0m" >&2
exit 1
fi
if [ -n "$DRONE_TAG" ]; then
# For a tag build use something like `session-ios-v1.2.3`
base="session-ios-$DRONE_TAG-$suffix"
else
# Otherwise build a length name from the datetime and commit hash, such as:
# session-ios-20200522T212342Z-04d7dcc54
base="session-ios-$(date --date=@$DRONE_BUILD_CREATED +%Y%m%dT%H%M%SZ)-${DRONE_COMMIT:0:9}-$suffix"
fi
# Copy over the build products
mkdir -vp "$base"
mkdir -p build
cp -av $target_path "$base"
# tar dat shiz up yo
archive="$base.tar.xz"
tar cJvf "$archive" "$base"

File diff suppressed because it is too large Load Diff

View File

@ -1,213 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWSBackupSettingsViewController.h"
#import "OWSBackup.h"
#import "Session-Swift.h"
#import <PromiseKit/AnyPromise.h>
#import <SessionMessagingKit/Environment.h>
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
#import <SignalUtilitiesKit/UIColor+OWS.h>
#import <SignalUtilitiesKit/UIFont+OWS.h>
#import <SessionUtilitiesKit/UIView+OWS.h>
#import <SessionUtilitiesKit/MIMETypeUtil.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWSBackupSettingsViewController ()
@property (nonatomic, nullable) NSError *iCloudError;
@end
#pragma mark -
@implementation OWSBackupSettingsViewController
#pragma mark - Dependencies
- (OWSBackup *)backup
{
OWSAssertDebug(AppEnvironment.shared.backup);
return AppEnvironment.shared.backup;
}
#pragma mark -
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(@"SETTINGS_BACKUP", @"Label for the backup view in app settings.");
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backupStateDidChange:)
name:NSNotificationNameBackupStateDidChange
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:OWSApplicationDidBecomeActiveNotification
object:nil];
[self updateTableContents];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateTableContents];
[self updateICloudStatus];
}
- (void)updateICloudStatus
{
__weak OWSBackupSettingsViewController *weakSelf = self;
[[self.backup ensureCloudKitAccess]
.then(^{
OWSAssertIsOnMainThread();
weakSelf.iCloudError = nil;
[weakSelf updateTableContents];
})
.catch(^(NSError *error) {
OWSAssertIsOnMainThread();
weakSelf.iCloudError = error;
[weakSelf updateTableContents];
}) retainUntilComplete];
}
#pragma mark - Table Contents
- (void)updateTableContents
{
OWSTableContents *contents = [OWSTableContents new];
BOOL isBackupEnabled = [OWSBackup.sharedManager isBackupEnabled];
if (self.iCloudError) {
OWSTableSection *iCloudSection = [OWSTableSection new];
iCloudSection.headerTitle = NSLocalizedString(
@"SETTINGS_BACKUP_ICLOUD_STATUS", @"Label for iCloud status row in the in the backup settings view.");
[iCloudSection
addItem:[OWSTableItem
longDisclosureItemWithText:[OWSBackupAPI errorMessageForCloudKitAccessError:self.iCloudError]
actionBlock:^{
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}]];
[contents addSection:iCloudSection];
}
// TODO: This UI is temporary.
// Enabling backup will involve entering and registering a PIN.
OWSTableSection *enableSection = [OWSTableSection new];
enableSection.headerTitle = NSLocalizedString(@"SETTINGS_BACKUP", @"Label for the backup view in app settings.");
[enableSection
addItem:[OWSTableItem switchItemWithText:
NSLocalizedString(@"SETTINGS_BACKUP_ENABLING_SWITCH",
@"Label for switch in settings that controls whether or not backup is enabled.")
isOnBlock:^{
return [OWSBackup.sharedManager isBackupEnabled];
}
target:self
selector:@selector(isBackupEnabledDidChange:)]];
[contents addSection:enableSection];
if (isBackupEnabled) {
// TODO: This UI is temporary.
// Enabling backup will involve entering and registering a PIN.
OWSTableSection *progressSection = [OWSTableSection new];
[progressSection
addItem:[OWSTableItem
labelItemWithText:NSLocalizedString(@"SETTINGS_BACKUP_STATUS",
@"Label for backup status row in the in the backup settings view.")
accessoryText:NSStringForBackupExportState(OWSBackup.sharedManager.backupExportState)]];
if (OWSBackup.sharedManager.backupExportState == OWSBackupState_InProgress) {
if (OWSBackup.sharedManager.backupExportDescription) {
[progressSection
addItem:[OWSTableItem
labelItemWithText:NSLocalizedString(@"SETTINGS_BACKUP_PHASE",
@"Label for phase row in the in the backup settings view.")
accessoryText:OWSBackup.sharedManager.backupExportDescription]];
if (OWSBackup.sharedManager.backupExportProgress) {
NSUInteger progressPercent
= (NSUInteger)round(OWSBackup.sharedManager.backupExportProgress.floatValue * 100);
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterPercentStyle];
[numberFormatter setMaximumFractionDigits:0];
[numberFormatter setMultiplier:@1];
NSString *progressString = [numberFormatter stringFromNumber:@(progressPercent)];
[progressSection
addItem:[OWSTableItem
labelItemWithText:NSLocalizedString(@"SETTINGS_BACKUP_PROGRESS",
@"Label for phase row in the in the backup settings view.")
accessoryText:progressString]];
}
}
}
switch (OWSBackup.sharedManager.backupExportState) {
case OWSBackupState_Idle:
case OWSBackupState_Failed:
case OWSBackupState_Succeeded:
[progressSection
addItem:[OWSTableItem disclosureItemWithText:
NSLocalizedString(@"SETTINGS_BACKUP_BACKUP_NOW",
@"Label for 'backup now' button in the backup settings view.")
actionBlock:^{
[OWSBackup.sharedManager tryToExportBackup];
}]];
break;
case OWSBackupState_InProgress:
[progressSection
addItem:[OWSTableItem disclosureItemWithText:
NSLocalizedString(@"SETTINGS_BACKUP_CANCEL_BACKUP",
@"Label for 'cancel backup' button in the backup settings view.")
actionBlock:^{
[OWSBackup.sharedManager cancelExportBackup];
}]];
break;
}
[contents addSection:progressSection];
}
self.contents = contents;
}
- (void)isBackupEnabledDidChange:(UISwitch *)sender
{
[OWSBackup.sharedManager setIsBackupEnabled:sender.isOn];
[self updateTableContents];
}
#pragma mark - Events
- (void)backupStateDidChange:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
[self updateTableContents];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
[self updateICloudStatus];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -9,6 +9,8 @@ import WebRTC
import SessionUIKit
import SignalUtilitiesKit
import SessionMessagingKit
import SessionUtilitiesKit
import SessionSnodeKit
public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
@objc static let isEnabled = true

View File

@ -2,6 +2,7 @@
import UIKit
import GRDB
import SessionUtilitiesKit
extension SessionCallManager {
@discardableResult

View File

@ -6,6 +6,7 @@ import GRDB
import SessionMessagingKit
import SignalCoreKit
import SignalUtilitiesKit
import SessionUtilitiesKit
public final class SessionCallManager: NSObject, CallManagerProtocol {
let provider: CXProvider?
@ -92,7 +93,8 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
public func reportOutgoingCall(_ call: SessionCall) {
AssertIsOnMainThread()
UserDefaults.sharedLokiProject?.set(true, forKey: "isCallOngoing")
UserDefaults.sharedLokiProject?[.isCallOngoing] = true
UserDefaults.sharedLokiProject?[.lastCallPreOffer] = Date()
call.stateDidChange = {
if call.hasStartedConnecting {
@ -122,7 +124,8 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
completion(error)
return
}
UserDefaults.sharedLokiProject?.set(true, forKey: "isCallOngoing")
UserDefaults.sharedLokiProject?[.isCallOngoing] = true
UserDefaults.sharedLokiProject?[.lastCallPreOffer] = Date()
completion(nil)
}
}
@ -137,7 +140,9 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
func handleCallEnded() {
WebRTCSession.current = nil
UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing")
UserDefaults.sharedLokiProject?[.isCallOngoing] = false
UserDefaults.sharedLokiProject?[.lastCallPreOffer] = nil
if CurrentAppContext().isInBackground() {
(UIApplication.shared.delegate as? AppDelegate)?.stopPollers()
DDLog.flushLog()

View File

@ -4,6 +4,7 @@ import UIKit
import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SessionUtilitiesKit
final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
private static let swipeToOperateThreshold: CGFloat = 60
@ -113,7 +114,7 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
publicKey: call.sessionId,
threadVariant: .contact,
customImageData: nil,
profile: Storage.shared.read { db in Profile.fetchOrCreate(db, id: call.sessionId) },
profile: Storage.shared.read { [sessionId = call.sessionId] db in Profile.fetchOrCreate(db, id: sessionId) },
additionalProfile: nil
)
displayNameLabel.text = call.contactName

View File

@ -3,6 +3,7 @@
import UIKit
import WebRTC
import SessionUIKit
import SessionUtilitiesKit
final class MiniCallView: UIView, RTCVideoViewDelegate {
var callVC: CallVC

View File

@ -7,6 +7,7 @@ import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SessionUtilitiesKit
final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate {
private struct GroupMemberDisplayInfo: FetchableRecord, Equatable, Hashable, Decodable, Differentiable {

View File

@ -2,6 +2,7 @@
import UIKit
import SessionMessagingKit
import SessionUtilitiesKit
extension ContextMenuVC {
struct Action {
@ -35,15 +36,15 @@ extension ContextMenuVC {
// MARK: - Actions
static func info(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func info(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_info"),
title: "context_menu_info".localized(),
accessibilityLabel: "Message info"
) { delegate?.info(cellViewModel) }
) { delegate?.info(cellViewModel, using: dependencies) }
}
static func retry(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func retry(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(systemName: "arrow.triangle.2.circlepath"),
title: (cellViewModel.state == .failedToSync ?
@ -51,23 +52,23 @@ extension ContextMenuVC {
"context_menu_resend".localized()
),
accessibilityLabel: (cellViewModel.state == .failedToSync ? "Resync message" : "Resend message")
) { delegate?.retry(cellViewModel) }
) { delegate?.retry(cellViewModel, using: dependencies) }
}
static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_reply"),
title: "context_menu_reply".localized(),
accessibilityLabel: "Reply to message"
) { delegate?.reply(cellViewModel) }
) { delegate?.reply(cellViewModel, using: dependencies) }
}
static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_copy"),
title: "copy".localized(),
accessibilityLabel: "Copy text"
) { delegate?.copy(cellViewModel) }
) { delegate?.copy(cellViewModel, using: dependencies) }
}
static func copySessionID(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
@ -79,50 +80,50 @@ extension ContextMenuVC {
) { delegate?.copySessionID(cellViewModel) }
}
static func delete(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func delete(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_trash"),
title: "TXT_DELETE_TITLE".localized(),
accessibilityLabel: "Delete message"
) { delegate?.delete(cellViewModel) }
) { delegate?.delete(cellViewModel, using: dependencies) }
}
static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_download"),
title: "context_menu_save".localized(),
accessibilityLabel: "Save attachment"
) { delegate?.save(cellViewModel) }
) { delegate?.save(cellViewModel, using: dependencies) }
}
static func ban(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func ban(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_block"),
title: "context_menu_ban_user".localized(),
accessibilityLabel: "Ban user"
) { delegate?.ban(cellViewModel) }
) { delegate?.ban(cellViewModel, using: dependencies) }
}
static func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
icon: UIImage(named: "ic_block"),
title: "context_menu_ban_and_delete_all".localized(),
accessibilityLabel: "Ban user and delete"
) { delegate?.banAndDeleteAllMessages(cellViewModel) }
) { delegate?.banAndDeleteAllMessages(cellViewModel, using: dependencies) }
}
static func react(_ cellViewModel: MessageViewModel, _ emoji: EmojiWithSkinTones, _ delegate: ContextMenuActionDelegate?) -> Action {
static func react(_ cellViewModel: MessageViewModel, _ emoji: EmojiWithSkinTones, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
title: emoji.rawValue,
isEmojiAction: true
) { delegate?.react(cellViewModel, with: emoji) }
) { delegate?.react(cellViewModel, with: emoji, using: dependencies) }
}
static func emojiPlusButton(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
static func emojiPlusButton(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?, using dependencies: Dependencies) -> Action {
return Action(
isEmojiPlus: true,
accessibilityLabel: "Add emoji"
) { delegate?.showFullEmojiKeyboard(cellViewModel) }
) { delegate?.showFullEmojiKeyboard(cellViewModel, using: dependencies) }
}
static func dismiss(_ delegate: ContextMenuActionDelegate?) -> Action {
@ -150,7 +151,8 @@ extension ContextMenuVC {
currentUserBlinded25PublicKey: String?,
currentUserIsOpenGroupModerator: Bool,
currentThreadIsMessageRequest: Bool,
delegate: ContextMenuActionDelegate?
delegate: ContextMenuActionDelegate?,
using dependencies: Dependencies = Dependencies()
) -> [Action]? {
switch cellViewModel.variant {
case .standardIncomingDeleted, .infoCall,
@ -159,7 +161,7 @@ extension ContextMenuVC {
.infoClosedGroupCurrentUserLeft, .infoClosedGroupCurrentUserLeaving, .infoClosedGroupCurrentUserErrorLeaving,
.infoMessageRequestAccepted, .infoDisappearingMessagesUpdate:
// Let the user delete info messages and unsent messages
return [ Action.delete(cellViewModel, delegate) ]
return [ Action.delete(cellViewModel, delegate, using: dependencies) ]
case .standardOutgoing, .standardIncoming: break
}
@ -227,18 +229,21 @@ extension ContextMenuVC {
let shouldShowInfo: Bool = (cellViewModel.attachments?.isEmpty == false)
let generatedActions: [Action] = [
(canRetry ? Action.retry(cellViewModel, delegate) : nil),
(viewModelCanReply(cellViewModel) ? Action.reply(cellViewModel, delegate) : nil),
(canCopy ? Action.copy(cellViewModel, delegate) : nil),
(canSave ? Action.save(cellViewModel, delegate) : nil),
(canRetry ? Action.retry(cellViewModel, delegate, using: dependencies) : nil),
(viewModelCanReply(cellViewModel) ? Action.reply(cellViewModel, delegate, using: dependencies) : nil),
(canCopy ? Action.copy(cellViewModel, delegate, using: dependencies) : nil),
(canSave ? Action.save(cellViewModel, delegate, using: dependencies) : nil),
(canCopySessionId ? Action.copySessionID(cellViewModel, delegate) : nil),
(canDelete ? Action.delete(cellViewModel, delegate) : nil),
(canBan ? Action.ban(cellViewModel, delegate) : nil),
(canBan ? Action.banAndDeleteAllMessages(cellViewModel, delegate) : nil),
(shouldShowInfo ? Action.info(cellViewModel, delegate) : nil),
(canDelete ? Action.delete(cellViewModel, delegate, using: dependencies) : nil),
(canBan ? Action.ban(cellViewModel, delegate, using: dependencies) : nil),
(canBan ? Action.banAndDeleteAllMessages(cellViewModel, delegate, using: dependencies) : nil),
(shouldShowInfo ? Action.info(cellViewModel, delegate, using: dependencies) : nil),
]
.appending(contentsOf: (shouldShowEmojiActions ? recentEmojis : []).map { Action.react(cellViewModel, $0, delegate) })
.appending(Action.emojiPlusButton(cellViewModel, delegate))
.appending(
contentsOf: (shouldShowEmojiActions ? recentEmojis : [])
.map { Action.react(cellViewModel, $0, delegate, using: dependencies) }
)
.appending(Action.emojiPlusButton(cellViewModel, delegate, using: dependencies))
.compactMap { $0 }
guard !generatedActions.isEmpty else { return [] }
@ -250,16 +255,16 @@ extension ContextMenuVC {
// MARK: - Delegate
protocol ContextMenuActionDelegate {
func info(_ cellViewModel: MessageViewModel)
func retry(_ cellViewModel: MessageViewModel)
func reply(_ cellViewModel: MessageViewModel)
func copy(_ cellViewModel: MessageViewModel)
func info(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func retry(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func reply(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func copy(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func copySessionID(_ cellViewModel: MessageViewModel)
func delete(_ cellViewModel: MessageViewModel)
func save(_ cellViewModel: MessageViewModel)
func ban(_ cellViewModel: MessageViewModel)
func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel)
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones)
func showFullEmojiKeyboard(_ cellViewModel: MessageViewModel)
func delete(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func save(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func ban(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones, using dependencies: Dependencies)
func showFullEmojiKeyboard(_ cellViewModel: MessageViewModel, using dependencies: Dependencies)
func contextMenuDismissed()
}

View File

@ -5,6 +5,7 @@ import GRDB
import SignalUtilitiesKit
import SignalCoreKit
import SessionUIKit
import SessionUtilitiesKit
public class StyledSearchController: UISearchController {
public override var preferredStatusBarStyle: UIStatusBarStyle {

View File

@ -1,6 +1,8 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import AVKit
import AVFoundation
import Combine
import CoreServices
import Photos
@ -11,6 +13,7 @@ import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalUtilitiesKit
import SessionSnodeKit
extension ConversationVC:
InputViewDelegate,
@ -149,8 +152,15 @@ extension ConversationVC:
dismiss(animated: true, completion: nil)
}
func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didApproveAttachments attachments: [SignalAttachment], forThreadId threadId: String, messageText: String?) {
sendMessage(text: (messageText ?? ""), attachments: attachments)
func sendMediaNav(
_ sendMediaNavigationController: SendMediaNavigationController,
didApproveAttachments attachments: [SignalAttachment],
forThreadId threadId: String,
threadVariant: SessionThread.Variant,
messageText: String?,
using dependencies: Dependencies
) {
sendMessage(text: (messageText ?? ""), attachments: attachments, using: dependencies)
resetMentions()
dismiss(animated: true) { [weak self] in
@ -173,8 +183,15 @@ extension ConversationVC:
// MARK: - AttachmentApprovalViewControllerDelegate
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didApproveAttachments attachments: [SignalAttachment], forThreadId threadId: String, messageText: String?) {
sendMessage(text: (messageText ?? ""), attachments: attachments)
func attachmentApproval(
_ attachmentApproval: AttachmentApprovalViewController,
didApproveAttachments attachments: [SignalAttachment],
forThreadId threadId: String,
threadVariant: SessionThread.Variant,
messageText: String?,
using dependencies: Dependencies
) {
sendMessage(text: (messageText ?? ""), attachments: attachments, using: dependencies)
resetMentions()
dismiss(animated: true) { [weak self] in
@ -248,11 +265,13 @@ extension ConversationVC:
func handleLibraryButtonTapped() {
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
Permissions.requestLibraryPermissionIfNeeded { [weak self] in
DispatchQueue.main.async {
let sendMediaNavController = SendMediaNavigationController.showingMediaLibraryFirst(
threadId: threadId
threadId: threadId,
threadVariant: threadVariant
)
sendMediaNavController.sendMediaNavDelegate = self
sendMediaNavController.modalPresentationStyle = .fullScreen
@ -270,7 +289,10 @@ extension ConversationVC:
SNLog("Proceeding without microphone access. Any recorded video will be silent.")
}
let sendMediaNavController = SendMediaNavigationController.showingCameraFirst(threadId: self.viewModel.threadData.threadId)
let sendMediaNavController = SendMediaNavigationController.showingCameraFirst(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant
)
sendMediaNavController.sendMediaNavDelegate = self
sendMediaNavController.modalPresentationStyle = .fullScreen
@ -356,6 +378,7 @@ extension ConversationVC:
func showAttachmentApprovalDialog(for attachments: [SignalAttachment]) {
let navController = AttachmentApprovalViewController.wrappedInNavController(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
attachments: attachments,
approvalDelegate: self
)
@ -409,7 +432,8 @@ extension ConversationVC:
attachments: [SignalAttachment] = [],
linkPreviewDraft: LinkPreviewDraft? = nil,
quoteModel: QuotedReplyModel? = nil,
hasPermissionToSendSeed: Bool = false
hasPermissionToSendSeed: Bool = false,
using dependencies: Dependencies = Dependencies()
) {
guard !showBlockedModalIfNeeded() else { return }
@ -480,20 +504,23 @@ extension ConversationVC:
quoteModel: quoteModel
)
sendMessage(optimisticData: optimisticData)
sendMessage(optimisticData: optimisticData, using: dependencies)
}
private func sendMessage(optimisticData: ConversationViewModel.OptimisticMessageData) {
private func sendMessage(
optimisticData: ConversationViewModel.OptimisticMessageData,
using dependencies: Dependencies
) {
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
DispatchQueue.global(qos:.userInitiated).async {
DispatchQueue.global(qos:.userInitiated).async(using: dependencies) {
// Generate the quote thumbnail if needed (want this to happen outside of the DBWrite thread as
// this can take up to 0.5s
let quoteThumbnailAttachment: Attachment? = optimisticData.quoteModel?.attachment?.cloneAsQuoteThumbnail()
// Actually send the message
Storage.shared
dependencies.storage
.writePublisher { [weak self] db in
// Update the thread to be visible (if it isn't already)
if self?.viewModel.threadData.threadShouldBeVisible == false {
@ -507,16 +534,34 @@ extension ConversationVC:
let insertedInteraction: Interaction = try optimisticData.interaction.inserted(db)
self?.viewModel.associate(optimisticMessageId: optimisticData.id, to: insertedInteraction.id)
// If there is a LinkPreview and it doesn't match an existing one then add it now
if
let linkPreviewDraft: LinkPreviewDraft = optimisticData.linkPreviewDraft,
(try? insertedInteraction.linkPreview.isEmpty(db)) == true
{
try LinkPreview(
url: linkPreviewDraft.urlString,
title: linkPreviewDraft.title,
attachmentId: try optimisticData.linkPreviewAttachment?.inserted(db).id
).insert(db)
// If there is a LinkPreview draft then check the state of any existing link previews and
// insert a new one if needed
if let linkPreviewDraft: LinkPreviewDraft = optimisticData.linkPreviewDraft {
let invalidLinkPreviewAttachmentStates: [Attachment.State] = [
.failedDownload, .pendingDownload, .downloading, .failedUpload, .invalid
]
let linkPreviewAttachmentId: String? = try? insertedInteraction.linkPreview
.select(.attachmentId)
.asRequest(of: String.self)
.fetchOne(db)
let linkPreviewAttachmentState: Attachment.State = linkPreviewAttachmentId
.map {
try? Attachment
.filter(id: $0)
.select(.state)
.asRequest(of: Attachment.State.self)
.fetchOne(db)
}
.defaulting(to: .invalid)
// If we don't have a "valid" existing link preview then upsert a new one
if invalidLinkPreviewAttachmentStates.contains(linkPreviewAttachmentState) {
try LinkPreview(
url: linkPreviewDraft.urlString,
title: linkPreviewDraft.title,
attachmentId: try optimisticData.linkPreviewAttachment?.inserted(db).id
).save(db)
}
}
// If there is a Quote the insert it now
@ -541,7 +586,8 @@ extension ConversationVC:
db,
interaction: insertedInteraction,
threadId: threadId,
threadVariant: threadVariant
threadVariant: threadVariant,
using: dependencies
)
}
.subscribe(on: DispatchQueue.global(qos: .userInitiated))
@ -635,6 +681,7 @@ extension ConversationVC:
let approvalVC = AttachmentApprovalViewController.wrappedInNavController(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
attachments: [ attachment ],
approvalDelegate: self
)
@ -798,10 +845,14 @@ extension ConversationVC:
self.contextMenuWindow?.makeKeyAndVisible()
}
func handleItemTapped(_ cellViewModel: MessageViewModel, gestureRecognizer: UITapGestureRecognizer) {
func handleItemTapped(
_ cellViewModel: MessageViewModel,
gestureRecognizer: UITapGestureRecognizer,
using dependencies: Dependencies = Dependencies()
) {
guard cellViewModel.variant != .standardOutgoing || (cellViewModel.state != .failed && cellViewModel.state != .failedToSync) else {
// Show the failed message sheet
showFailedMessageSheet(for: cellViewModel)
showFailedMessageSheet(for: cellViewModel, using: dependencies)
return
}
@ -846,7 +897,7 @@ extension ConversationVC:
}
switch cellViewModel.cellType {
case .audio: viewModel.playOrPauseAudio(for: cellViewModel)
case .voiceMessage: viewModel.playOrPauseAudio(for: cellViewModel)
case .mediaMessage:
guard
@ -875,8 +926,8 @@ extension ConversationVC:
let threadId: String = self.viewModel.threadData.threadId
// Retry downloading the failed attachment
Storage.shared.writeAsync { db in
JobRunner.add(
dependencies.storage.writeAsync { db in
dependencies.jobRunner.add(
db,
job: Job(
variant: .attachmentDownload,
@ -885,7 +936,9 @@ extension ConversationVC:
details: AttachmentDownloadJob.Details(
attachmentId: mediaView.attachment.id
)
)
),
canStartJob: true,
using: dependencies
)
}
break
@ -894,6 +947,18 @@ extension ConversationVC:
// Ignore invalid media
guard mediaView.attachment.isValid else { return }
guard albumView.numItems > 1 || !mediaView.attachment.isVideo else {
guard
let originalFilePath: String = mediaView.attachment.originalFilePath,
FileManager.default.fileExists(atPath: originalFilePath)
else { return SNLog("Missing video file") }
let viewController: AVPlayerViewController = AVPlayerViewController()
viewController.player = AVPlayer(url: URL(fileURLWithPath: originalFilePath))
self.navigationController?.present(viewController, animated: true)
return
}
let viewController: UIViewController? = MediaGalleryViewModel.createDetailViewController(
for: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
@ -924,6 +989,17 @@ extension ConversationVC:
}
}
case .audio:
guard
let attachment: Attachment = cellViewModel.attachments?.first,
let originalFilePath: String = attachment.originalFilePath
else { return }
// Use the native player to play audio files
let viewController: AVPlayerViewController = AVPlayerViewController()
viewController.player = AVPlayer(url: URL(fileURLWithPath: originalFilePath))
self.navigationController?.present(viewController, animated: true)
case .genericAttachment:
guard
let attachment: Attachment = cellViewModel.attachments?.first,
@ -987,7 +1063,7 @@ extension ConversationVC:
func handleItemDoubleTapped(_ cellViewModel: MessageViewModel) {
switch cellViewModel.cellType {
// The user can double tap a voice message when it's playing to speed it up
case .audio: self.viewModel.speedUpAudio(for: cellViewModel)
case .voiceMessage: self.viewModel.speedUpAudio(for: cellViewModel)
default: break
}
}
@ -1024,8 +1100,8 @@ extension ConversationVC:
self.present(actionSheet, animated: true)
}
func handleReplyButtonTapped(for cellViewModel: MessageViewModel) {
reply(cellViewModel)
func handleReplyButtonTapped(for cellViewModel: MessageViewModel, using dependencies: Dependencies) {
reply(cellViewModel, using: dependencies)
}
func startThread(with sessionId: String, openGroupServer: String?, openGroupPublicKey: String?) {
@ -1134,15 +1210,15 @@ extension ConversationVC:
UIView.setAnimationsEnabled(true)
}
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones) {
react(cellViewModel, with: emoji.rawValue, remove: false)
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones, using dependencies: Dependencies) {
react(cellViewModel, with: emoji.rawValue, remove: false, using: dependencies)
}
func removeReact(_ cellViewModel: MessageViewModel, for emoji: EmojiWithSkinTones) {
react(cellViewModel, with: emoji.rawValue, remove: true)
func removeReact(_ cellViewModel: MessageViewModel, for emoji: EmojiWithSkinTones, using dependencies: Dependencies) {
react(cellViewModel, with: emoji.rawValue, remove: true, using: dependencies)
}
func removeAllReactions(_ cellViewModel: MessageViewModel, for emoji: String) {
func removeAllReactions(_ cellViewModel: MessageViewModel, for emoji: String, using dependencies: Dependencies) {
guard cellViewModel.threadVariant == .community else { return }
Storage.shared
@ -1219,7 +1295,7 @@ extension ConversationVC:
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
let openGroupRoom: String? = self.viewModel.threadData.openGroupRoomToken
let sentTimestamp: Int64 = SnodeAPI.currentOffsetTimestampMs()
let recentReactionTimestamps: [Int64] = dependencies.generalCache.recentReactionTimestamps
let recentReactionTimestamps: [Int64] = dependencies.caches[.general].recentReactionTimestamps
guard
recentReactionTimestamps.count < 20 ||
@ -1237,7 +1313,7 @@ extension ConversationVC:
return
}
dependencies.mutableGeneralCache.mutate {
dependencies.caches.mutate(cache: .general) {
$0.recentReactionTimestamps = Array($0.recentReactionTimestamps
.suffix(19))
.appending(sentTimestamp)
@ -1272,9 +1348,9 @@ extension ConversationVC:
))
}
}
.subscribe(on: DispatchQueue.global(qos: .userInitiated))
.subscribe(on: DispatchQueue.global(qos: .userInitiated), using: dependencies)
.flatMap { pendingChange -> AnyPublisher<(MessageSender.PreparedSendData?, OpenGroupInfo?), Error> in
Storage.shared.writePublisher { [weak self] db -> (MessageSender.PreparedSendData?, OpenGroupInfo?) in
dependencies.storage.writePublisher { [weak self] db -> (MessageSender.PreparedSendData?, OpenGroupInfo?) in
// Update the thread to be visible (if it isn't already)
if self?.viewModel.threadData.threadShouldBeVisible == false {
_ = try SessionThread
@ -1383,7 +1459,8 @@ extension ConversationVC:
namespace: try Message.Destination
.from(db, threadId: cellViewModel.threadId, threadVariant: cellViewModel.threadVariant)
.defaultNamespace,
interactionId: cellViewModel.id
interactionId: cellViewModel.id,
using: dependencies
)
return (sendData, nil)
@ -1393,7 +1470,7 @@ extension ConversationVC:
.tryFlatMap { messageSendData, openGroupInfo -> AnyPublisher<Void, Error> in
switch (messageSendData, openGroupInfo) {
case (.some(let sendData), _):
return MessageSender.sendImmediate(preparedSendData: sendData)
return MessageSender.sendImmediate(data: sendData, using: dependencies)
case (_, .some(let info)):
return OpenGroupAPI.send(data: info.sendData)
@ -1444,14 +1521,14 @@ extension ConversationVC:
}
}
func showFullEmojiKeyboard(_ cellViewModel: MessageViewModel) {
func showFullEmojiKeyboard(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
hideInputAccessoryView()
let emojiPicker = EmojiPickerSheet(
completionHandler: { [weak self] emoji in
guard let emoji: EmojiWithSkinTones = emoji else { return }
self?.react(cellViewModel, with: emoji)
self?.react(cellViewModel, with: emoji, using: dependencies)
},
dismissHandler: { [weak self] in
self?.showInputAccessoryView()
@ -1467,7 +1544,7 @@ extension ConversationVC:
// MARK: --action handling
func showFailedMessageSheet(for cellViewModel: MessageViewModel) {
private func showFailedMessageSheet(for cellViewModel: MessageViewModel, using dependencies: Dependencies) {
let sheet = UIAlertController(
title: (cellViewModel.state == .failedToSync ?
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE".localized() :
@ -1494,7 +1571,7 @@ extension ConversationVC:
"context_menu_resend".localized()
),
style: .default,
handler: { [weak self] _ in self?.retry(cellViewModel) }
handler: { [weak self] _ in self?.retry(cellViewModel, using: dependencies) }
))
// HACK: Extracting this info from the error string is pretty dodgy
@ -1607,7 +1684,7 @@ extension ConversationVC:
// MARK: - ContextMenuActionDelegate
func info(_ cellViewModel: MessageViewModel) {
func info(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
let mediaInfoVC = MediaInfoVC(
attachments: (cellViewModel.attachments ?? []),
isOutgoing: (cellViewModel.variant == .standardOutgoing),
@ -1618,8 +1695,7 @@ extension ConversationVC:
navigationController?.pushViewController(mediaInfoVC, animated: true)
}
func retry(_ cellViewModel: MessageViewModel) {
// If the failed message is an optimistic update then we need to do things differently
func retry(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
guard cellViewModel.id != MessageViewModel.optimisticUpdateId else {
guard
let optimisticMessageId: UUID = cellViewModel.optimisticMessageId,
@ -1640,11 +1716,11 @@ extension ConversationVC:
}
// Try to send the optimistic message again
self.sendMessage(optimisticData: optimisticMessageData)
sendMessage(optimisticData: optimisticMessageData, using: dependencies)
return
}
Storage.shared.writeAsync { [weak self] db in
dependencies.storage.writeAsync { [weak self] db in
guard
let threadId: String = self?.viewModel.threadData.threadId,
let threadVariant: SessionThread.Variant = self?.viewModel.threadData.threadVariant,
@ -1685,12 +1761,13 @@ extension ConversationVC:
interaction: interaction,
threadId: threadId,
threadVariant: threadVariant,
isSyncMessage: (cellViewModel.state == .failedToSync)
isSyncMessage: (cellViewModel.state == .failedToSync),
using: dependencies
)
}
}
func reply(_ cellViewModel: MessageViewModel) {
func reply(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
let maybeQuoteDraft: QuotedReplyModel? = QuotedReplyModel.quotedReplyForSending(
threadId: self.viewModel.threadData.threadId,
authorId: cellViewModel.authorId,
@ -1713,7 +1790,7 @@ extension ConversationVC:
snInputView.becomeFirstResponder()
}
func copy(_ cellViewModel: MessageViewModel) {
func copy(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
switch cellViewModel.cellType {
case .typingIndicator, .dateHeader, .unreadMarker: break
@ -1725,7 +1802,7 @@ extension ConversationVC:
UIPasteboard.general.string = cellViewModel.body
case .audio, .genericAttachment, .mediaMessage:
case .audio, .voiceMessage, .genericAttachment, .mediaMessage:
guard
cellViewModel.attachments?.count == 1,
let attachment: Attachment = cellViewModel.attachments?.first,
@ -1751,7 +1828,7 @@ extension ConversationVC:
UIPasteboard.general.string = cellViewModel.authorId
}
func delete(_ cellViewModel: MessageViewModel) {
func delete(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
switch cellViewModel.variant {
case .standardIncomingDeleted, .infoCall,
.infoScreenshotNotification, .infoMediaSavedNotification,
@ -1947,7 +2024,8 @@ extension ConversationVC:
message: unsendRequest,
threadId: cellViewModel.threadId,
interactionId: nil,
to: .contact(publicKey: userPublicKey)
to: .contact(publicKey: userPublicKey),
using: dependencies
)
}
return
@ -1970,7 +2048,8 @@ extension ConversationVC:
message: unsendRequest,
threadId: cellViewModel.threadId,
interactionId: nil,
to: .contact(publicKey: userPublicKey)
to: .contact(publicKey: userPublicKey),
using: dependencies
)
}
self?.showInputAccessoryView()
@ -1998,7 +2077,8 @@ extension ConversationVC:
message: unsendRequest,
interactionId: nil,
threadId: cellViewModel.threadId,
threadVariant: cellViewModel.threadVariant
threadVariant: cellViewModel.threadVariant,
using: dependencies
)
}
@ -2032,7 +2112,7 @@ extension ConversationVC:
}
}
func save(_ cellViewModel: MessageViewModel) {
func save(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
guard cellViewModel.cellType == .mediaMessage else { return }
let mediaAttachments: [(Attachment, String)] = (cellViewModel.attachments ?? [])
@ -2074,24 +2154,10 @@ extension ConversationVC:
return
}
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
Storage.shared.writeAsync { db in
try MessageSender.send(
db,
message: DataExtractionNotification(
kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)),
sentTimestamp: UInt64(SnodeAPI.currentOffsetTimestampMs())
),
interactionId: nil,
threadId: threadId,
threadVariant: threadVariant
)
}
sendDataExtraction(kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)))
}
func ban(_ cellViewModel: MessageViewModel) {
func ban(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
guard cellViewModel.threadVariant == .community else { return }
let threadId: String = self.viewModel.threadData.threadId
@ -2147,7 +2213,7 @@ extension ConversationVC:
self.present(modal, animated: true)
}
func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel) {
func banAndDeleteAllMessages(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
guard cellViewModel.threadVariant == .community else { return }
let threadId: String = self.viewModel.threadData.threadId
@ -2205,7 +2271,7 @@ extension ConversationVC:
// MARK: - VoiceMessageRecordingViewDelegate
func startVoiceMessageRecording() {
func startVoiceMessageRecording(using dependencies: Dependencies) {
// Request permission if needed
Permissions.requestMicrophonePermissionIfNeeded() { [weak self] in
DispatchQueue.main.async {
@ -2254,7 +2320,7 @@ extension ConversationVC:
// Limit voice messages to a minute
audioTimer = Timer.scheduledTimer(withTimeInterval: 180, repeats: false, block: { [weak self] _ in
self?.snInputView.hideVoiceMessageUI()
self?.endVoiceMessageRecording()
self?.endVoiceMessageRecording(using: dependencies)
})
// Prepare audio recorder
@ -2270,7 +2336,7 @@ extension ConversationVC:
}
}
func endVoiceMessageRecording() {
func endVoiceMessageRecording(using dependencies: Dependencies) {
UIApplication.shared.isIdleTimerDisabled = true
// Hide the UI
@ -2322,7 +2388,7 @@ extension ConversationVC:
}
// Send attachment
sendMessage(text: "", attachments: [attachment])
sendMessage(text: "", attachments: [attachment], using: dependencies)
}
func cancelVoiceMessageRecording() {
@ -2339,23 +2405,29 @@ extension ConversationVC:
// MARK: - Data Extraction Notifications
@objc func sendScreenshotNotification() {
@objc func sendScreenshotNotification() { sendDataExtraction(kind: .screenshot) }
func sendDataExtraction(
kind: DataExtractionNotification.Kind,
using dependencies: Dependencies = Dependencies()
) {
// Only send screenshot notifications to one-to-one conversations
guard self.viewModel.threadData.threadVariant == .contact else { return }
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
Storage.shared.writeAsync { db in
dependencies.storage.writeAsync { db in
try MessageSender.send(
db,
message: DataExtractionNotification(
kind: .screenshot,
kind: kind,
sentTimestamp: UInt64(SnodeAPI.currentOffsetTimestampMs())
),
interactionId: nil,
threadId: threadId,
threadVariant: threadVariant
threadVariant: threadVariant,
using: dependencies
)
}
}
@ -2391,16 +2463,20 @@ extension ConversationVC {
for threadId: String,
threadVariant: SessionThread.Variant,
isNewThread: Bool,
timestampMs: Int64
timestampMs: Int64,
using dependencies: Dependencies = Dependencies()
) {
guard threadVariant == .contact else { return }
let updateNavigationBackStack: () -> Void = {
// Remove the 'MessageRequestsViewController' from the nav hierarchy if present
// Remove the 'SessionTableViewController<MessageRequestsViewModel>' from the nav hierarchy if present
DispatchQueue.main.async { [weak self] in
if
let viewControllers: [UIViewController] = self?.navigationController?.viewControllers,
let messageRequestsIndex = viewControllers.firstIndex(where: { $0 is MessageRequestsViewController }),
let messageRequestsIndex = viewControllers
.firstIndex(where: { viewCon -> Bool in
(viewCon as? SessionViewModelAccessible)?.viewModelType == MessageRequestsViewModel.self
}),
messageRequestsIndex > 0
{
var newViewControllers = viewControllers
@ -2432,7 +2508,8 @@ extension ConversationVC {
),
interactionId: nil,
threadId: threadId,
threadVariant: threadVariant
threadVariant: threadVariant,
using: dependencies
)
}

View File

@ -208,17 +208,7 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
}()
private lazy var emptyStateLabel: UILabel = {
let text: String = String(
format: {
switch (viewModel.threadData.threadIsNoteToSelf, viewModel.threadData.canWrite) {
case (true, _): return "CONVERSATION_EMPTY_STATE_NOTE_TO_SELF".localized()
case (_, false): return "CONVERSATION_EMPTY_STATE_READ_ONLY".localized()
default: return "CONVERSATION_EMPTY_STATE".localized()
}
}(),
viewModel.threadData.displayName
)
let text: String = emptyStateText(for: viewModel.threadData)
let result: UILabel = UILabel()
result.accessibilityLabel = "Empty state label"
result.translatesAutoresizingMaskIntoConstraints = false
@ -507,6 +497,9 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
startObservingChanges()
/// If the view is removed and readded to the view hierarchy then `viewWillDisappear` will be called but `viewDidDisappear`
/// **won't**, as a result `viewIsDisappearing` would never get set to `false` - do so here to handle this case
viewIsDisappearing = false
viewIsAppearing = true
}
@ -579,12 +572,16 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
let threadId: String = viewModel.threadData.threadId
if
(
self.navigationController == nil ||
self.navigationController?.viewControllers.contains(self) == false
) &&
viewModel.threadData.threadIsNoteToSelf == false &&
viewModel.threadData.threadShouldBeVisible == false &&
!SessionUtil.conversationInConfig(
threadId: threadId,
threadVariant: viewModel.threadData.threadVariant,
visibleOnly: true
visibleOnly: false
)
{
Storage.shared.writeAsync { db in
@ -698,6 +695,24 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
self.viewModel.onInteractionChange = nil
}
private func emptyStateText(for threadData: SessionThreadViewModel) -> String {
return String(
format: {
switch (threadData.threadIsNoteToSelf, threadData.canWrite) {
case (true, _): return "CONVERSATION_EMPTY_STATE_NOTE_TO_SELF".localized()
case (_, false):
return (threadData.profile?.blocksCommunityMessageRequests == true ?
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE".localized() :
"CONVERSATION_EMPTY_STATE_READ_ONLY".localized()
)
default: return "CONVERSATION_EMPTY_STATE".localized()
}
}(),
threadData.displayName
)
}
private func handleThreadUpdates(_ updatedThreadData: SessionThreadViewModel, initialLoad: Bool = false) {
// Ensure the first load or a load when returning from a child screen runs without animations (if
// we don't do this the cells will animate in from a frame of CGRect.zero or have a buggy transition)
@ -738,17 +753,7 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
)
// Update the empty state
let text: String = String(
format: {
switch (updatedThreadData.threadIsNoteToSelf, updatedThreadData.canWrite) {
case (true, _): return "CONVERSATION_EMPTY_STATE_NOTE_TO_SELF".localized()
case (_, false): return "CONVERSATION_EMPTY_STATE_READ_ONLY".localized()
default: return "CONVERSATION_EMPTY_STATE".localized()
}
}(),
updatedThreadData.displayName
)
let text: String = emptyStateText(for: updatedThreadData)
emptyStateLabel.attributedText = NSAttributedString(string: text)
.adding(
attributes: [.font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize)],
@ -791,8 +796,10 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
updatedThreadData.threadRequiresApproval == true
)
self?.messageRequestStackView.isHidden = (
updatedThreadData.threadIsMessageRequest == false &&
updatedThreadData.threadRequiresApproval == false
!updatedThreadData.canWrite || (
updatedThreadData.threadIsMessageRequest == false &&
updatedThreadData.threadRequiresApproval == false
)
)
self?.messageRequestBackgroundView.isHidden = (self?.messageRequestStackView.isHidden == true)
self?.messageRequestDescriptionLabelBottomConstraint?.constant = (updatedThreadData.threadRequiresApproval == true ? -4 : -20)
@ -1951,14 +1958,22 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
.sorted()
.filter({ $0.section == messagesSection })
.compactMap({ indexPath -> (frame: CGRect, cellViewModel: MessageViewModel)? in
guard let cell: VisibleMessageCell = tableView.cellForRow(at: indexPath) as? VisibleMessageCell else {
return nil
}
guard let cell: UITableViewCell = tableView.cellForRow(at: indexPath) else { return nil }
return (
view.convert(cell.frame, from: tableView),
self.viewModel.interactionData[indexPath.section].elements[indexPath.row]
)
switch cell {
case is VisibleMessageCell, is CallMessageCell, is InfoMessageCell:
return (
view.convert(cell.frame, from: tableView),
self.viewModel.interactionData[indexPath.section].elements[indexPath.row]
)
case is TypingIndicatorCell, is DateHeaderCell, is UnreadMarkerCell:
return nil
default:
SNLog("[ConversationVC] Warning: Processing unhandled cell type when marking as read, this could result in intermittent failures")
return nil
}
})
// Exclude messages that are partially off the bottom of the screen
.filter({ $0.frame.maxY <= tableVisualBottom })

View File

@ -49,11 +49,13 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
private var markAsReadPublisher: AnyPublisher<Void, Never>?
public lazy var blockedBannerMessage: String = {
switch self.threadData.threadVariant {
let threadData: SessionThreadViewModel = self._threadData.wrappedValue
switch threadData.threadVariant {
case .contact:
let name: String = Profile.displayName(
id: self.threadData.threadId,
threadVariant: self.threadData.threadVariant
id: threadData.threadId,
threadVariant: threadData.threadVariant
)
return "\(name) is blocked. Unblock them?"
@ -140,16 +142,18 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
self.focusedInteractionInfo = (focusedInteractionInfo ?? initialData?.initialUnreadInteractionInfo)
self.focusBehaviour = (focusedInteractionInfo == nil ? .none : .highlight)
self.initialUnreadInteractionId = initialData?.initialUnreadInteractionInfo?.id
self.threadData = SessionThreadViewModel(
threadId: threadId,
threadVariant: threadVariant,
threadIsNoteToSelf: (initialData?.currentUserPublicKey == threadId),
threadIsBlocked: initialData?.threadIsBlocked,
currentUserIsClosedGroupMember: initialData?.currentUserIsClosedGroupMember,
openGroupPermissions: initialData?.openGroupPermissions
).populatingCurrentUserBlindedKeys(
currentUserBlinded15PublicKeyForThisThread: initialData?.blinded15Key,
currentUserBlinded25PublicKeyForThisThread: initialData?.blinded25Key
self._threadData = Atomic(
SessionThreadViewModel(
threadId: threadId,
threadVariant: threadVariant,
threadIsNoteToSelf: (initialData?.currentUserPublicKey == threadId),
threadIsBlocked: initialData?.threadIsBlocked,
currentUserIsClosedGroupMember: initialData?.currentUserIsClosedGroupMember,
openGroupPermissions: initialData?.openGroupPermissions
).populatingCurrentUserBlindedKeys(
currentUserBlinded15PublicKeyForThisThread: initialData?.blinded15Key,
currentUserBlinded25PublicKeyForThisThread: initialData?.blinded25Key
)
)
self.pagedDataObserver = nil
@ -179,8 +183,10 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
// MARK: - Thread Data
private var _threadData: Atomic<SessionThreadViewModel>
/// This value is the current state of the view
public private(set) var threadData: SessionThreadViewModel
public var threadData: SessionThreadViewModel { _threadData.wrappedValue }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
@ -200,6 +206,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
.trackingConstantRegion { [weak self] db -> SessionThreadViewModel? in
let userPublicKey: String = getUserHexEncodedPublicKey(db)
let recentReactionEmoji: [String] = try Emoji.getRecent(db, withDefaultEmoji: true)
let oldThreadData: SessionThreadViewModel? = self?._threadData.wrappedValue
let threadViewModel: SessionThreadViewModel? = try SessionThreadViewModel
.conversationQuery(threadId: threadId, userPublicKey: userPublicKey)
.fetchOne(db)
@ -209,8 +216,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
.map { viewModel -> SessionThreadViewModel in
viewModel.populatingCurrentUserBlindedKeys(
db,
currentUserBlinded15PublicKeyForThisThread: self?.threadData.currentUserBlinded15PublicKey,
currentUserBlinded25PublicKeyForThisThread: self?.threadData.currentUserBlinded25PublicKey
currentUserBlinded15PublicKeyForThisThread: oldThreadData?.currentUserBlinded15PublicKey,
currentUserBlinded25PublicKeyForThisThread: oldThreadData?.currentUserBlinded25PublicKey
)
}
}
@ -219,7 +226,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
}
public func updateThreadData(_ updatedData: SessionThreadViewModel) {
self.threadData = updatedData
self._threadData.mutate { $0 = updatedData }
}
// MARK: - Interaction Data
@ -265,6 +272,24 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
.allCases
.filter { $0 != .wasRead }
),
PagedData.ObservedChanges(
table: Attachment.self,
columns: [.state],
joinToPagedType: {
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
let linkPreview: TypedTableAlias<LinkPreview> = TypedTableAlias()
let linkPreviewAttachment: TypedTableAlias<Attachment> = TypedTableAlias()
return SQL("""
LEFT JOIN \(LinkPreview.self) ON (
\(linkPreview[.url]) = \(interaction[.linkPreviewUrl]) AND
\(Interaction.linkPreviewFilterLiteral())
)
LEFT JOIN \(linkPreviewAttachment) ON \(linkPreviewAttachment[.id]) = \(linkPreview[.attachmentId])
"""
)
}()
),
PagedData.ObservedChanges(
table: Contact.self,
columns: [.isTrusted],
@ -375,6 +400,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
optimisticMessages: [MessageViewModel]?,
initialUnreadInteractionId: Int64?
) -> [SectionModel] {
let threadData: SessionThreadViewModel = self._threadData.wrappedValue
let typingIndicator: MessageViewModel? = data.first(where: { $0.isTypingIndicator == true })
let sortedData: [MessageViewModel] = data
.filter { $0.id != MessageViewModel.optimisticUpdateId } // Remove old optimistic updates
@ -480,6 +506,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
) -> OptimisticMessageData {
// Generate the optimistic data
let optimisticMessageId: UUID = UUID()
let threadData: SessionThreadViewModel = self._threadData.wrappedValue
let currentUserProfile: Profile = Profile.fetchOrCreateCurrentUser()
let interaction: Interaction = Interaction(
threadId: threadData.threadId,
@ -640,7 +667,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
// MARK: - Mentions
public func mentions(for query: String = "") -> [MentionInfo] {
let threadData: SessionThreadViewModel = self.threadData
let threadData: SessionThreadViewModel = self._threadData.wrappedValue
return Storage.shared
.read { db -> [MentionInfo] in
@ -715,15 +742,17 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
.throttle(for: .milliseconds(100), scheduler: DispatchQueue.global(qos: .userInitiated), latest: true)
.handleEvents(
receiveOutput: { [weak self] target, timestampMs in
let threadData: SessionThreadViewModel? = self?._threadData.wrappedValue
switch target {
case .thread: self?.threadData.markAsRead(target: target)
case .thread: threadData?.markAsRead(target: target)
case .threadAndInteractions(let interactionId):
guard
timestampMs == nil ||
(self?.lastInteractionTimestampMsMarkedAsRead ?? 0) < (timestampMs ?? 0) ||
(self?.lastInteractionIdMarkedAsRead ?? 0) < (interactionId ?? 0)
else {
self?.threadData.markAsRead(target: .thread)
threadData?.markAsRead(target: .thread)
return
}
@ -733,8 +762,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
self?.lastInteractionTimestampMsMarkedAsRead = timestampMs
}
self?.lastInteractionIdMarkedAsRead = (interactionId ?? self?.threadData.interactionId)
self?.threadData.markAsRead(target: target)
self?.lastInteractionIdMarkedAsRead = (interactionId ?? threadData?.interactionId)
threadData?.markAsRead(target: target)
}
}
)
@ -773,7 +802,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
}
public func trustContact() {
guard self.threadData.threadVariant == .contact else { return }
guard self._threadData.wrappedValue.threadVariant == .contact else { return }
let threadId: String = self.threadId
@ -804,7 +833,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
}
public func unblockContact() {
guard self.threadData.threadVariant == .contact else { return }
guard self._threadData.wrappedValue.threadVariant == .contact else { return }
let threadId: String = self.threadId
@ -1030,7 +1059,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
let currentIndex: Int = messageSection.elements
.firstIndex(where: { $0.id == interactionId }),
currentIndex < (messageSection.elements.count - 1),
messageSection.elements[currentIndex + 1].cellType == .audio,
messageSection.elements[currentIndex + 1].cellType == .voiceMessage,
Storage.shared[.shouldAutoPlayConsecutiveAudioMessages] == true
else { return }

View File

@ -34,6 +34,7 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate {
lazy var documentButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_document_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityIdentifier = "Documents folder"
result.accessibilityLabel = "accessibility_document_button".localized()
result.isAccessibilityElement = true
return result
@ -42,6 +43,7 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate {
lazy var libraryButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_roll_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityIdentifier = "Images folder"
result.accessibilityLabel = "accessibility_library_button".localized()
result.isAccessibilityElement = true
return result
@ -50,6 +52,7 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate {
lazy var cameraButton: InputViewButton = {
let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_black"), delegate: self, hasOpaqueBackground: true)
result.accessibilityIdentifier = "Select camera button"
result.accessibilityLabel = "accessibility_camera_button".localized()
result.isAccessibilityElement = true
return result

View File

@ -416,14 +416,14 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
if inputViewButton == sendButton { delegate?.handleSendButtonTapped() }
}
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?) {
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?, using dependencies: Dependencies) {
guard inputViewButton == voiceMessageButton else { return }
// Note: The 'showVoiceMessageUI' call MUST come before triggering 'startVoiceMessageRecording'
// because if something goes wrong it'll trigger `hideVoiceMessageUI` and we don't want it to
// end up in a state with the input content hidden
showVoiceMessageUI()
delegate?.startVoiceMessageRecording()
delegate?.startVoiceMessageRecording(using: dependencies)
}
func handleInputViewButtonLongPressMoved(_ inputViewButton: InputViewButton, with touch: UITouch?) {

View File

@ -2,6 +2,7 @@
import UIKit
import SessionUIKit
import SessionUtilitiesKit
final class InputViewButton: UIView {
private let icon: UIImage?
@ -137,7 +138,9 @@ final class InputViewButton: UIView {
// We want to detect both taps and long presses
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { onTouchesBegan() }
private func onTouchesBegan(using dependencies: Dependencies = Dependencies()) {
guard isUserInteractionEnabled else { return }
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
@ -145,7 +148,7 @@ final class InputViewButton: UIView {
invalidateLongPressIfNeeded()
longPressTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { [weak self] _ in
self?.isLongPress = true
self?.delegate?.handleInputViewButtonLongPressBegan(self)
self?.delegate?.handleInputViewButtonLongPressBegan(self, using: dependencies)
})
}
@ -185,13 +188,13 @@ final class InputViewButton: UIView {
protocol InputViewButtonDelegate: AnyObject {
func handleInputViewButtonTapped(_ inputViewButton: InputViewButton)
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?)
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?, using dependencies: Dependencies)
func handleInputViewButtonLongPressMoved(_ inputViewButton: InputViewButton, with touch: UITouch?)
func handleInputViewButtonLongPressEnded(_ inputViewButton: InputViewButton, with touch: UITouch?)
}
extension InputViewButtonDelegate {
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?) { }
func handleInputViewButtonLongPressBegan(_ inputViewButton: InputViewButton?, using dependencies: Dependencies) { }
func handleInputViewButtonLongPressMoved(_ inputViewButton: InputViewButton, with touch: UITouch?) { }
func handleInputViewButtonLongPressEnded(_ inputViewButton: InputViewButton, with touch: UITouch?) { }
}

View File

@ -310,12 +310,12 @@ final class VoiceMessageRecordingView: UIView {
}
}
func handleLongPressEnded(at location: CGPoint) {
func handleLongPressEnded(at location: CGPoint, using dependencies: Dependencies = Dependencies()) {
if pulseView.frame.contains(location) {
delegate?.endVoiceMessageRecording()
delegate?.endVoiceMessageRecording(using: dependencies)
}
else if isValidLockViewLocation(location) {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCircleViewTap))
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(onCircleViewTap))
circleView.addGestureRecognizer(tapGestureRecognizer)
UIView.animate(withDuration: 0.25, delay: 0, options: .transitionCrossDissolve, animations: {
@ -332,8 +332,10 @@ final class VoiceMessageRecordingView: UIView {
}
}
@objc private func handleCircleViewTap() {
delegate?.endVoiceMessageRecording()
@objc private func onCircleViewTap() { handleCircleViewTap() }
private func handleCircleViewTap(using dependencies: Dependencies = Dependencies()) {
delegate?.endVoiceMessageRecording(using: dependencies)
}
@objc private func handleCancelButtonTapped() {
@ -474,7 +476,7 @@ extension VoiceMessageRecordingView {
// MARK: - Delegate
protocol VoiceMessageRecordingViewDelegate: AnyObject {
func startVoiceMessageRecording()
func endVoiceMessageRecording()
func startVoiceMessageRecording(using dependencies: Dependencies)
func endVoiceMessageRecording(using dependencies: Dependencies)
func cancelVoiceMessageRecording()
}

View File

@ -3,6 +3,7 @@
import UIKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
final class CallMessageCell: MessageCell {
private static let iconSize: CGFloat = 16

View File

@ -33,20 +33,35 @@ final class DocumentView: UIView {
)
imageView.setContentCompressionResistancePriority(.required, for: .horizontal)
imageView.setContentHuggingPriority(.required, for: .horizontal)
imageView.contentMode = .scaleAspectFit
imageView.themeTintColor = textColor
imageView.set(.height, to: 22)
imageView.set(.width, to: 24)
imageView.set(.height, to: 32)
if attachment.isAudio {
let audioImageView = UIImageView(
image: UIImage(systemName: "music.note")?
.withRenderingMode(.alwaysTemplate)
)
audioImageView.contentMode = .scaleAspectFit
audioImageView.themeTintColor = textColor
imageView.addSubview(audioImageView)
audioImageView.center(.horizontal, in: imageView)
audioImageView.center(.vertical, in: imageView, withInset: 4)
audioImageView.set(.height, to: .height, of: imageView, multiplier: 0.32)
}
// Body label
let titleLabel = UILabel()
titleLabel.font = .systemFont(ofSize: Values.mediumFontSize)
titleLabel.text = (attachment.sourceFilename ?? "File")
titleLabel.text = attachment.documentFileName
titleLabel.themeTextColor = textColor
titleLabel.lineBreakMode = .byTruncatingTail
// Size label
let sizeLabel = UILabel()
sizeLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
sizeLabel.text = Format.fileSize(attachment.byteCount)
sizeLabel.text = attachment.documentFileInfo
sizeLabel.themeTextColor = textColor
sizeLabel.lineBreakMode = .byTruncatingTail
@ -55,14 +70,19 @@ final class DocumentView: UIView {
labelStackView.axis = .vertical
// Download image view
let downloadImageView = UIImageView(
image: UIImage(systemName: "arrow.down")?
.withRenderingMode(.alwaysTemplate)
let rightImageView = UIImageView(
image: {
switch attachment.isAudio {
case true: return UIImage(systemName: "play.fill")
case false: return UIImage(systemName: "arrow.down")
}
}()?.withRenderingMode(.alwaysTemplate)
)
downloadImageView.setContentCompressionResistancePriority(.required, for: .horizontal)
downloadImageView.setContentHuggingPriority(.required, for: .horizontal)
downloadImageView.themeTintColor = textColor
downloadImageView.set(.height, to: 16)
rightImageView.setContentCompressionResistancePriority(.required, for: .horizontal)
rightImageView.setContentHuggingPriority(.required, for: .horizontal)
rightImageView.contentMode = .scaleAspectFit
rightImageView.themeTintColor = textColor
rightImageView.set(.height, to: 24)
// Stack view
let stackView = UIStackView(
@ -70,7 +90,7 @@ final class DocumentView: UIView {
imageView,
UIView.spacer(withWidth: 0),
labelStackView,
downloadImageView
rightImageView
]
)
stackView.axis = .horizontal

View File

@ -3,11 +3,14 @@
import UIKit
import SessionMessagingKit
import SignalCoreKit
import SessionUtilitiesKit
public class MediaAlbumView: UIStackView {
private let items: [Attachment]
public let itemViews: [MediaView]
public var moreItemsView: MediaView?
public var numItems: Int { return items.count }
public var numVisibleItems: Int { return itemViews.count }
private static let kSpacingPts: CGFloat = 4
private static let kMaxItems = 3
@ -23,13 +26,22 @@ public class MediaAlbumView: UIStackView {
isOutgoing: Bool,
maxMessageWidth: CGFloat
) {
let itemsToDisplay: [Attachment] = MediaAlbumView.itemsToDisplay(forItems: items)
self.items = items
self.itemViews = MediaAlbumView.itemsToDisplay(forItems: items)
.map {
self.itemViews = itemsToDisplay.enumerated()
.map { index, attachment -> MediaView in
MediaView(
mediaCache: mediaCache,
attachment: $0,
attachment: attachment,
isOutgoing: isOutgoing,
shouldSupressControls: (
// If there are extra items that aren't displayed and this is the
// last one that will be displayed then suppress any custom controls
// otherwise the '+' icon will be obscured
itemsToDisplay.count != items.count &&
(index == (itemsToDisplay.count - 1))
),
cornerRadius: VisibleMessageCell.largeCornerRadius
)
}

View File

@ -6,6 +6,7 @@ import SessionUIKit
import SessionMessagingKit
import SignalCoreKit
import SignalUtilitiesKit
import SessionUtilitiesKit
public class MediaView: UIView {
static let contentMode: UIView.ContentMode = .scaleAspectFill
@ -21,6 +22,7 @@ public class MediaView: UIView {
private let mediaCache: NSCache<NSString, AnyObject>?
public let attachment: Attachment
private let isOutgoing: Bool
private let shouldSupressControls: Bool
private var loadBlock: (() -> Void)?
private var unloadBlock: (() -> Void)?
@ -50,11 +52,13 @@ public class MediaView: UIView {
mediaCache: NSCache<NSString, AnyObject>? = nil,
attachment: Attachment,
isOutgoing: Bool,
shouldSupressControls: Bool,
cornerRadius: CGFloat
) {
self.mediaCache = mediaCache
self.attachment = attachment
self.isOutgoing = isOutgoing
self.shouldSupressControls = shouldSupressControls
super.init(frame: .zero)
@ -274,7 +278,29 @@ public class MediaView: UIView {
addSubview(stillImageView)
stillImageView.autoPinEdgesToSuperviewEdges()
if !addUploadProgressIfNecessary(stillImageView) {
if !addUploadProgressIfNecessary(stillImageView) && !shouldSupressControls {
if let duration: TimeInterval = attachment.duration {
let fadeView: GradientView = GradientView()
fadeView.themeBackgroundGradient = [
.value(.black, alpha: 0),
.value(.black, alpha: 0.4)
]
stillImageView.addSubview(fadeView)
fadeView.set(.height, to: 40)
fadeView.pin(.leading, to: .leading, of: stillImageView)
fadeView.pin(.trailing, to: .trailing, of: stillImageView)
fadeView.pin(.bottom, to: .bottom, of: stillImageView)
let durationLabel: UILabel = UILabel()
durationLabel.font = .systemFont(ofSize: Values.smallFontSize)
durationLabel.text = Format.duration(duration)
durationLabel.themeTextColor = .white
stillImageView.addSubview(durationLabel)
durationLabel.pin(.trailing, to: .trailing, of: stillImageView, withInset: -Values.smallSpacing)
durationLabel.pin(.bottom, to: .bottom, of: stillImageView, withInset: -Values.smallSpacing)
}
// Add the play button above the duration label and fade
let videoPlayIcon = UIImage(named: "CirclePlay")
let videoPlayButton = UIImageView(image: videoPlayIcon)
videoPlayButton.set(.width, to: 72)

View File

@ -105,7 +105,6 @@ final class QuoteView: UIView {
availableWidth -= cancelButtonSize
}
let availableSpace = CGSize(width: availableWidth, height: .greatestFiniteMagnitude)
var body: String? = quotedText
// Main stack view
@ -119,8 +118,7 @@ final class QuoteView: UIView {
// Content view
let contentView = UIView()
addSubview(contentView)
contentView.pin([ UIView.HorizontalEdge.left, UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: self)
contentView.rightAnchor.constraint(lessThanOrEqualTo: self.rightAnchor).isActive = true
contentView.pin(to: self)
if let attachment: Attachment = attachment {
let isAudio: Bool = MIMETypeUtil.isAudio(attachment.contentType)
@ -156,7 +154,7 @@ final class QuoteView: UIView {
if attachment.isVisualMedia {
attachment.thumbnail(
size: .small,
success: { image, _ in
success: { [imageView] image, _ in
guard Thread.isMainThread else {
DispatchQueue.main.async {
imageView.image = image
@ -234,8 +232,6 @@ final class QuoteView: UIView {
}
// Label stack view
let bodyLabelSize = bodyLabel.systemLayoutSizeFitting(availableSpace)
let isCurrentUser: Bool = [
currentUserPublicKey,
currentUserBlinded15PublicKey,
@ -288,9 +284,8 @@ final class QuoteView: UIView {
cancelButton.set(.height, to: cancelButtonSize)
cancelButton.addTarget(self, action: #selector(cancel), for: UIControl.Event.touchUpInside)
addSubview(cancelButton)
mainStackView.addArrangedSubview(cancelButton)
cancelButton.center(.vertical, in: self)
cancelButton.pin(.right, to: .right, of: self)
}
}

View File

@ -3,6 +3,7 @@
import UIKit
import SessionUIKit
import SignalCoreKit
import SessionUtilitiesKit
@objc class TypingIndicatorView: UIStackView {
// This represents the spacing between the dots

View File

@ -112,7 +112,6 @@ public final class VoiceMessageView: UIView {
}
private func setUpViewHierarchy() {
let toggleContainerSize = VoiceMessageView.toggleContainerSize
let inset = VoiceMessageView.inset
// Width & height

View File

@ -2,6 +2,7 @@
import UIKit
import SessionMessagingKit
import SessionUtilitiesKit
public enum SwipeState {
case began
@ -87,12 +88,18 @@ public class MessageCell: UITableViewCell {
protocol MessageCellDelegate: ReactionDelegate {
func handleItemLongPressed(_ cellViewModel: MessageViewModel)
func handleItemTapped(_ cellViewModel: MessageViewModel, gestureRecognizer: UITapGestureRecognizer)
func handleItemTapped(_ cellViewModel: MessageViewModel, gestureRecognizer: UITapGestureRecognizer, using dependencies: Dependencies)
func handleItemDoubleTapped(_ cellViewModel: MessageViewModel)
func handleItemSwiped(_ cellViewModel: MessageViewModel, state: SwipeState)
func openUrl(_ urlString: String)
func handleReplyButtonTapped(for cellViewModel: MessageViewModel)
func handleReplyButtonTapped(for cellViewModel: MessageViewModel, using dependencies: Dependencies)
func startThread(with sessionId: String, openGroupServer: String?, openGroupPublicKey: String?)
func showReactionList(_ cellViewModel: MessageViewModel, selectedReaction: EmojiWithSkinTones?)
func needsLayout(for cellViewModel: MessageViewModel, expandingReactions: Bool)
}
extension MessageCellDelegate {
func handleItemTapped(_ cellViewModel: MessageViewModel, gestureRecognizer: UITapGestureRecognizer) {
handleItemTapped(cellViewModel, gestureRecognizer: gestureRecognizer, using: Dependencies())
}
}

View File

@ -52,7 +52,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
profilePictureView,
replyButton,
timerView,
messageStatusImageView,
messageStatusContainerView,
reactionContainerView
]
@ -467,7 +467,6 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
subview.removeFromSuperview()
}
albumView = nil
albumView = nil
bodyTappableLabel = nil
// Handle the deleted state first (it's much simpler than the others)
@ -612,7 +611,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
unloadContent = { albumView.unloadMedia() }
case .audio:
case .voiceMessage:
guard let attachment: Attachment = cellViewModel.attachments?.first(where: { $0.isAudio }) else {
return
}
@ -631,7 +630,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
snContentView.addArrangedSubview(bubbleBackgroundView)
self.voiceMessageView = voiceMessageView
case .genericAttachment:
case .audio, .genericAttachment:
guard let attachment: Attachment = cellViewModel.attachments?.first else { preconditionFailure() }
let inset: CGFloat = 12
@ -742,7 +741,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
}
switch cellViewModel.cellType {
case .audio:
case .voiceMessage:
guard let attachment: Attachment = cellViewModel.attachments?.first(where: { $0.isAudio }) else {
return
}
@ -861,7 +860,9 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
isHandlingLongPress = true
}
@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) { onTap(gestureRecognizer) }
private func onTap(_ gestureRecognizer: UITapGestureRecognizer, using dependencies: Dependencies = Dependencies()) {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }
let location = gestureRecognizer.location(in: self)
@ -897,10 +898,10 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
if reactionContainerView.convert(reactionView.frame, from: reactionView.superview).contains(convertedLocation) {
if reactionView.viewModel.showBorder {
delegate?.removeReact(cellViewModel, for: reactionView.viewModel.emoji)
delegate?.removeReact(cellViewModel, for: reactionView.viewModel.emoji, using: dependencies)
}
else {
delegate?.react(cellViewModel, with: reactionView.viewModel.emoji)
delegate?.react(cellViewModel, with: reactionView.viewModel.emoji, using: dependencies)
}
return
}
@ -917,7 +918,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
}
}
else if snContentView.bounds.contains(snContentView.convert(location, from: self)) {
delegate?.handleItemTapped(cellViewModel, gestureRecognizer: gestureRecognizer)
delegate?.handleItemTapped(cellViewModel, gestureRecognizer: gestureRecognizer, using: dependencies)
}
}
@ -985,11 +986,11 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
}
}
private func reply() {
private func reply(using dependencies: Dependencies = Dependencies()) {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }
resetReply()
delegate?.handleReplyButtonTapped(for: cellViewModel)
delegate?.handleReplyButtonTapped(for: cellViewModel, using: dependencies)
}
// MARK: - Convenience

View File

@ -9,27 +9,14 @@ import SessionMessagingKit
import SessionUtilitiesKit
import SessionSnodeKit
class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadDisappearingMessagesSettingsViewModel.NavButton, ThreadDisappearingMessagesSettingsViewModel.Section, ThreadDisappearingMessagesSettingsViewModel.Item> {
// MARK: - Config
class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, NavigationItemSource, NavigatableStateHolder, ObservableTableSource {
typealias TableItem = String
enum NavButton: Equatable {
case cancel
case save
}
public let dependencies: Dependencies
public let navigatableState: NavigatableState = NavigatableState()
public let state: TableDataState<Section, TableItem> = TableDataState()
public let observableState: ObservableTableSourceState<Section, TableItem> = ObservableTableSourceState()
public enum Section: SessionTableSection {
case content
}
public struct Item: Equatable, Hashable, Differentiable {
let title: String
public var differenceIdentifier: String { title }
}
// MARK: - Variables
private let dependencies: Dependencies
private let threadId: String
private let threadVariant: SessionThread.Variant
private let config: DisappearingMessagesConfiguration
@ -39,10 +26,10 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadD
// MARK: - Initialization
init(
dependencies: Dependencies = Dependencies(),
threadId: String,
threadVariant: SessionThread.Variant,
config: DisappearingMessagesConfiguration
config: DisappearingMessagesConfiguration,
using dependencies: Dependencies = Dependencies()
) {
self.dependencies = dependencies
self.threadId = threadId
@ -52,65 +39,65 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadD
self.currentSelection = CurrentValueSubject(self.storedSelection)
}
// MARK: - Config
enum NavItem: Equatable {
case cancel
case save
}
public enum Section: SessionTableSection {
case content
}
// MARK: - Navigation
override var leftNavItems: AnyPublisher<[NavItem]?, Never> {
Just([
NavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
) { [weak self] in self?.dismissScreen() }
]).eraseToAnyPublisher()
}
lazy var leftNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = [
SessionNavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
) { [weak self] in self?.dismissScreen() }
]
override var rightNavItems: AnyPublisher<[NavItem]?, Never> {
currentSelection
.removeDuplicates()
.map { [weak self] currentSelection in (self?.storedSelection != currentSelection) }
.map { isChanged in
guard isChanged else { return [] }
return [
NavItem(
id: .save,
systemItem: .save,
accessibilityIdentifier: "Save button"
) { [weak self] in
self?.saveChanges()
self?.dismissScreen()
}
]
}
.eraseToAnyPublisher()
}
lazy var rightNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = currentSelection
.removeDuplicates()
.map { [weak self] currentSelection in (self?.storedSelection != currentSelection) }
.map { [weak self, dependencies] isChanged in
guard isChanged else { return [] }
return [
SessionNavItem(
id: .save,
systemItem: .save,
accessibilityIdentifier: "Save button"
) {
self?.saveChanges(using: dependencies)
self?.dismissScreen()
}
]
}
.eraseToAnyPublisher()
// MARK: - Content
override var title: String { "DISAPPEARING_MESSAGES".localized() }
let title: String = "DISAPPEARING_MESSAGES".localized()
public override var observableTableData: ObservableData { _observableTableData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableTableData: ObservableData = ValueObservation
.trackingConstantRegion { [weak self, config, dependencies, threadId = self.threadId] db -> [SectionModel] in
let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
let maybeThreadViewModel: SessionThreadViewModel? = try SessionThreadViewModel
lazy var observation: TargetObservation = ObservationBuilder
.databaseObservation(self) { [dependencies, threadId = self.threadId] db -> SessionThreadViewModel? in
let userPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
return try SessionThreadViewModel
.conversationSettingsQuery(threadId: threadId, userPublicKey: userPublicKey)
.fetchOne(db)
}
.map { [weak self, config, dependencies, threadId = self.threadId] maybeThreadViewModel -> [SectionModel] in
return [
SectionModel(
model: .content,
elements: [
SessionCell.Info(
id: Item(title: "DISAPPEARING_MESSAGES_OFF".localized()),
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value == 0) }
@ -130,7 +117,7 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadD
let title: String = duration.formatted(format: .long)
return SessionCell.Info(
id: Item(title: title),
id: title,
title: title,
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value == duration) }
@ -149,14 +136,10 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadD
)
]
}
.removeDuplicates()
.handleEvents(didFail: { SNLog("[ThreadDisappearingMessageSettingsViewModel] Observation failed with error: \($0)") })
.publisher(in: dependencies.storage, scheduling: dependencies.scheduler)
.mapToSessionTableViewData(for: self)
// MARK: - Functions
private func saveChanges() {
private func saveChanges(using dependencies: Dependencies = Dependencies()) {
let threadId: String = self.threadId
let threadVariant: SessionThread.Variant = self.threadVariant
let currentSelection: TimeInterval = self.currentSelection.value
@ -195,7 +178,8 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel<ThreadD
),
interactionId: interaction.id,
threadId: threadId,
threadVariant: threadVariant
threadVariant: threadVariant,
using: dependencies
)
// Legacy closed groups

View File

@ -9,8 +9,45 @@ import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SessionUtilitiesKit
import SessionSnodeKit
class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.NavButton, ThreadSettingsViewModel.Section, ThreadSettingsViewModel.Setting> {
class ThreadSettingsViewModel: SessionTableViewModel, NavigationItemSource, NavigatableStateHolder, EditableStateHolder, ObservableTableSource {
public let dependencies: Dependencies
public let navigatableState: NavigatableState = NavigatableState()
public let editableState: EditableState<TableItem> = EditableState()
public let state: TableDataState<Section, TableItem> = TableDataState()
public let observableState: ObservableTableSourceState<Section, TableItem> = ObservableTableSourceState()
private let threadId: String
private let threadVariant: SessionThread.Variant
private let didTriggerSearch: () -> ()
private var oldDisplayName: String?
private var editedDisplayName: String?
// MARK: - Initialization
init(
threadId: String,
threadVariant: SessionThread.Variant,
didTriggerSearch: @escaping () -> (),
using dependencies: Dependencies = Dependencies()
) {
self.dependencies = dependencies
self.threadId = threadId
self.threadVariant = threadVariant
self.didTriggerSearch = didTriggerSearch
self.oldDisplayName = (threadVariant != .contact ?
nil :
dependencies.storage.read { db in
try Profile
.filter(id: threadId)
.select(.nickname)
.asRequest(of: String.self)
.fetchOne(db)
}
)
}
// MARK: - Config
enum NavState {
@ -18,7 +55,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
case editing
}
enum NavButton: Equatable {
enum NavItem: Equatable {
case edit
case cancel
case done
@ -29,7 +66,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
case content
}
public enum Setting: Differentiable {
public enum TableItem: Differentiable {
case avatar
case nickname
case sessionId
@ -48,39 +85,6 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
case blockUser
}
// MARK: - Variables
private let dependencies: Dependencies
private let threadId: String
private let threadVariant: SessionThread.Variant
private let didTriggerSearch: () -> ()
private var oldDisplayName: String?
private var editedDisplayName: String?
// MARK: - Initialization
init(
dependencies: Dependencies = Dependencies(),
threadId: String,
threadVariant: SessionThread.Variant,
didTriggerSearch: @escaping () -> ()
) {
self.dependencies = dependencies
self.threadId = threadId
self.threadVariant = threadVariant
self.didTriggerSearch = didTriggerSearch
self.oldDisplayName = (threadVariant != .contact ?
nil :
dependencies.storage.read { db in
try Profile
.filter(id: threadId)
.select(.nickname)
.asRequest(of: String.self)
.fetchOne(db)
}
)
}
// MARK: - Navigation
lazy var navState: AnyPublisher<NavState, Never> = {
@ -103,112 +107,97 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
.eraseToAnyPublisher()
}()
override var leftNavItems: AnyPublisher<[NavItem]?, Never> {
navState
.map { [weak self] navState -> [NavItem] in
// Only show the 'Edit' button if it's a contact thread
guard self?.threadVariant == .contact else { return [] }
guard navState == .editing else { return [] }
lazy var leftNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = navState
.map { [weak self] navState -> [SessionNavItem<NavItem>] in
// Only show the 'Edit' button if it's a contact thread
guard self?.threadVariant == .contact else { return [] }
guard navState == .editing else { return [] }
return [
NavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
) { [weak self] in
self?.setIsEditing(false)
self?.editedDisplayName = self?.oldDisplayName
}
]
}
.eraseToAnyPublisher()
}
override var rightNavItems: AnyPublisher<[NavItem]?, Never> {
navState
.map { [weak self, dependencies] navState -> [NavItem] in
// Only show the 'Edit' button if it's a contact thread
guard self?.threadVariant == .contact else { return [] }
switch navState {
case .editing:
return [
NavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done"
) { [weak self] in
self?.setIsEditing(false)
guard
self?.threadVariant == .contact,
let threadId: String = self?.threadId,
let editedDisplayName: String = self?.editedDisplayName
else { return }
let updatedNickname: String = editedDisplayName
.trimmingCharacters(in: .whitespacesAndNewlines)
self?.oldDisplayName = (updatedNickname.isEmpty ? nil : editedDisplayName)
dependencies.storage.writeAsync { db in
try Profile
.filter(id: threadId)
.updateAllAndConfig(
db,
Profile.Columns.nickname
.set(to: (updatedNickname.isEmpty ? nil : editedDisplayName))
)
}
}
]
case .standard:
return [
NavItem(
id: .edit,
systemItem: .edit,
accessibilityIdentifier: "Edit button",
accessibilityLabel: "Edit user nickname"
) { [weak self] in self?.setIsEditing(true) }
]
return [
SessionNavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
) { [weak self] in
self?.setIsEditing(false)
self?.editedDisplayName = self?.oldDisplayName
}
}
.eraseToAnyPublisher()
}
]
}
.eraseToAnyPublisher()
lazy var rightNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = navState
.map { [weak self, dependencies] navState -> [SessionNavItem<NavItem>] in
// Only show the 'Edit' button if it's a contact thread
guard self?.threadVariant == .contact else { return [] }
switch navState {
case .editing:
return [
SessionNavItem(
id: .done,
systemItem: .done,
accessibilityIdentifier: "Done"
) { [weak self] in
self?.setIsEditing(false)
guard
self?.threadVariant == .contact,
let threadId: String = self?.threadId,
let editedDisplayName: String = self?.editedDisplayName
else { return }
let updatedNickname: String = editedDisplayName
.trimmingCharacters(in: .whitespacesAndNewlines)
self?.oldDisplayName = (updatedNickname.isEmpty ? nil : editedDisplayName)
dependencies.storage.writeAsync(using: dependencies) { db in
try Profile
.filter(id: threadId)
.updateAllAndConfig(
db,
Profile.Columns.nickname
.set(to: (updatedNickname.isEmpty ? nil : editedDisplayName))
)
}
}
]
case .standard:
return [
SessionNavItem(
id: .edit,
systemItem: .edit,
accessibilityIdentifier: "Edit button",
accessibilityLabel: "Edit user nickname"
) { [weak self] in self?.setIsEditing(true) }
]
}
}
.eraseToAnyPublisher()
// MARK: - Content
override var title: String {
private struct State: Equatable {
let threadViewModel: SessionThreadViewModel?
let notificationSound: Preferences.Sound
let disappearingMessagesConfig: DisappearingMessagesConfiguration
}
var title: String {
switch threadVariant {
case .contact: return "vc_settings_title".localized()
case .legacyGroup, .group, .community: return "vc_group_settings_title".localized()
}
}
public override var observableTableData: ObservableData { _observableTableData }
/// This is all the data the screen needs to populate itself, please see the following link for tips to help optimise
/// performance https://github.com/groue/GRDB.swift#valueobservation-performance
///
/// **Note:** This observation will be triggered twice immediately (and be de-duped by the `removeDuplicates`)
/// this is due to the behaviour of `ValueConcurrentObserver.asyncStartObservation` which triggers it's own
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
private lazy var _observableTableData: ObservableData = ValueObservation
.trackingConstantRegion { [weak self, dependencies, threadId = self.threadId, threadVariant = self.threadVariant] db -> [SectionModel] in
let userPublicKey: String = getUserHexEncodedPublicKey(db, dependencies: dependencies)
let maybeThreadViewModel: SessionThreadViewModel? = try SessionThreadViewModel
lazy var observation: TargetObservation = ObservationBuilder
.databaseObservation(self) { [dependencies, threadId = self.threadId] db -> State in
let userPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
let threadViewModel: SessionThreadViewModel? = try SessionThreadViewModel
.conversationSettingsQuery(threadId: threadId, userPublicKey: userPublicKey)
.fetchOne(db)
// If we don't get a `SessionThreadViewModel` then it means the thread was probably deleted
// so dismiss the screen
guard let threadViewModel: SessionThreadViewModel = maybeThreadViewModel else {
self?.dismissScreen(type: .popToRoot)
return []
}
// Additional Queries
let fallbackSound: Preferences.Sound = db[.defaultNotificationSound]
.defaulting(to: Preferences.Sound.defaultNotificationSound)
let notificationSound: Preferences.Sound = try SessionThread
@ -220,17 +209,32 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
let disappearingMessagesConfig: DisappearingMessagesConfiguration = try DisappearingMessagesConfiguration
.fetchOne(db, id: threadId)
.defaulting(to: DisappearingMessagesConfiguration.defaultWith(threadId))
return State(
threadViewModel: threadViewModel,
notificationSound: notificationSound,
disappearingMessagesConfig: disappearingMessagesConfig
)
}
.mapWithPrevious { [weak self, dependencies] previous, current -> [SectionModel] in
// If we don't get a `SessionThreadViewModel` then it means the thread was probably deleted
// so dismiss the screen
guard let threadViewModel: SessionThreadViewModel = current.threadViewModel else {
self?.dismissScreen(type: .popToRoot)
return []
}
let currentUserIsClosedGroupMember: Bool = (
(
threadVariant == .legacyGroup ||
threadVariant == .group
threadViewModel.threadVariant == .legacyGroup ||
threadViewModel.threadVariant == .group
) &&
threadViewModel.currentUserIsClosedGroupMember == true
)
let currentUserIsClosedGroupAdmin: Bool = (
(
threadVariant == .legacyGroup ||
threadVariant == .group
threadViewModel.threadVariant == .legacyGroup ||
threadViewModel.threadVariant == .group
) &&
threadViewModel.currentUserIsClosedGroupAdmin == true
)
@ -245,7 +249,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
accessory: .profile(
id: threadViewModel.id,
size: .hero,
threadVariant: threadVariant,
threadVariant: threadViewModel.threadVariant,
customImageData: threadViewModel.openGroupProfilePictureData,
profile: threadViewModel.profile,
profileIcon: .none,
@ -262,7 +266,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
SessionCell.Info(
id: .nickname,
leftAccessory: (threadVariant != .contact ? nil :
leftAccessory: (threadViewModel.threadVariant != .contact ? nil :
.icon(
editIcon?.withRenderingMode(.alwaysTemplate),
size: .fit,
@ -274,17 +278,17 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
font: .titleLarge,
alignment: .center,
editingPlaceholder: "CONTACT_NICKNAME_PLACEHOLDER".localized(),
interaction: (threadVariant == .contact ? .editable : .none)
interaction: (threadViewModel.threadVariant == .contact ? .editable : .none)
),
styling: SessionCell.StyleInfo(
alignment: .centerHugging,
customPadding: SessionCell.Padding(
top: Values.smallSpacing,
trailing: (threadVariant != .contact ?
trailing: (threadViewModel.threadVariant != .contact ?
nil :
-(((editIcon?.size.width ?? 0) + (Values.smallSpacing * 2)) / 2)
),
bottom: (threadVariant != .contact ?
bottom: (threadViewModel.threadVariant != .contact ?
nil :
Values.smallSpacing
),
@ -302,7 +306,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
}
),
(threadVariant != .contact ? nil :
(threadViewModel.threadVariant != .contact ? nil :
SessionCell.Info(
id: .sessionId,
subtitle: SessionCell.TextInfo(
@ -329,14 +333,14 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
SectionModel(
model: .content,
elements: [
(threadVariant == .legacyGroup || threadVariant == .group ? nil :
(threadViewModel.threadVariant == .legacyGroup || threadViewModel.threadVariant == .group ? nil :
SessionCell.Info(
id: .copyThreadId,
leftAccessory: .icon(
UIImage(named: "ic_copy")?
.withRenderingMode(.alwaysTemplate)
),
title: (threadVariant == .community ?
title: (threadViewModel.threadVariant == .community ?
"COPY_GROUP_URL".localized() :
"vc_conversation_settings_copy_session_id_button_title".localized()
),
@ -345,9 +349,9 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
label: "Copy Session ID"
),
onTap: {
switch threadVariant {
switch threadViewModel.threadVariant {
case .contact, .legacyGroup, .group:
UIPasteboard.general.string = threadId
UIPasteboard.general.string = threadViewModel.threadId
case .community:
guard
@ -385,8 +389,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
onTap: { [weak self] in
self?.transitionToScreen(
MediaGalleryViewModel.createAllMediaViewController(
threadId: threadId,
threadVariant: threadVariant,
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant,
focusedAttachmentId: nil
)
)
@ -409,7 +413,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
}
),
(threadVariant != .community ? nil :
(threadViewModel.threadVariant != .community ? nil :
SessionCell.Info(
id: .addToOpenGroup,
leftAccessory: .icon(
@ -436,12 +440,12 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
)
),
(threadVariant == .community || threadViewModel.threadIsBlocked == true ? nil :
(threadViewModel.threadVariant == .community || threadViewModel.threadIsBlocked == true ? nil :
SessionCell.Info(
id: .disappearingMessages,
leftAccessory: .icon(
UIImage(
named: (disappearingMessagesConfig.isEnabled ?
named: (current.disappearingMessagesConfig.isEnabled ?
"ic_timer" :
"ic_timer_disabled"
)
@ -451,10 +455,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
)
),
title: "DISAPPEARING_MESSAGES".localized(),
subtitle: (disappearingMessagesConfig.isEnabled ?
subtitle: (current.disappearingMessagesConfig.isEnabled ?
String(
format: "DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER".localized(),
arguments: [disappearingMessagesConfig.durationString]
arguments: [current.disappearingMessagesConfig.durationString]
) :
"DISAPPEARING_MESSAGES_SUBTITLE_OFF".localized()
),
@ -466,9 +470,9 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
self?.transitionToScreen(
SessionTableViewController(
viewModel: ThreadDisappearingMessagesSettingsViewModel(
threadId: threadId,
threadVariant: threadVariant,
config: disappearingMessagesConfig
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant,
config: current.disappearingMessagesConfig
)
)
)
@ -490,7 +494,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
onTap: { [weak self] in
self?.transitionToScreen(
EditClosedGroupVC(threadId: threadId, threadVariant: threadVariant)
EditClosedGroupVC(
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant
)
)
}
)
@ -536,8 +543,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
dependencies.storage.write { db in
try SessionThread.deleteOrLeave(
db,
threadId: threadId,
threadVariant: threadVariant,
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant,
groupLeaveType: .standard,
calledFromConfigHandling: false
)
@ -555,19 +562,19 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
title: "SETTINGS_ITEM_NOTIFICATION_SOUND".localized(),
rightAccessory: .dropDown(
.dynamicString { notificationSound.displayName }
.dynamicString { current.notificationSound.displayName }
),
onTap: { [weak self] in
self?.transitionToScreen(
SessionTableViewController(
viewModel: NotificationSoundViewModel(threadId: threadId)
viewModel: NotificationSoundViewModel(threadId: threadViewModel.threadId)
)
)
}
)
),
(threadVariant == .contact ? nil :
(threadViewModel.threadVariant == .contact ? nil :
SessionCell.Info(
id: .notificationMentionsOnly,
leftAccessory: .icon(
@ -577,7 +584,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
title: "vc_conversation_settings_notify_for_mentions_only_title".localized(),
subtitle: "vc_conversation_settings_notify_for_mentions_only_explanation".localized(),
rightAccessory: .toggle(
.boolValue(threadViewModel.threadOnlyNotifyForMentions == true)
.boolValue(
threadViewModel.threadOnlyNotifyForMentions == true,
oldValue: ((previous?.threadViewModel ?? threadViewModel).threadOnlyNotifyForMentions == true)
)
),
isEnabled: (
(
@ -595,7 +605,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
dependencies.storage.writeAsync { db in
try SessionThread
.filter(id: threadId)
.filter(id: threadViewModel.threadId)
.updateAll(
db,
SessionThread.Columns.onlyNotifyForMentions
@ -615,7 +625,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
title: "CONVERSATION_SETTINGS_MUTE_LABEL".localized(),
rightAccessory: .toggle(
.boolValue(threadViewModel.threadMutedUntilTimestamp != nil)
.boolValue(
threadViewModel.threadMutedUntilTimestamp != nil,
oldValue: ((previous?.threadViewModel ?? threadViewModel).threadMutedUntilTimestamp != nil)
)
),
isEnabled: (
(
@ -631,13 +644,13 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
onTap: {
dependencies.storage.writeAsync { db in
let currentValue: TimeInterval? = try SessionThread
.filter(id: threadId)
.filter(id: threadViewModel.threadId)
.select(.mutedUntilTimestamp)
.asRequest(of: TimeInterval.self)
.fetchOne(db)
try SessionThread
.filter(id: threadId)
.filter(id: threadViewModel.threadId)
.updateAll(
db,
SessionThread.Columns.mutedUntilTimestamp.set(
@ -652,7 +665,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
)
),
(threadViewModel.threadIsNoteToSelf || threadVariant != .contact ? nil :
(threadViewModel.threadIsNoteToSelf || threadViewModel.threadVariant != .contact ? nil :
SessionCell.Info(
id: .blockUser,
leftAccessory: .icon(
@ -661,7 +674,10 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
),
title: "CONVERSATION_SETTINGS_BLOCK_THIS_USER".localized(),
rightAccessory: .toggle(
.boolValue(threadViewModel.threadIsBlocked == true)
.boolValue(
threadViewModel.threadIsBlocked == true,
oldValue: ((previous?.threadViewModel ?? threadViewModel).threadIsBlocked == true)
)
),
accessibility: Accessibility(
identifier: "\(ThreadSettingsViewModel.self).block",
@ -698,7 +714,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
self?.updateBlockedState(
from: isBlocked,
isBlocked: !isBlocked,
threadId: threadId,
threadId: threadViewModel.threadId,
displayName: threadViewModel.displayName
)
}
@ -708,10 +724,6 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
)
]
}
.removeDuplicates()
.handleEvents(didFail: { SNLog("[ThreadSettingsViewModel] Observation failed with error: \($0)") })
.publisher(in: dependencies.storage, scheduling: dependencies.scheduler)
.mapToSessionTableViewData(for: self)
// MARK: - Functions
@ -755,7 +767,7 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
publicKey: publicKey
)
dependencies.storage.writeAsync { db in
dependencies.storage.writeAsync { [dependencies] db in
try selectedUsers.forEach { userId in
let thread: SessionThread = try SessionThread
.fetchOrCreate(db, id: userId, variant: .contact, shouldBeVisible: nil)
@ -786,7 +798,8 @@ class ThreadSettingsViewModel: SessionTableViewModel<ThreadSettingsViewModel.Nav
db,
interaction: interaction,
threadId: thread.id,
threadVariant: thread.variant
threadVariant: thread.variant,
using: dependencies
)
}
}

View File

@ -5,6 +5,7 @@ import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SessionUtilitiesKit
final class ReactionListSheet: BaseVC {
public struct ReactionSummary: Hashable, Differentiable {
@ -368,10 +369,12 @@ final class ReactionListSheet: BaseVC {
dismiss(animated: true, completion: nil)
}
@objc private func clearAllTapped() {
@objc private func clearAllTapped() { clearAll() }
private func clearAll(using dependencies: Dependencies = Dependencies()) {
guard let selectedReaction: EmojiWithSkinTones = self.reactionSummaries.first(where: { $0.isSelected })?.emoji else { return }
delegate?.removeAllReactions(messageViewModel, for: selectedReaction.rawValue)
delegate?.removeAllReactions(messageViewModel, for: selectedReaction.rawValue, using: dependencies)
}
}
@ -599,7 +602,13 @@ extension ReactionListSheet {
// MARK: - Delegate
protocol ReactionDelegate: AnyObject {
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones)
func removeReact(_ cellViewModel: MessageViewModel, for emoji: EmojiWithSkinTones)
func removeAllReactions(_ cellViewModel: MessageViewModel, for emoji: String)
func react(_ cellViewModel: MessageViewModel, with emoji: EmojiWithSkinTones, using dependencies: Dependencies)
func removeReact(_ cellViewModel: MessageViewModel, for emoji: EmojiWithSkinTones, using dependencies: Dependencies)
func removeAllReactions(_ cellViewModel: MessageViewModel, for emoji: String, using dependencies: Dependencies)
}
extension ReactionDelegate {
func removeReact(_ cellViewModel: MessageViewModel, for emoji: EmojiWithSkinTones) {
removeReact(cellViewModel, for: emoji, using: Dependencies())
}
}

View File

@ -1,5 +1,6 @@
import Foundation
import SignalCoreKit
import SessionUtilitiesKit
extension Emoji {
private static let availableCache: Atomic<[Emoji:Bool]> = Atomic([:])

View File

@ -1,6 +1,9 @@
// This file is generated by EmojiGenerator.swift, do not manually edit it.
// swiftlint:disable all
// stringlint:disable
extension Emoji {
enum Category: String, CaseIterable, Equatable {
case smileysAndPeople = "Smileys & People"
@ -86,6 +89,7 @@ extension Emoji {
.grimacing,
.faceExhaling,
.lyingFace,
.shakingFace,
.relieved,
.pensive,
.sleepy,
@ -163,7 +167,6 @@ extension Emoji {
.seeNoEvil,
.hearNoEvil,
.speakNoEvil,
.kiss,
.loveLetter,
.cupid,
.giftHeart,
@ -178,14 +181,18 @@ extension Emoji {
.heartOnFire,
.mendingHeart,
.heart,
.pinkHeart,
.orangeHeart,
.yellowHeart,
.greenHeart,
.blueHeart,
.lightBlueHeart,
.purpleHeart,
.brownHeart,
.blackHeart,
.greyHeart,
.whiteHeart,
.kiss,
.oneHundred,
.anger,
.boom,
@ -193,7 +200,6 @@ extension Emoji {
.sweatDrops,
.dash,
.hole,
.bomb,
.speechBalloon,
.eyeInSpeechBubble,
.leftSpeechBubble,
@ -209,6 +215,8 @@ extension Emoji {
.leftwardsHand,
.palmDownHand,
.palmUpHand,
.leftwardsPushingHand,
.rightwardsPushingHand,
.okHand,
.pinchedFingers,
.pinchingHand,
@ -584,6 +592,8 @@ extension Emoji {
.tiger2,
.leopard,
.horse,
.moose,
.donkey,
.racehorse,
.unicornFace,
.zebraFace,
@ -646,6 +656,9 @@ extension Emoji {
.flamingo,
.peacock,
.parrot,
.wing,
.blackBird,
.goose,
.frog,
.crocodile,
.turtle,
@ -666,6 +679,7 @@ extension Emoji {
.octopus,
.shell,
.coral,
.jellyfish,
.snail,
.butterfly,
.bug,
@ -693,6 +707,7 @@ extension Emoji {
.sunflower,
.blossom,
.tulip,
.hyacinth,
.seedling,
.pottedPlant,
.evergreenTree,
@ -708,6 +723,7 @@ extension Emoji {
.leaves,
.emptyNest,
.nestWithEggs,
.mushroom,
]
case .food:
return [
@ -742,10 +758,11 @@ extension Emoji {
.broccoli,
.garlic,
.onion,
.mushroom,
.peanuts,
.beans,
.chestnut,
.gingerRoot,
.peaPod,
.bread,
.croissant,
.baguetteBread,
@ -903,11 +920,10 @@ extension Emoji {
.dart,
.yoYo,
.kite,
.gun,
.eightBall,
.crystalBall,
.magicWand,
.nazarAmulet,
.hamsa,
.videoGame,
.joystick,
.slotMachine,
@ -1176,6 +1192,7 @@ extension Emoji {
.shorts,
.bikini,
.womansClothes,
.foldingHandFan,
.purse,
.handbag,
.pouch,
@ -1190,6 +1207,7 @@ extension Emoji {
.sandal,
.balletShoes,
.boot,
.hairPick,
.crown,
.womansHat,
.tophat,
@ -1228,6 +1246,8 @@ extension Emoji {
.banjo,
.drumWithDrumsticks,
.longDrum,
.maracas,
.flute,
.iphone,
.calling,
.phone,
@ -1347,7 +1367,7 @@ extension Emoji {
.hammerAndWrench,
.daggerKnife,
.crossedSwords,
.gun,
.bomb,
.boomerang,
.bowAndArrow,
.shield,
@ -1408,6 +1428,8 @@ extension Emoji {
.coffin,
.headstone,
.funeralUrn,
.nazarAmulet,
.hamsa,
.moyai,
.placard,
.identificationCard,
@ -1473,6 +1495,7 @@ extension Emoji {
.peaceSymbol,
.menorahWithNineBranches,
.sixPointedStar,
.khanda,
.aries,
.taurus,
.gemini,
@ -1508,6 +1531,7 @@ extension Emoji {
.lowBrightness,
.highBrightness,
.signalStrength,
.wireless,
.vibrationMode,
.mobilePhoneOff,
.femaleSign,
@ -1962,6 +1986,7 @@ extension Emoji {
case .grimacing: return .smileysAndPeople
case .faceExhaling: return .smileysAndPeople
case .lyingFace: return .smileysAndPeople
case .shakingFace: return .smileysAndPeople
case .relieved: return .smileysAndPeople
case .pensive: return .smileysAndPeople
case .sleepy: return .smileysAndPeople
@ -2039,7 +2064,6 @@ extension Emoji {
case .seeNoEvil: return .smileysAndPeople
case .hearNoEvil: return .smileysAndPeople
case .speakNoEvil: return .smileysAndPeople
case .kiss: return .smileysAndPeople
case .loveLetter: return .smileysAndPeople
case .cupid: return .smileysAndPeople
case .giftHeart: return .smileysAndPeople
@ -2054,14 +2078,18 @@ extension Emoji {
case .heartOnFire: return .smileysAndPeople
case .mendingHeart: return .smileysAndPeople
case .heart: return .smileysAndPeople
case .pinkHeart: return .smileysAndPeople
case .orangeHeart: return .smileysAndPeople
case .yellowHeart: return .smileysAndPeople
case .greenHeart: return .smileysAndPeople
case .blueHeart: return .smileysAndPeople
case .lightBlueHeart: return .smileysAndPeople
case .purpleHeart: return .smileysAndPeople
case .brownHeart: return .smileysAndPeople
case .blackHeart: return .smileysAndPeople
case .greyHeart: return .smileysAndPeople
case .whiteHeart: return .smileysAndPeople
case .kiss: return .smileysAndPeople
case .oneHundred: return .smileysAndPeople
case .anger: return .smileysAndPeople
case .boom: return .smileysAndPeople
@ -2069,7 +2097,6 @@ extension Emoji {
case .sweatDrops: return .smileysAndPeople
case .dash: return .smileysAndPeople
case .hole: return .smileysAndPeople
case .bomb: return .smileysAndPeople
case .speechBalloon: return .smileysAndPeople
case .eyeInSpeechBubble: return .smileysAndPeople
case .leftSpeechBubble: return .smileysAndPeople
@ -2085,6 +2112,8 @@ extension Emoji {
case .leftwardsHand: return .smileysAndPeople
case .palmDownHand: return .smileysAndPeople
case .palmUpHand: return .smileysAndPeople
case .leftwardsPushingHand: return .smileysAndPeople
case .rightwardsPushingHand: return .smileysAndPeople
case .okHand: return .smileysAndPeople
case .pinchedFingers: return .smileysAndPeople
case .pinchingHand: return .smileysAndPeople
@ -2457,6 +2486,8 @@ extension Emoji {
case .tiger2: return .animals
case .leopard: return .animals
case .horse: return .animals
case .moose: return .animals
case .donkey: return .animals
case .racehorse: return .animals
case .unicornFace: return .animals
case .zebraFace: return .animals
@ -2519,6 +2550,9 @@ extension Emoji {
case .flamingo: return .animals
case .peacock: return .animals
case .parrot: return .animals
case .wing: return .animals
case .blackBird: return .animals
case .goose: return .animals
case .frog: return .animals
case .crocodile: return .animals
case .turtle: return .animals
@ -2539,6 +2573,7 @@ extension Emoji {
case .octopus: return .animals
case .shell: return .animals
case .coral: return .animals
case .jellyfish: return .animals
case .snail: return .animals
case .butterfly: return .animals
case .bug: return .animals
@ -2566,6 +2601,7 @@ extension Emoji {
case .sunflower: return .animals
case .blossom: return .animals
case .tulip: return .animals
case .hyacinth: return .animals
case .seedling: return .animals
case .pottedPlant: return .animals
case .evergreenTree: return .animals
@ -2581,6 +2617,7 @@ extension Emoji {
case .leaves: return .animals
case .emptyNest: return .animals
case .nestWithEggs: return .animals
case .mushroom: return .animals
case .grapes: return .food
case .melon: return .food
case .watermelon: return .food
@ -2612,10 +2649,11 @@ extension Emoji {
case .broccoli: return .food
case .garlic: return .food
case .onion: return .food
case .mushroom: return .food
case .peanuts: return .food
case .beans: return .food
case .chestnut: return .food
case .gingerRoot: return .food
case .peaPod: return .food
case .bread: return .food
case .croissant: return .food
case .baguetteBread: return .food
@ -2988,11 +3026,10 @@ extension Emoji {
case .dart: return .activities
case .yoYo: return .activities
case .kite: return .activities
case .gun: return .activities
case .eightBall: return .activities
case .crystalBall: return .activities
case .magicWand: return .activities
case .nazarAmulet: return .activities
case .hamsa: return .activities
case .videoGame: return .activities
case .joystick: return .activities
case .slotMachine: return .activities
@ -3037,6 +3074,7 @@ extension Emoji {
case .shorts: return .objects
case .bikini: return .objects
case .womansClothes: return .objects
case .foldingHandFan: return .objects
case .purse: return .objects
case .handbag: return .objects
case .pouch: return .objects
@ -3051,6 +3089,7 @@ extension Emoji {
case .sandal: return .objects
case .balletShoes: return .objects
case .boot: return .objects
case .hairPick: return .objects
case .crown: return .objects
case .womansHat: return .objects
case .tophat: return .objects
@ -3089,6 +3128,8 @@ extension Emoji {
case .banjo: return .objects
case .drumWithDrumsticks: return .objects
case .longDrum: return .objects
case .maracas: return .objects
case .flute: return .objects
case .iphone: return .objects
case .calling: return .objects
case .phone: return .objects
@ -3208,7 +3249,7 @@ extension Emoji {
case .hammerAndWrench: return .objects
case .daggerKnife: return .objects
case .crossedSwords: return .objects
case .gun: return .objects
case .bomb: return .objects
case .boomerang: return .objects
case .bowAndArrow: return .objects
case .shield: return .objects
@ -3269,6 +3310,8 @@ extension Emoji {
case .coffin: return .objects
case .headstone: return .objects
case .funeralUrn: return .objects
case .nazarAmulet: return .objects
case .hamsa: return .objects
case .moyai: return .objects
case .placard: return .objects
case .identificationCard: return .objects
@ -3331,6 +3374,7 @@ extension Emoji {
case .peaceSymbol: return .symbols
case .menorahWithNineBranches: return .symbols
case .sixPointedStar: return .symbols
case .khanda: return .symbols
case .aries: return .symbols
case .taurus: return .symbols
case .gemini: return .symbols
@ -3366,6 +3410,7 @@ extension Emoji {
case .lowBrightness: return .symbols
case .highBrightness: return .symbols
case .signalStrength: return .symbols
case .wireless: return .symbols
case .vibrationMode: return .symbols
case .mobilePhoneOff: return .symbols
case .femaleSign: return .symbols
@ -3774,3 +3819,4 @@ extension Emoji {
}
}
}
// swiftlint:disable all

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
// This file is generated by EmojiGenerator.swift, do not manually edit it.
// swiftlint:disable all
// stringlint:disable
extension Emoji {
enum SkinTone: String, CaseIterable, Equatable {
case light = "🏻"
@ -106,6 +109,22 @@ extension Emoji {
[.mediumDark]: "🫴🏾",
[.dark]: "🫴🏿",
]
case .leftwardsPushingHand:
return [
[.light]: "🫷🏻",
[.mediumLight]: "🫷🏼",
[.medium]: "🫷🏽",
[.mediumDark]: "🫷🏾",
[.dark]: "🫷🏿",
]
case .rightwardsPushingHand:
return [
[.light]: "🫸🏻",
[.mediumLight]: "🫸🏼",
[.medium]: "🫸🏽",
[.mediumDark]: "🫸🏾",
[.dark]: "🫸🏿",
]
case .okHand:
return [
[.light]: "👌🏻",
@ -2722,3 +2741,4 @@ extension Emoji {
}
}
}
// swiftlint:disable all

View File

@ -2,6 +2,7 @@
// This file is generated by EmojiGenerator.swift, do not manually edit it.
// swiftlint:disable all
// stringlint:disable
/// A sorted representation of all available emoji
enum Emoji: String, CaseIterable, Equatable {
@ -54,6 +55,7 @@ enum Emoji: String, CaseIterable, Equatable {
case grimacing = "😬"
case faceExhaling = "😮‍💨"
case lyingFace = "🤥"
case shakingFace = "🫨"
case relieved = "😌"
case pensive = "😔"
case sleepy = "😪"
@ -131,7 +133,6 @@ enum Emoji: String, CaseIterable, Equatable {
case seeNoEvil = "🙈"
case hearNoEvil = "🙉"
case speakNoEvil = "🙊"
case kiss = "💋"
case loveLetter = "💌"
case cupid = "💘"
case giftHeart = "💝"
@ -146,14 +147,18 @@ enum Emoji: String, CaseIterable, Equatable {
case heartOnFire = "❤️‍🔥"
case mendingHeart = "❤️‍🩹"
case heart = "❤️"
case pinkHeart = "🩷"
case orangeHeart = "🧡"
case yellowHeart = "💛"
case greenHeart = "💚"
case blueHeart = "💙"
case lightBlueHeart = "🩵"
case purpleHeart = "💜"
case brownHeart = "🤎"
case blackHeart = "🖤"
case greyHeart = "🩶"
case whiteHeart = "🤍"
case kiss = "💋"
case oneHundred = "💯"
case anger = "💢"
case boom = "💥"
@ -161,7 +166,6 @@ enum Emoji: String, CaseIterable, Equatable {
case sweatDrops = "💦"
case dash = "💨"
case hole = "🕳️"
case bomb = "💣"
case speechBalloon = "💬"
case eyeInSpeechBubble = "👁️‍🗨️"
case leftSpeechBubble = "🗨️"
@ -177,6 +181,8 @@ enum Emoji: String, CaseIterable, Equatable {
case leftwardsHand = "🫲"
case palmDownHand = "🫳"
case palmUpHand = "🫴"
case leftwardsPushingHand = "🫷"
case rightwardsPushingHand = "🫸"
case okHand = "👌"
case pinchedFingers = "🤌"
case pinchingHand = "🤏"
@ -554,6 +560,8 @@ enum Emoji: String, CaseIterable, Equatable {
case tiger2 = "🐅"
case leopard = "🐆"
case horse = "🐴"
case moose = "🫎"
case donkey = "🫏"
case racehorse = "🐎"
case unicornFace = "🦄"
case zebraFace = "🦓"
@ -616,6 +624,9 @@ enum Emoji: String, CaseIterable, Equatable {
case flamingo = "🦩"
case peacock = "🦚"
case parrot = "🦜"
case wing = "🪽"
case blackBird = "🐦‍⬛"
case goose = "🪿"
case frog = "🐸"
case crocodile = "🐊"
case turtle = "🐢"
@ -636,6 +647,7 @@ enum Emoji: String, CaseIterable, Equatable {
case octopus = "🐙"
case shell = "🐚"
case coral = "🪸"
case jellyfish = "🪼"
case snail = "🐌"
case butterfly = "🦋"
case bug = "🐛"
@ -663,6 +675,7 @@ enum Emoji: String, CaseIterable, Equatable {
case sunflower = "🌻"
case blossom = "🌼"
case tulip = "🌷"
case hyacinth = "🪻"
case seedling = "🌱"
case pottedPlant = "🪴"
case evergreenTree = "🌲"
@ -678,6 +691,7 @@ enum Emoji: String, CaseIterable, Equatable {
case leaves = "🍃"
case emptyNest = "🪹"
case nestWithEggs = "🪺"
case mushroom = "🍄"
case grapes = "🍇"
case melon = "🍈"
case watermelon = "🍉"
@ -709,10 +723,11 @@ enum Emoji: String, CaseIterable, Equatable {
case broccoli = "🥦"
case garlic = "🧄"
case onion = "🧅"
case mushroom = "🍄"
case peanuts = "🥜"
case beans = "🫘"
case chestnut = "🌰"
case gingerRoot = "🫚"
case peaPod = "🫛"
case bread = "🍞"
case croissant = "🥐"
case baguetteBread = "🥖"
@ -1085,11 +1100,10 @@ enum Emoji: String, CaseIterable, Equatable {
case dart = "🎯"
case yoYo = "🪀"
case kite = "🪁"
case gun = "🔫"
case eightBall = "🎱"
case crystalBall = "🔮"
case magicWand = "🪄"
case nazarAmulet = "🧿"
case hamsa = "🪬"
case videoGame = "🎮"
case joystick = "🕹️"
case slotMachine = "🎰"
@ -1134,6 +1148,7 @@ enum Emoji: String, CaseIterable, Equatable {
case shorts = "🩳"
case bikini = "👙"
case womansClothes = "👚"
case foldingHandFan = "🪭"
case purse = "👛"
case handbag = "👜"
case pouch = "👝"
@ -1148,6 +1163,7 @@ enum Emoji: String, CaseIterable, Equatable {
case sandal = "👡"
case balletShoes = "🩰"
case boot = "👢"
case hairPick = "🪮"
case crown = "👑"
case womansHat = "👒"
case tophat = "🎩"
@ -1186,6 +1202,8 @@ enum Emoji: String, CaseIterable, Equatable {
case banjo = "🪕"
case drumWithDrumsticks = "🥁"
case longDrum = "🪘"
case maracas = "🪇"
case flute = "🪈"
case iphone = "📱"
case calling = "📲"
case phone = "☎️"
@ -1305,7 +1323,7 @@ enum Emoji: String, CaseIterable, Equatable {
case hammerAndWrench = "🛠️"
case daggerKnife = "🗡️"
case crossedSwords = "⚔️"
case gun = "🔫"
case bomb = "💣"
case boomerang = "🪃"
case bowAndArrow = "🏹"
case shield = "🛡️"
@ -1366,6 +1384,8 @@ enum Emoji: String, CaseIterable, Equatable {
case coffin = "⚰️"
case headstone = "🪦"
case funeralUrn = "⚱️"
case nazarAmulet = "🧿"
case hamsa = "🪬"
case moyai = "🗿"
case placard = "🪧"
case identificationCard = "🪪"
@ -1428,6 +1448,7 @@ enum Emoji: String, CaseIterable, Equatable {
case peaceSymbol = "☮️"
case menorahWithNineBranches = "🕎"
case sixPointedStar = "🔯"
case khanda = "🪯"
case aries = ""
case taurus = ""
case gemini = ""
@ -1463,6 +1484,7 @@ enum Emoji: String, CaseIterable, Equatable {
case lowBrightness = "🔅"
case highBrightness = "🔆"
case signalStrength = "📶"
case wireless = "🛜"
case vibrationMode = "📳"
case mobilePhoneOff = "📴"
case femaleSign = "♀️"

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,7 @@ extension Emoji {
guard withDefaultEmoji else { return recentReactionEmoji }
// Add in our default emoji if desired
let defaultEmoji = ["😂", "🥰", "😢", "😡", "😮", "😈"]
let defaultEmoji = ["😂", "🥰", "😢", "😡", "😮", "😈"] // stringlint:disable
.filter { !recentReactionEmoji.contains($0) }
return Array(recentReactionEmoji

View File

@ -203,6 +203,11 @@ class GlobalSearchViewController: BaseVC, SessionUtilRespondingViewController, U
])
}
catch {
// Don't log the 'interrupt' error as that's just the user typing too fast
if (error as? DatabaseError)?.resultCode != DatabaseError.SQLITE_INTERRUPT {
SNLog("[GlobalSearch] Failed to find results due to error: \(error)")
}
return .failure(error)
}
}

View File

@ -283,14 +283,6 @@ final class HomeVC: BaseVC, SessionUtilRespondingViewController, UITableViewData
// Start polling if needed (i.e. if the user just created or restored their Session ID)
if Identity.userExists(), let appDelegate: AppDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.startPollersIfNeeded()
// FIXME: Remove this once `useSharedUtilForUserConfig` is permanent
if !SessionUtil.userConfigsEnabled {
// Do this only if we created a new Session ID, or if we already received the initial configuration message
if UserDefaults.standard[.hasSyncedInitialConfiguration] {
appDelegate.syncConfigurationIfNeeded()
}
}
}
// Onion request path countries cache
@ -625,7 +617,9 @@ final class HomeVC: BaseVC, SessionUtilRespondingViewController, UITableViewData
switch section.model {
case .messageRequests:
let viewController: MessageRequestsViewController = MessageRequestsViewController()
let viewController: SessionTableViewController = SessionTableViewController(
viewModel: MessageRequestsViewModel()
)
self.navigationController?.pushViewController(viewController, animated: true)
case .threads:
@ -784,7 +778,7 @@ final class HomeVC: BaseVC, SessionUtilRespondingViewController, UITableViewData
let finalViewControllers: [UIViewController] = [
self,
(isMessageRequest ? MessageRequestsViewController() : nil),
(isMessageRequest ? SessionTableViewController(viewModel: MessageRequestsViewModel()) : nil),
ConversationVC(
threadId: threadId,
threadVariant: variant,

View File

@ -1,485 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import GRDB
import DifferenceKit
import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
class MessageRequestsViewController: BaseVC, SessionUtilRespondingViewController, UITableViewDelegate, UITableViewDataSource {
private static let loadingHeaderHeight: CGFloat = 40
private let viewModel: MessageRequestsViewModel = MessageRequestsViewModel()
private var hasLoadedInitialThreadData: Bool = false
private var isLoadingMore: Bool = false
private var isAutoLoadingNextPage: Bool = false
private var viewHasAppeared: Bool = false
// MARK: - SessionUtilRespondingViewController
let isConversationList: Bool = true
// MARK: - Intialization
init() {
Storage.shared.addObserver(viewModel.pagedDataObserver)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
preconditionFailure("Use init() instead.")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - UI
private lazy var loadingConversationsLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.smallFontSize)
result.text = "LOADING_CONVERSATIONS".localized()
result.themeTextColor = .textSecondary
result.textAlignment = .center
result.numberOfLines = 0
return result
}()
private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.translatesAutoresizingMaskIntoConstraints = false
result.separatorStyle = .none
result.themeBackgroundColor = .clear
result.showsVerticalScrollIndicator = false
result.contentInset = UIEdgeInsets(
top: 0,
left: 0,
bottom: Values.footerGradientHeight(window: UIApplication.shared.keyWindow),
right: 0
)
result.register(view: FullConversationCell.self)
result.dataSource = self
result.delegate = self
if #available(iOS 15.0, *) {
result.sectionHeaderTopPadding = 0
}
return result
}()
private lazy var emptyStateLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.isUserInteractionEnabled = false
result.font = .systemFont(ofSize: Values.smallFontSize)
result.text = "MESSAGE_REQUESTS_EMPTY_TEXT".localized()
result.themeTextColor = .textSecondary
result.textAlignment = .center
result.numberOfLines = 0
result.isHidden = true
return result
}()
private lazy var fadeView: GradientView = {
let result: GradientView = GradientView()
result.themeBackgroundGradient = [
.value(.backgroundPrimary, alpha: 0), // Want this to take up 20% (~25pt)
.backgroundPrimary,
.backgroundPrimary,
.backgroundPrimary,
.backgroundPrimary
]
result.set(.height, to: Values.footerGradientHeight(window: UIApplication.shared.keyWindow))
return result
}()
private lazy var clearAllButton: SessionButton = {
let result: SessionButton = SessionButton(style: .destructive, size: .large)
result.translatesAutoresizingMaskIntoConstraints = false
result.setTitle("MESSAGE_REQUESTS_CLEAR_ALL".localized(), for: .normal)
result.addTarget(self, action: #selector(clearAllTapped), for: .touchUpInside)
result.accessibilityIdentifier = "Clear all"
return result
}()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
ViewControllerUtilities.setUpDefaultSessionStyle(
for: self,
title: "MESSAGE_REQUESTS_TITLE".localized(),
hasCustomBackButton: false
)
// Add the UI (MUST be done after the thread freeze so the 'tableView' creation and setting
// the dataSource has the correct data)
view.addSubview(loadingConversationsLabel)
view.addSubview(tableView)
view.addSubview(emptyStateLabel)
view.addSubview(fadeView)
view.addSubview(clearAllButton)
setupLayout()
// Notifications
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive(_:)),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidResignActive(_:)),
name: UIApplication.didEnterBackgroundNotification, object: nil
)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startObservingChanges()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.viewHasAppeared = true
self.autoLoadNextPageIfNeeded()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopObservingChanges()
}
@objc func applicationDidBecomeActive(_ notification: Notification) {
/// Need to dispatch to the next run loop to prevent a possible crash caused by the database resuming mid-query
DispatchQueue.main.async { [weak self] in
self?.startObservingChanges(didReturnFromBackground: true)
}
}
@objc func applicationDidResignActive(_ notification: Notification) {
stopObservingChanges()
}
// MARK: - Layout
private func setupLayout() {
NSLayoutConstraint.activate([
loadingConversationsLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: Values.veryLargeSpacing),
loadingConversationsLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: Values.massiveSpacing),
loadingConversationsLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -Values.massiveSpacing),
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: Values.smallSpacing),
tableView.leftAnchor.constraint(equalTo: view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: view.rightAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
emptyStateLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: Values.massiveSpacing),
emptyStateLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: Values.mediumSpacing),
emptyStateLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -Values.mediumSpacing),
emptyStateLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
fadeView.leftAnchor.constraint(equalTo: view.leftAnchor),
fadeView.rightAnchor.constraint(equalTo: view.rightAnchor),
fadeView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
clearAllButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
clearAllButton.bottomAnchor.constraint(
equalTo: view.safeAreaLayoutGuide.bottomAnchor,
constant: -Values.smallSpacing
),
clearAllButton.widthAnchor.constraint(equalToConstant: Values.iPadButtonWidth)
])
}
// MARK: - Updating
private func startObservingChanges(didReturnFromBackground: Bool = false) {
self.viewModel.onThreadChange = { [weak self] updatedThreadData, changeset in
self?.handleThreadUpdates(updatedThreadData, changeset: changeset)
}
// Note: When returning from the background we could have received notifications but the
// PagedDatabaseObserver won't have them so we need to force a re-fetch of the current
// data to ensure everything is up to date
if didReturnFromBackground {
self.viewModel.pagedDataObserver?.reload()
}
}
private func stopObservingChanges() {
self.viewModel.onThreadChange = nil
}
private func handleThreadUpdates(
_ updatedData: [MessageRequestsViewModel.SectionModel],
changeset: StagedChangeset<[MessageRequestsViewModel.SectionModel]>,
initialLoad: Bool = false
) {
// Ensure the first load runs without animations (if we don't do this the cells will animate
// in from a frame of CGRect.zero)
guard hasLoadedInitialThreadData else {
UIView.performWithoutAnimation {
// Hide the 'loading conversations' label (now that we have received conversation data)
loadingConversationsLabel.isHidden = true
// Show the empty state if there is no data
clearAllButton.isHidden = !(updatedData.first?.elements.isEmpty == false)
emptyStateLabel.isHidden = !clearAllButton.isHidden
// Update the content
viewModel.updateThreadData(updatedData)
tableView.reloadData()
hasLoadedInitialThreadData = true
}
return
}
// Hide the 'loading conversations' label (now that we have received conversation data)
loadingConversationsLabel.isHidden = true
// Show the empty state if there is no data
clearAllButton.isHidden = !(updatedData.first?.elements.isEmpty == false)
emptyStateLabel.isHidden = !clearAllButton.isHidden
CATransaction.begin()
CATransaction.setCompletionBlock { [weak self] in
// Complete page loading
self?.isLoadingMore = false
self?.autoLoadNextPageIfNeeded()
}
// Reload the table content (animate changes after the first load)
tableView.reload(
using: changeset,
deleteSectionsAnimation: .none,
insertSectionsAnimation: .none,
reloadSectionsAnimation: .none,
deleteRowsAnimation: .bottom,
insertRowsAnimation: .top,
reloadRowsAnimation: .none,
interrupt: { $0.changeCount > 100 } // Prevent too many changes from causing performance issues
) { [weak self] updatedData in
self?.viewModel.updateThreadData(updatedData)
}
CATransaction.commit()
}
private func autoLoadNextPageIfNeeded() {
guard
self.hasLoadedInitialThreadData &&
!self.isAutoLoadingNextPage &&
!self.isLoadingMore
else { return }
self.isAutoLoadingNextPage = true
DispatchQueue.main.asyncAfter(deadline: .now() + PagedData.autoLoadNextPageDelay) { [weak self] in
self?.isAutoLoadingNextPage = false
// Note: We sort the headers as we want to prioritise loading newer pages over older ones
let sections: [(MessageRequestsViewModel.Section, CGRect)] = (self?.viewModel.threadData
.enumerated()
.map { index, section in (section.model, (self?.tableView.rectForHeader(inSection: index) ?? .zero)) })
.defaulting(to: [])
let shouldLoadMore: Bool = sections
.contains { section, headerRect in
section == .loadMore &&
headerRect != .zero &&
(self?.tableView.bounds.contains(headerRect) == true)
}
guard shouldLoadMore else { return }
self?.isLoadingMore = true
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
self?.viewModel.pagedDataObserver?.load(.pageAfter)
}
}
}
// MARK: - UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.threadData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section: MessageRequestsViewModel.SectionModel = viewModel.threadData[section]
return section.elements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section: MessageRequestsViewModel.SectionModel = viewModel.threadData[indexPath.section]
switch section.model {
case .threads:
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
let cell: FullConversationCell = tableView.dequeue(type: FullConversationCell.self, for: indexPath)
cell.accessibilityIdentifier = "Message request"
cell.isAccessibilityElement = true
cell.update(with: threadViewModel)
return cell
default: preconditionFailure("Other sections should have no content")
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let section: MessageRequestsViewModel.SectionModel = viewModel.threadData[section]
switch section.model {
case .loadMore:
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(style: .medium)
loadingIndicator.themeTintColor = .textPrimary
loadingIndicator.alpha = 0.5
loadingIndicator.startAnimating()
let view: UIView = UIView()
view.addSubview(loadingIndicator)
loadingIndicator.center(in: view)
return view
default: return nil
}
}
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
let section: MessageRequestsViewModel.SectionModel = viewModel.threadData[section]
switch section.model {
case .loadMore: return MessageRequestsViewController.loadingHeaderHeight
default: return 0
}
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
guard self.hasLoadedInitialThreadData && self.viewHasAppeared && !self.isLoadingMore else { return }
let section: MessageRequestsViewModel.SectionModel = self.viewModel.threadData[section]
switch section.model {
case .loadMore:
self.isLoadingMore = true
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
self?.viewModel.pagedDataObserver?.load(.pageAfter)
}
default: break
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let section: MessageRequestsViewModel.SectionModel = self.viewModel.threadData[indexPath.section]
switch section.model {
case .threads:
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
let conversationVC: ConversationVC = ConversationVC(
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant
)
self.navigationController?.pushViewController(conversationVC, animated: true)
default: break
}
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
UIContextualAction.willBeginEditing(indexPath: indexPath, tableView: tableView)
}
func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
UIContextualAction.didEndEditing(indexPath: indexPath, tableView: tableView)
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let section: MessageRequestsViewModel.SectionModel = self.viewModel.threadData[indexPath.section]
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row]
switch section.model {
case .threads:
return UIContextualAction.configuration(
for: UIContextualAction.generateSwipeActions(
[
(threadViewModel.threadVariant != .contact ? nil : .block),
.delete
].compactMap { $0 },
for: .trailing,
indexPath: indexPath,
tableView: tableView,
threadViewModel: threadViewModel,
viewController: self
)
)
default: return nil
}
}
// MARK: - Interaction
@objc private func clearAllTapped() {
guard viewModel.threadData.first(where: { $0.model == .threads })?.elements.isEmpty == false else {
return
}
let contactThreadIds: [String] = (viewModel.threadData
.first { $0.model == .threads }?
.elements
.filter { $0.threadVariant == .contact }
.map { $0.threadId })
.defaulting(to: [])
let groupThreadIds: [String] = (viewModel.threadData
.first { $0.model == .threads }?
.elements
.filter { $0.threadVariant == .legacyGroup || $0.threadVariant == .group }
.map { $0.threadId })
.defaulting(to: [])
let alertVC: UIAlertController = UIAlertController(
title: "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE".localized(),
message: nil,
preferredStyle: .actionSheet
)
alertVC.addAction(UIAlertAction(
title: "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON".localized(),
style: .destructive
) { _ in
MessageRequestsViewModel.clearAllRequests(
contactThreadIds: contactThreadIds,
groupThreadIds: groupThreadIds
)
})
alertVC.addAction(UIAlertAction(title: "TXT_CANCEL_TITLE".localized(), style: .cancel, handler: nil))
Modal.setupForIPadIfNeeded(alertVC, targetView: self.view)
self.present(alertVC, animated: true, completion: nil)
}
}

View File

@ -1,34 +1,37 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import GRDB
import DifferenceKit
import SessionUIKit
import SessionUtilitiesKit
import SignalUtilitiesKit
public class MessageRequestsViewModel {
public typealias SectionModel = ArraySection<Section, SessionThreadViewModel>
// MARK: - Section
public enum Section: Differentiable {
case threads
case loadMore
}
class MessageRequestsViewModel: SessionTableViewModel, NavigatableStateHolder, ObservableTableSource, PagedObservationSource {
typealias TableItem = SessionThreadViewModel
typealias PagedTable = SessionThread
typealias PagedDataModel = SessionThreadViewModel
// MARK: - Variables
public static let pageSize: Int = (UIDevice.current.isIPad ? 20 : 15)
public let dependencies: Dependencies
public let state: TableDataState<Section, TableItem> = TableDataState()
public let observableState: ObservableTableSourceState<Section, SessionThreadViewModel> = ObservableTableSourceState()
public let navigatableState: NavigatableState = NavigatableState()
// MARK: - Initialization
init() {
init(using dependencies: Dependencies = Dependencies()) {
self.dependencies = dependencies
self.pagedDataObserver = nil
// Note: Since this references self we need to finish initializing before setting it, we
// also want to skip the initial query and trigger it async so that the push animation
// doesn't stutter (it should load basically immediately but without this there is a
// distinct stutter)
let userPublicKey: String = getUserHexEncodedPublicKey()
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
let thread: TypedTableAlias<SessionThread> = TypedTableAlias()
self.pagedDataObserver = PagedDatabaseObserver(
pagedTable: SessionThread.self,
@ -100,14 +103,8 @@ public class MessageRequestsViewModel {
onChangeUnsorted: { [weak self] updatedData, updatedPageInfo in
PagedData.processAndTriggerUpdates(
updatedData: self?.process(data: updatedData, for: updatedPageInfo),
currentDataRetriever: { self?.threadData },
onDataChange: self?.onThreadChange,
onUnobservedDataChange: { updatedData, changeset in
self?.unobservedThreadDataChanges = (changeset.isEmpty ?
nil :
(updatedData, changeset)
)
}
currentDataRetriever: { self?.tableData },
valueSubject: self?.pendingTableDataSubject
)
}
)
@ -119,35 +116,35 @@ public class MessageRequestsViewModel {
}
}
// MARK: - Thread Data
// MARK: - Section
public private(set) var unobservedThreadDataChanges: ([SectionModel], StagedChangeset<[SectionModel]>)?
public private(set) var threadData: [SectionModel] = []
public private(set) var pagedDataObserver: PagedDatabaseObserver<SessionThread, SessionThreadViewModel>?
public var onThreadChange: (([SectionModel], StagedChangeset<[SectionModel]>) -> ())? {
didSet {
// When starting to observe interaction changes we want to trigger a UI update just in case the
// data was changed while we weren't observing
if let changes: ([SectionModel], StagedChangeset<[SectionModel]>) = self.unobservedThreadDataChanges {
let performChange: (([SectionModel], StagedChangeset<[SectionModel]>) -> ())? = onThreadChange
switch Thread.isMainThread {
case true: performChange?(changes.0, changes.1)
case false: DispatchQueue.main.async { performChange?(changes.0, changes.1) }
}
self.unobservedThreadDataChanges = nil
public enum Section: SessionTableSection {
case threads
case loadMore
var style: SessionTableSectionStyle {
switch self {
case .threads: return .none
case .loadMore: return .loadMore
}
}
}
// MARK: - Content
public let title: String = "MESSAGE_REQUESTS_TITLE".localized()
public let initialLoadMessage: String? = "LOADING_CONVERSATIONS".localized()
public let emptyStateTextPublisher: AnyPublisher<String?, Never> = Just("MESSAGE_REQUESTS_EMPTY_TEXT".localized())
.eraseToAnyPublisher()
public let cellType: SessionTableViewCellType = .fullConversation
public private(set) var pagedDataObserver: PagedDatabaseObserver<SessionThread, SessionThreadViewModel>?
private func process(data: [SessionThreadViewModel], for pageInfo: PagedData.PageInfo) -> [SectionModel] {
let groupedOldData: [String: [SessionThreadViewModel]] = (self.threadData
let groupedOldData: [String: [SessionCell.Info<SessionThreadViewModel>]] = (self.tableData
.first(where: { $0.model == .threads })?
.elements)
.defaulting(to: [])
.grouped(by: \.threadId)
.grouped(by: \.id.threadId)
return [
[
@ -155,14 +152,28 @@ public class MessageRequestsViewModel {
section: .threads,
elements: data
.sorted { lhs, rhs -> Bool in lhs.lastInteractionDate > rhs.lastInteractionDate }
.map { viewModel -> SessionThreadViewModel in
viewModel.populatingCurrentUserBlindedKeys(
currentUserBlinded15PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
.first?
.currentUserBlinded15PublicKey,
currentUserBlinded25PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
.first?
.currentUserBlinded25PublicKey
.map { viewModel -> SessionCell.Info<SessionThreadViewModel> in
SessionCell.Info(
id: viewModel.populatingCurrentUserBlindedKeys(
currentUserBlinded15PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
.first?
.id
.currentUserBlinded15PublicKey,
currentUserBlinded25PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
.first?
.id
.currentUserBlinded25PublicKey
),
accessibility: Accessibility(
identifier: "Message request"
),
onTap: { [weak self] in
let viewController: ConversationVC = ConversationVC(
threadId: viewModel.threadId,
threadVariant: viewModel.threadVariant
)
self?.transitionToScreen(viewController, transitionType: .push)
}
)
}
)
@ -174,35 +185,100 @@ public class MessageRequestsViewModel {
].flatMap { $0 }
}
public func updateThreadData(_ updatedData: [SectionModel]) {
self.threadData = updatedData
}
lazy var footerButtonInfo: AnyPublisher<SessionButton.Info?, Never> = observableState
.pendingTableDataSubject
.map { [dependencies] (currentThreadData: [SectionModel], _: StagedChangeset<[SectionModel]>) in
let threadInfo: [(id: String, variant: SessionThread.Variant)] = (currentThreadData
.first(where: { $0.model == .threads })?
.elements
.map { ($0.id.id, $0.id.threadVariant) })
.defaulting(to: [])
return SessionButton.Info(
style: .destructive,
title: "MESSAGE_REQUESTS_CLEAR_ALL".localized(),
isEnabled: !threadInfo.isEmpty,
accessibility: Accessibility(
identifier: "Clear all"
),
onTap: { [weak self] in
let modal: ConfirmationModal = ConfirmationModal(
info: ConfirmationModal.Info(
title: "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE".localized(),
accessibility: Accessibility(
identifier: "Clear all"
),
confirmTitle: "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON".localized(),
confirmAccessibility: Accessibility(
identifier: "Clear"
),
confirmStyle: .danger,
cancelStyle: .alert_text,
onConfirm: { _ in
// Clear the requests
dependencies.storage.write { db in
// Remove the one-to-one requests
try SessionThread.deleteOrLeave(
db,
threadIds: threadInfo
.filter { _, variant in variant == .contact }
.map { id, _ in id },
threadVariant: .contact,
groupLeaveType: .silent,
calledFromConfigHandling: false
)
// Remove the group requests
try SessionThread.deleteOrLeave(
db,
threadIds: threadInfo
.filter { _, variant in variant == .legacyGroup || variant == .group }
.map { id, _ in id },
threadVariant: .group,
groupLeaveType: .silent,
calledFromConfigHandling: false
)
}
}
)
)
self?.transitionToScreen(modal, transitionType: .present)
}
)
}
.eraseToAnyPublisher()
// MARK: - Functions
static func clearAllRequests(
contactThreadIds: [String],
groupThreadIds: [String]
) {
// Clear the requests
Storage.shared.write { db in
// Remove the one-to-one requests
try SessionThread.deleteOrLeave(
db,
threadIds: contactThreadIds,
threadVariant: .contact,
groupLeaveType: .silent,
calledFromConfigHandling: false
)
// Remove the group requests
try SessionThread.deleteOrLeave(
db,
threadIds: groupThreadIds,
threadVariant: .group,
groupLeaveType: .silent,
calledFromConfigHandling: false
)
func canEditRow(at indexPath: IndexPath) -> Bool {
let section: SectionModel = tableData[indexPath.section]
return (section.model == .threads)
}
func trailingSwipeActionsConfiguration(forRowAt indexPath: IndexPath, in tableView: UITableView, of viewController: UIViewController) -> UISwipeActionsConfiguration? {
let section: SectionModel = tableData[indexPath.section]
switch section.model {
case .threads:
let threadViewModel: SessionThreadViewModel = section.elements[indexPath.row].id
return UIContextualAction.configuration(
for: UIContextualAction.generateSwipeActions(
[
(threadViewModel.threadVariant != .contact ? nil : .block),
.delete
].compactMap { $0 },
for: .trailing,
indexPath: indexPath,
tableView: tableView,
threadViewModel: threadViewModel,
viewController: viewController
)
)
default: return nil
}
}
}

View File

@ -7,6 +7,7 @@ import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SignalUtilitiesKit
import SessionSnodeKit
final class NewDMVC: BaseVC, UIPageViewControllerDataSource, UIPageViewControllerDelegate, QRScannerDelegate {
private var shouldShowBackButton: Bool = true
@ -694,7 +695,7 @@ private final class ScanQRCodePlaceholderVC: UIViewController {
// Set up call to action button
let callToActionButton = UIButton()
callToActionButton.titleLabel?.font = .boldSystemFont(ofSize: Values.mediumFontSize)
callToActionButton.setTitle("vc_scan_qr_code_grant_camera_access_button_title".localized(), for: UIControl.State.normal)
callToActionButton.setTitle("continue_2".localized(), for: .normal)
callToActionButton.setThemeTitleColor(.primary, for: .normal)
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)

View File

@ -5,6 +5,7 @@ import MediaPlayer
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
// This kind of view is tricky. I've tried to organize things in the
// simplest possible way.
@ -359,54 +360,54 @@ import SignalCoreKit
@objc func handlePinch(sender: UIPinchGestureRecognizer) {
switch sender.state {
case .possible:
break
case .began:
srcTranslationAtPinchStart = srcTranslation
imageScaleAtPinchStart = imageScale
case .possible: break
case .began:
srcTranslationAtPinchStart = srcTranslation
imageScaleAtPinchStart = imageScale
lastPinchLocation =
sender.location(in: sender.view)
lastPinchScale = sender.scale
break
case .changed, .ended:
if sender.numberOfTouches > 1 {
let location =
lastPinchLocation =
sender.location(in: sender.view)
let scaleDiff = sender.scale / lastPinchScale
// Update scaling.
let srcCropSizeBeforeScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
imageScale = max(kMinImageScale, min(kMaxImageScale, imageScale * scaleDiff))
let srcCropSizeAfterScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
// Since the translation state reflects the "upper left" corner of the crop region, we need to
// adjust the translation when scaling to preserve the "center" of the crop region.
srcTranslation.x += (srcCropSizeBeforeScalePoints.width - srcCropSizeAfterScalePoints.width) * 0.5
srcTranslation.y += (srcCropSizeBeforeScalePoints.height - srcCropSizeAfterScalePoints.height) * 0.5
// Update translation.
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
let gestureTranslation = CGPoint(x: location.x - lastPinchLocation.x,
y: location.y - lastPinchLocation.y)
srcTranslation = CGPoint(x: srcTranslation.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslation.y + gestureTranslation.y * -viewToSrcRatio)
lastPinchLocation = location
lastPinchScale = sender.scale
}
break
case .cancelled, .failed:
srcTranslation = srcTranslationAtPinchStart
imageScale = imageScaleAtPinchStart
break
case .changed, .ended:
if sender.numberOfTouches > 1 {
let location =
sender.location(in: sender.view)
let scaleDiff = sender.scale / lastPinchScale
// Update scaling.
let srcCropSizeBeforeScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
imageScale = max(kMinImageScale, min(kMaxImageScale, imageScale * scaleDiff))
let srcCropSizeAfterScalePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
// Since the translation state reflects the "upper left" corner of the crop region, we need to
// adjust the translation when scaling to preserve the "center" of the crop region.
srcTranslation.x += (srcCropSizeBeforeScalePoints.width - srcCropSizeAfterScalePoints.width) * 0.5
srcTranslation.y += (srcCropSizeBeforeScalePoints.height - srcCropSizeAfterScalePoints.height) * 0.5
// Update translation.
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
let gestureTranslation = CGPoint(x: location.x - lastPinchLocation.x,
y: location.y - lastPinchLocation.y)
srcTranslation = CGPoint(x: srcTranslation.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslation.y + gestureTranslation.y * -viewToSrcRatio)
lastPinchLocation = location
lastPinchScale = sender.scale
}
case .cancelled, .failed:
srcTranslation = srcTranslationAtPinchStart
imageScale = imageScaleAtPinchStart
@unknown default: break
}
updateImageLayout()
@ -416,29 +417,28 @@ import SignalCoreKit
@objc func handlePan(sender: UIPanGestureRecognizer) {
switch sender.state {
case .possible:
break
case .began:
srcTranslationAtPanStart = srcTranslation
break
case .changed, .ended:
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
case .possible: break
case .began:
srcTranslationAtPanStart = srcTranslation
case .changed, .ended:
let viewSizePoints = imageView.frame.size
let srcCropSizePoints = CGSize(width: srcDefaultCropSizePoints.width / imageScale,
height: srcDefaultCropSizePoints.height / imageScale)
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
let viewToSrcRatio = srcCropSizePoints.width / viewSizePoints.width
let gestureTranslation =
sender.translation(in: sender.view)
let gestureTranslation =
sender.translation(in: sender.view)
// Update translation.
srcTranslation = CGPoint(x: srcTranslationAtPanStart.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslationAtPanStart.y + gestureTranslation.y * -viewToSrcRatio)
break
case .cancelled, .failed:
srcTranslation
= srcTranslationAtPanStart
break
// Update translation.
srcTranslation = CGPoint(x: srcTranslationAtPanStart.x + gestureTranslation.x * -viewToSrcRatio,
y: srcTranslationAtPanStart.y + gestureTranslation.y * -viewToSrcRatio)
case .cancelled, .failed:
srcTranslation = srcTranslationAtPanStart
@unknown default: break
}
updateImageLayout()

View File

@ -7,6 +7,7 @@ import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
public class DocumentTileViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@ -46,6 +47,10 @@ public class DocumentTileViewController: UIViewController, UITableViewDelegate,
// MARK: - UI
override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.isIPad {
return .all
}
return .allButUpsideDown
}
@ -371,10 +376,17 @@ class DocumentCell: UITableViewCell {
// MARK: - UI
private static let iconImageViewSize: CGSize = CGSize(width: 31, height: 40)
private let iconImageView: UIImageView = {
let result: UIImageView = UIImageView(image: #imageLiteral(resourceName: "File").withRenderingMode(.alwaysTemplate))
let result: UIImageView = UIImageView(image: UIImage(systemName: "doc")?.withRenderingMode(.alwaysTemplate))
result.translatesAutoresizingMaskIntoConstraints = false
result.themeTintColor = .textPrimary
result.contentMode = .scaleAspectFit
return result
}()
private let audioImageView: UIImageView = {
let result = UIImageView(image: UIImage(systemName: "music.note")?.withRenderingMode(.alwaysTemplate))
result.translatesAutoresizingMaskIntoConstraints = false
result.themeTintColor = .textPrimary
result.contentMode = .scaleAspectFit
@ -434,6 +446,8 @@ class DocumentCell: UITableViewCell {
contentView.addSubview(titleLabel)
contentView.addSubview(timeLabel)
contentView.addSubview(detailLabel)
iconImageView.addSubview(audioImageView)
}
// MARK: - Layout
@ -453,6 +467,8 @@ class DocumentCell: UITableViewCell {
lessThanOrEqualTo: contentView.bottomAnchor,
constant: -(Values.verySmallSpacing + Values.verySmallSpacing)
),
iconImageView.widthAnchor.constraint(equalToConstant: 36),
iconImageView.heightAnchor.constraint(equalToConstant: 46),
titleLabel.topAnchor.constraint(
equalTo: contentView.topAnchor,
@ -480,6 +496,10 @@ class DocumentCell: UITableViewCell {
lessThanOrEqualTo: contentView.bottomAnchor,
constant: -(Values.verySmallSpacing + Values.smallSpacing)
),
audioImageView.centerXAnchor.constraint(equalTo: iconImageView.centerXAnchor),
audioImageView.centerYAnchor.constraint(equalTo: iconImageView.centerYAnchor, constant: 7),
audioImageView.heightAnchor.constraint(equalTo: iconImageView.heightAnchor, multiplier: 0.32)
])
}
@ -499,11 +519,12 @@ class DocumentCell: UITableViewCell {
func update(with item: MediaGalleryViewModel.Item) {
let attachment = item.attachment
titleLabel.text = (attachment.sourceFilename ?? "File")
detailLabel.text = "\(Format.fileSize(attachment.byteCount)))"
titleLabel.text = attachment.documentFileName
detailLabel.text = attachment.documentFileInfo
timeLabel.text = Date(
timeIntervalSince1970: TimeInterval(item.interactionTimestampMs / 1000)
).formattedForDisplay
audioImageView.isHidden = !attachment.isAudio
}
}

View File

@ -5,6 +5,7 @@ import Combine
import YYImage
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
class GifPickerCell: UICollectionViewCell {

View File

@ -6,6 +6,7 @@ import Reachability
import SignalUtilitiesKit
import SessionUIKit
import SignalCoreKit
import SessionUtilitiesKit
class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollectionViewDataSource, UICollectionViewDelegate, GifPickerLayoutDelegate {

View File

@ -56,32 +56,26 @@ class GiphyRendition: ProxiedContentAssetDescription {
private class func fileExtension(forFormat format: GiphyFormat) -> String {
switch format {
case .gif:
return "gif"
case .mp4:
return "mp4"
case .jpg:
return "jpg"
case .gif: return "gif" // stringlint:disable
case .mp4: return "mp4" // stringlint:disable
case .jpg: return "jpg" // stringlint:disable
}
}
public var utiType: String {
switch format {
case .gif:
return kUTTypeGIF as String
case .mp4:
return kUTTypeMPEG4 as String
case .jpg:
return kUTTypeJPEG as String
case .gif: return kUTTypeGIF as String
case .mp4: return kUTTypeMPEG4 as String
case .jpg: return kUTTypeJPEG as String
}
}
public var isStill: Bool {
return name.hasSuffix("_still")
return name.hasSuffix("_still") // stringlint:disable
}
public var isDownsampled: Bool {
return name.hasSuffix("_downsampled")
return name.hasSuffix("_downsampled") // stringlint:disable
}
public func log() {
@ -279,11 +273,11 @@ enum GiphyAPI {
// MARK: - Search
// This is the Signal iOS API key.
private static let kGiphyApiKey = "ZsUpUm2L6cVbvei347EQNp7HrROjbOdc"
private static let kGiphyApiKey = "ZsUpUm2L6cVbvei347EQNp7HrROjbOdc" // stringlint:disable
private static let kGiphyPageSize = 20
public static func trending() -> AnyPublisher<[GiphyImageInfo], Error> {
let urlString = "/v1/gifs/trending?api_key=\(kGiphyApiKey)&limit=\(kGiphyPageSize)"
let urlString = "/v1/gifs/trending?api_key=\(kGiphyApiKey)&limit=\(kGiphyPageSize)" // stringlint:disable
guard let url: URL = URL(string: "\(kGiphyBaseURL)\(urlString)") else {
return Fail(error: HTTPError.invalidURL)
@ -319,10 +313,10 @@ enum GiphyAPI {
let url: URL = URL(
string: [
kGiphyBaseURL,
"/v1/gifs/search?api_key=\(kGiphyApiKey)",
"&offset=\(kGiphyPageOffset)",
"&limit=\(kGiphyPageSize)",
"&q=\(queryEncoded)"
"/v1/gifs/search?api_key=\(kGiphyApiKey)", // stringlint:disable
"&offset=\(kGiphyPageOffset)", // stringlint:disable
"&limit=\(kGiphyPageSize)", // stringlint:disable
"&q=\(queryEncoded)" // stringlint:disable
].joined()
)
else {
@ -370,7 +364,7 @@ enum GiphyAPI {
Logger.error("Invalid response.")
return nil
}
guard let imageDicts = responseDict["data"] as? [[String: Any]] else {
guard let imageDicts = responseDict["data"] as? [[String: Any]] else { // stringlint:disable
Logger.error("Invalid response data.")
return nil
}
@ -381,7 +375,7 @@ enum GiphyAPI {
// Giphy API results are often incomplete or malformed, so we need to be defensive.
private static func parseGiphyImage(imageDict: [String: Any]) -> GiphyImageInfo? {
guard let giphyId = imageDict["id"] as? String else {
guard let giphyId = imageDict["id"] as? String else { // stringlint:disable
Logger.warn("Image dict missing id.")
return nil
}
@ -389,7 +383,7 @@ enum GiphyAPI {
Logger.warn("Image dict has invalid id.")
return nil
}
guard let renditionDicts = imageDict["images"] as? [String: Any] else {
guard let renditionDicts = imageDict["images"] as? [String: Any] else { // stringlint:disable
Logger.warn("Image dict missing renditions.")
return nil
}
@ -423,7 +417,7 @@ enum GiphyAPI {
}
private static func findOriginalRendition(renditions: [GiphyRendition]) -> GiphyRendition? {
for rendition in renditions where rendition.name == "original" {
for rendition in renditions where rendition.name == "original" { // stringlint:disable
return rendition
}
return nil
@ -436,15 +430,15 @@ enum GiphyAPI {
renditionName: String,
renditionDict: [String: Any]
) -> GiphyRendition? {
guard let width = parsePositiveUInt(dict: renditionDict, key: "width", typeName: "rendition") else {
guard let width = parsePositiveUInt(dict: renditionDict, key: "width", typeName: "rendition") else { // stringlint:disable
return nil
}
guard let height = parsePositiveUInt(dict: renditionDict, key: "height", typeName: "rendition") else {
guard let height = parsePositiveUInt(dict: renditionDict, key: "height", typeName: "rendition") else { // stringlint:disable
return nil
}
// Be lenient when parsing file sizes - we don't require them for stills.
let fileSize = parseLenientUInt(dict: renditionDict, key: "size")
guard let urlString = renditionDict["url"] as? String else {
let fileSize = parseLenientUInt(dict: renditionDict, key: "size") // stringlint:disable
guard let urlString = renditionDict["url"] as? String else { // stringlint:disable
return nil
}
guard urlString.count > 0 else {
@ -460,13 +454,13 @@ enum GiphyAPI {
return nil
}
var format = GiphyFormat.gif
if fileExtension == "gif" {
if fileExtension == "gif" { // stringlint:disable
format = .gif
} else if fileExtension == "jpg" {
} else if fileExtension == "jpg" { // stringlint:disable
format = .jpg
} else if fileExtension == "mp4" {
} else if fileExtension == "mp4" { // stringlint:disable
format = .mp4
} else if fileExtension == "webp" {
} else if fileExtension == "webp" { // stringlint:disable
return nil
} else {
Logger.warn("Invalid file extension: \(fileExtension).")

View File

@ -2,6 +2,7 @@
import Foundation
import SignalUtilitiesKit
import SessionUtilitiesKit
public class GiphyDownloader: ProxiedContentDownloader {

View File

@ -3,9 +3,11 @@
import Foundation
import Combine
import Photos
import PhotosUI
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
protocol ImagePickerGridControllerDelegate: AnyObject {
func imagePickerDidCompleteSelection(_ imagePicker: ImagePickerGridController)
@ -155,6 +157,8 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
case .cancelled, .ended, .failed:
collectionView.isUserInteractionEnabled = true
collectionView.isScrollEnabled = true
@unknown default: break
}
}
@ -380,6 +384,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat
func photoLibraryDidChange(_ photoLibrary: PhotoLibrary) {
photoCollectionContents = photoCollection.contents()
collectionView?.reloadData()
}
// MARK: - PhotoCollectionPicker Presentation

View File

@ -1,18 +1,21 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import AVKit
import AVFoundation
import YYImage
import SessionUIKit
import SignalUtilitiesKit
import SessionMessagingKit
import SignalCoreKit
import SessionUtilitiesKit
public enum MediaGalleryOption {
case sliderEnabled
case showAllMediaButton
}
class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVideoPlayerDelegate, PlayerProgressBarDelegate {
class MediaDetailViewController: OWSViewController, UIScrollViewDelegate {
public let galleryItem: MediaGalleryViewModel.Item
public weak var delegate: MediaDetailViewControllerDelegate?
private var image: UIImage?
@ -36,9 +39,19 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
}()
public var mediaView: UIView = UIView()
private var playVideoButton: UIButton = UIButton()
private var videoProgressBar: PlayerProgressBar = PlayerProgressBar()
private var videoPlayer: OWSVideoPlayer?
private lazy var playVideoButton: UIButton = {
let result: UIButton = UIButton()
result.contentMode = .scaleAspectFill
result.setBackgroundImage(UIImage(named: "CirclePlay"), for: .normal)
result.addTarget(self, action: #selector(playVideo), for: .touchUpInside)
result.alpha = 0
let playButtonSize: CGFloat = ScaleFromIPhone5(70)
result.set(.width, to: playButtonSize)
result.set(.height, to: playButtonSize)
return result
}()
// MARK: - Initialization
@ -85,10 +98,6 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
fatalError("init(coder:) has not been implemented")
}
deinit {
self.stopAnyVideo()
}
// MARK: - Lifecycle
override func viewDidLoad() {
@ -97,7 +106,10 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
self.view.themeBackgroundColor = .newConversation_background
self.view.addSubview(scrollView)
self.view.addSubview(playVideoButton)
scrollView.pin(to: self.view)
playVideoButton.center(in: self.view)
self.updateContents()
}
@ -111,12 +123,18 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.parent == nil || !(self.parent is MediaPageViewController) {
parentDidAppear()
}
}
public func parentDidAppear() {
if mediaView is YYAnimatedImageView {
// Add a slight delay before starting the gif animation to prevent it from looking
// buggy due to the custom transition
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250)) { [weak self] in
(self?.mediaView as? YYAnimatedImageView)?.startAnimating()
}
(mediaView as? YYAnimatedImageView)?.startAnimating()
}
if self.galleryItem.attachment.isVideo {
UIView.animate(withDuration: 0.2) { self.playVideoButton.alpha = 1 }
}
}
@ -127,6 +145,12 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
self.centerMediaViewConstraints()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
UIView.animate(withDuration: 0.15) { [weak playVideoButton] in playVideoButton?.alpha = 0 }
}
// MARK: - Functions
private func updateMinZoomScale() {
@ -173,8 +197,6 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
private func updateContents() {
self.mediaView.removeFromSuperview()
self.playVideoButton.removeFromSuperview()
self.videoProgressBar.removeFromSuperview()
self.scrollView.zoomScale = 1
if self.galleryItem.attachment.isAnimated {
@ -194,15 +216,6 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
self.mediaView = UIView()
self.mediaView.themeBackgroundColor = .newConversation_background
}
else if self.galleryItem.attachment.isVideo {
if self.galleryItem.attachment.isValid {
self.mediaView = self.buildVideoPlayerView()
}
else {
self.mediaView = UIView()
self.mediaView.themeBackgroundColor = .newConversation_background
}
}
else {
// Present the static image using standard UIImageView
self.mediaView = UIImageView(image: self.image)
@ -229,61 +242,6 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
// some performance cost.
self.mediaView.layer.minificationFilter = .trilinear
self.mediaView.layer.magnificationFilter = .trilinear
if self.galleryItem.attachment.isVideo {
self.videoProgressBar = PlayerProgressBar()
self.videoProgressBar.delegate = self
self.videoProgressBar.player = self.videoPlayer?.avPlayer
// We hide the progress bar until either:
// 1. Video completes playing
// 2. User taps the screen
self.videoProgressBar.isHidden = false
self.view.addSubview(self.videoProgressBar)
self.videoProgressBar.autoPinWidthToSuperview()
self.videoProgressBar.autoPinEdge(toSuperviewSafeArea: .top)
self.videoProgressBar.autoSetDimension(.height, toSize: 44)
self.playVideoButton = UIButton()
self.playVideoButton.contentMode = .scaleAspectFill
self.playVideoButton.setBackgroundImage(UIImage(named: "CirclePlay"), for: .normal)
self.playVideoButton.addTarget(self, action: #selector(playVideo), for: .touchUpInside)
self.view.addSubview(self.playVideoButton)
self.playVideoButton.set(.width, to: 72)
self.playVideoButton.set(.height, to: 72)
self.playVideoButton.center(in: self.view)
}
}
private func buildVideoPlayerView() -> UIView {
guard
let originalFilePath: String = self.galleryItem.attachment.originalFilePath,
FileManager.default.fileExists(atPath: originalFilePath)
else {
owsFailDebug("Missing video file")
return UIView()
}
self.videoPlayer = OWSVideoPlayer(url: URL(fileURLWithPath: originalFilePath))
self.videoPlayer?.seek(to: .zero)
self.videoPlayer?.delegate = self
let imageSize: CGSize = (self.image?.size ?? .zero)
let playerView: VideoPlayerView = VideoPlayerView()
playerView.player = self.videoPlayer?.avPlayer
NSLayoutConstraint.autoSetPriority(.defaultLow) {
playerView.autoSetDimensions(to: imageSize)
}
return playerView
}
public func setShouldHideToolbars(_ shouldHideToolbars: Bool) {
self.videoProgressBar.isHidden = shouldHideToolbars
}
private func addGestureRecognizers(to view: UIView) {
@ -329,14 +287,10 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
self.scrollView.zoom(to: translatedRect, animated: true)
}
@objc public func didPressPlayBarButton() {
public func didPressPlayBarButton() {
self.playVideo()
}
@objc public func didPressPauseBarButton() {
self.pauseVideo()
}
// MARK: - UIScrollViewDelegate
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
@ -390,49 +344,17 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
// MARK: - Video Playback
@objc public func playVideo() {
self.playVideoButton.isHidden = true
self.videoPlayer?.play()
self.delegate?.mediaDetailViewController(self, isPlayingVideo: true)
}
private func pauseVideo() {
self.videoPlayer?.pause()
self.delegate?.mediaDetailViewController(self, isPlayingVideo: false)
}
public func stopAnyVideo() {
guard self.galleryItem.attachment.isVideo else { return }
guard
let originalFilePath: String = self.galleryItem.attachment.originalFilePath,
FileManager.default.fileExists(atPath: originalFilePath)
else { return SNLog("Missing video file") }
self.stopVideo()
}
private func stopVideo() {
self.videoPlayer?.stop()
self.playVideoButton.isHidden = false
self.delegate?.mediaDetailViewController(self, isPlayingVideo: false)
}
// MARK: - OWSVideoPlayerDelegate
func videoPlayerDidPlayToCompletion(_ videoPlayer: OWSVideoPlayer) {
self.stopVideo()
}
// MARK: - PlayerProgressBarDelegate
func playerProgressBarDidStartScrubbing(_ playerProgressBar: PlayerProgressBar) {
self.videoPlayer?.pause()
}
func playerProgressBar(_ playerProgressBar: PlayerProgressBar, scrubbedToTime time: CMTime) {
self.videoPlayer?.seek(to: time)
}
func playerProgressBar(_ playerProgressBar: PlayerProgressBar, didFinishScrubbingAtTime time: CMTime, shouldResumePlayback: Bool) {
self.videoPlayer?.seek(to: time)
if shouldResumePlayback {
self.videoPlayer?.play()
let videoUrl: URL = URL(fileURLWithPath: originalFilePath)
let player: AVPlayer = AVPlayer(url: videoUrl)
let viewController: AVPlayerViewController = AVPlayerViewController()
viewController.player = player
self.present(viewController, animated: true) { [weak player] in
player?.play()
}
}
}
@ -440,6 +362,5 @@ class MediaDetailViewController: OWSViewController, UIScrollViewDelegate, OWSVid
// MARK: - MediaDetailViewControllerDelegate
protocol MediaDetailViewControllerDelegate: AnyObject {
func mediaDetailViewController(_ mediaDetailViewController: MediaDetailViewController, isPlayingVideo: Bool)
func mediaDetailViewControllerDidTapMedia(_ mediaDetailViewController: MediaDetailViewController)
}

View File

@ -44,6 +44,10 @@ class MediaGalleryNavigationController: UINavigationController {
// MARK: - Orientation
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.isIPad {
return .all
}
return .allButUpsideDown
}

View File

@ -145,7 +145,7 @@ public class MediaGalleryViewModel {
public struct GalleryDate: Differentiable, Equatable, Comparable, Hashable {
private static let thisYearFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM"
formatter.dateFormat = "MMMM" // stringlint:disable
return formatter
}()
@ -153,7 +153,7 @@ public class MediaGalleryViewModel {
private static let olderFormatter: DateFormatter = {
// FIXME: localize for RTL, or is there a built in way to do this?
let formatter = DateFormatter()
formatter.dateFormat = "MMMM yyyy"
formatter.dateFormat = "MMMM yyyy" // stringlint:disable
return formatter
}()
@ -199,16 +199,18 @@ public class MediaGalleryViewModel {
}
}
public struct Item: FetchableRecordWithRowId, Decodable, Identifiable, Differentiable, Equatable, Hashable {
fileprivate static let interactionIdKey: SQL = SQL(stringLiteral: CodingKeys.interactionId.stringValue)
fileprivate static let interactionVariantKey: SQL = SQL(stringLiteral: CodingKeys.interactionVariant.stringValue)
fileprivate static let interactionAuthorIdKey: SQL = SQL(stringLiteral: CodingKeys.interactionAuthorId.stringValue)
fileprivate static let interactionTimestampMsKey: SQL = SQL(stringLiteral: CodingKeys.interactionTimestampMs.stringValue)
fileprivate static let rowIdKey: SQL = SQL(stringLiteral: CodingKeys.rowId.stringValue)
fileprivate static let attachmentKey: SQL = SQL(stringLiteral: CodingKeys.attachment.stringValue)
fileprivate static let attachmentAlbumIndexKey: SQL = SQL(stringLiteral: CodingKeys.attachmentAlbumIndex.stringValue)
fileprivate static let attachmentString: String = CodingKeys.attachment.stringValue
public struct Item: FetchableRecordWithRowId, Decodable, Identifiable, Differentiable, Equatable, Hashable, ColumnExpressible {
public typealias Columns = CodingKeys
public enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
case interactionId
case interactionVariant
case interactionAuthorId
case interactionTimestampMs
case rowId
case attachmentAlbumIndex
case attachment
}
public var id: String { attachment.id }
public var differenceIdentifier: String { attachment.id }
@ -306,7 +308,7 @@ public class MediaGalleryViewModel {
let finalFilterSQL: SQL = {
guard let customFilters: SQL = customFilters else {
return """
WHERE \(attachment.alias[Column.rowID]) IN \(rowIds)
WHERE \(attachment[.rowId]) IN \(rowIds)
"""
}
@ -318,14 +320,14 @@ public class MediaGalleryViewModel {
}()
let request: SQLRequest<Item> = """
SELECT
\(interaction[.id]) AS \(Item.interactionIdKey),
\(interaction[.variant]) AS \(Item.interactionVariantKey),
\(interaction[.authorId]) AS \(Item.interactionAuthorIdKey),
\(interaction[.timestampMs]) AS \(Item.interactionTimestampMsKey),
\(interaction[.id]) AS \(Item.Columns.interactionId),
\(interaction[.variant]) AS \(Item.Columns.interactionVariant),
\(interaction[.authorId]) AS \(Item.Columns.interactionAuthorId),
\(interaction[.timestampMs]) AS \(Item.Columns.interactionTimestampMs),
\(attachment.alias[Column.rowID]) AS \(Item.rowIdKey),
\(interactionAttachment[.albumIndex]) AS \(Item.attachmentAlbumIndexKey),
\(Item.attachmentKey).*
\(attachment[.rowId]) AS \(Item.Columns.rowId),
\(interactionAttachment[.albumIndex]) AS \(Item.Columns.attachmentAlbumIndex),
\(attachment.allColumns)
FROM \(Attachment.self)
\(joinSQL)
\(finalFilterSQL)
@ -338,8 +340,8 @@ public class MediaGalleryViewModel {
Attachment.numberOfSelectedColumns(db)
])
return ScopeAdapter([
Item.attachmentString: adapters[1]
return ScopeAdapter.with(Item.self, [
.attachment: adapters[1]
])
}
}

View File

@ -18,6 +18,7 @@ extension MediaInfoVC {
let result: MediaView = MediaView.init(
attachment: attachment,
isOutgoing: isOutgoing,
shouldSupressControls: false,
cornerRadius: 0
)

View File

@ -6,6 +6,8 @@ import SessionUIKit
import SessionMessagingKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
import SessionSnodeKit
class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, MediaDetailViewControllerDelegate, InteractivelyDismissableViewController {
class DynamicallySizedView: UIView {
@ -48,8 +50,10 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
updateTitle(item: item)
updateCaption(item: item)
setViewControllers([galleryPage], direction: direction, animated: isAnimated)
updateFooterBarButtonItems(isPlayingVideo: false)
setViewControllers([galleryPage], direction: direction, animated: isAnimated) { [weak galleryPage] _ in
galleryPage?.parentDidAppear() // Trigger any custom appearance animations
}
updateFooterBarButtonItems()
updateMediaRail(item: item)
}
@ -202,7 +206,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
updateTitle(item: currentItem)
updateCaption(item: currentItem)
updateMediaRail(item: currentItem)
updateFooterBarButtonItems(isPlayingVideo: false)
updateFooterBarButtonItems()
// Gestures
@ -235,6 +239,15 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
hasAppeared = true
becomeFirstResponder()
children.forEach { child in
switch child {
case let detailViewController as MediaDetailViewController:
detailViewController.parentDidAppear()
default: break
}
}
}
public override func viewWillDisappear(_ animated: Bool) {
@ -289,7 +302,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
// MARK: View Helpers
public func willBePresentedAgain() {
updateFooterBarButtonItems(isPlayingVideo: false)
updateFooterBarButtonItems()
}
public func wasPresented() {
@ -307,7 +320,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
self.navigationController?.setNavigationBarHidden(shouldHideToolbars, animated: false)
UIView.animate(withDuration: 0.1) {
self.currentViewController.setShouldHideToolbars(self.shouldHideToolbars)
self.bottomContainer.isHidden = self.shouldHideToolbars
}
}
@ -352,24 +364,12 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
return videoPlayBarButton
}()
lazy var videoPauseBarButton: UIBarButtonItem = {
let videoPauseBarButton = UIBarButtonItem(
barButtonSystemItem: .pause,
target: self,
action: #selector(didPressPauseBarButton)
)
videoPauseBarButton.themeTintColor = .textPrimary
return videoPauseBarButton
}()
private func updateFooterBarButtonItems(isPlayingVideo: Bool) {
private func updateFooterBarButtonItems() {
self.footerBar.setItems(
[
shareBarButton,
buildFlexibleSpace(),
(self.currentItem.isVideo && isPlayingVideo ? self.videoPauseBarButton : nil),
(self.currentItem.isVideo && !isPlayingVideo ? self.videoPlayBarButton : nil),
(self.currentItem.isVideo ? self.videoPlayBarButton : nil),
(self.currentItem.isVideo ? buildFlexibleSpace() : nil),
deleteBarButton
].compactMap { $0 },
@ -463,12 +463,19 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
// MARK: - Actions
@objc public func didPressAllMediaButton(sender: Any) {
currentViewController.stopAnyVideo()
// If the screen wasn't presented or it was presented from a location which isn't the
// MediaTileViewController then just pop/dismiss the screen
let parentNavController: UINavigationController? = {
switch self.presentingViewController {
case let topBannerController as TopBannerController:
return topBannerController.children.first as? UINavigationController
default: return self.presentingViewController as? UINavigationController
}
}()
guard
let presentingNavController: UINavigationController = (self.presentingViewController as? UINavigationController),
let presentingNavController: UINavigationController = parentNavController,
!(presentingNavController.viewControllers.last is AllMediaViewController)
else {
guard self.navigationController?.viewControllers.count == 1 else {
@ -505,8 +512,9 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
dismissSelf(animated: true)
}
@objc
public func didPressShare(_ sender: Any) {
@objc public func didPressShare(_ sender: Any) { share() }
public func share(using dependencies: Dependencies = Dependencies()) {
guard let currentViewController = self.viewControllers?[0] as? MediaDetailViewController else {
owsFailDebug("currentViewController was unexpectedly nil")
return
@ -553,7 +561,8 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
),
interactionId: nil, // Show no interaction for the current user
threadId: threadId,
threadVariant: threadVariant
threadVariant: threadVariant,
using: dependencies
)
}
}
@ -609,15 +618,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
currentViewController.didPressPlayBarButton()
}
@objc public func didPressPauseBarButton() {
guard let currentViewController = self.viewControllers?.first as? MediaDetailViewController else {
SNLog("currentViewController was unexpectedly nil")
return
}
currentViewController.didPressPauseBarButton()
}
// MARK: UIPageViewControllerDelegate
var pendingViewController: MediaDetailViewController?
@ -637,9 +637,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
} else {
self.captionContainerView.pendingText = nil
}
// Ensure upcoming page respects current toolbar status
pendingViewController.setShouldHideToolbars(self.shouldHideToolbars)
}
}
@ -663,11 +660,11 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
captionContainerView.completePagerTransition()
}
currentViewController.parentDidAppear() // Trigger any custom appearance animations
updateTitle(item: currentItem)
updateMediaRail(item: currentItem)
previousPage.zoomOut(animated: false)
previousPage.stopAnyVideo()
updateFooterBarButtonItems(isPlayingVideo: false)
updateFooterBarButtonItems()
} else {
captionContainerView.pendingText = nil
}
@ -788,7 +785,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
// Swapping mediaView for presentationView will be perceptible if we're not zoomed out all the way.
// currentVC
currentViewController.zoomOut(animated: true)
currentViewController.stopAnyVideo()
self.navigationController?.view.isUserInteractionEnabled = false
self.navigationController?.dismiss(animated: true, completion: { [weak self] in
@ -810,16 +806,6 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
self.shouldHideToolbars = !self.shouldHideToolbars
}
public func mediaDetailViewController(_ mediaDetailViewController: MediaDetailViewController, isPlayingVideo: Bool) {
guard mediaDetailViewController == currentViewController else {
Logger.verbose("ignoring stale delegate.")
return
}
self.shouldHideToolbars = isPlayingVideo
self.updateFooterBarButtonItems(isPlayingVideo: isPlayingVideo)
}
// MARK: - Dynamic Header
private lazy var dateFormatter: DateFormatter = {

View File

@ -7,6 +7,7 @@ import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
public class MediaTileViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
@ -54,6 +55,10 @@ public class MediaTileViewController: UIViewController, UICollectionViewDataSour
// MARK: - UI
override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.isIPad {
return .all
}
return .allButUpsideDown
}

View File

@ -1,4 +1,6 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
import Combine

View File

@ -6,6 +6,7 @@ import AVFoundation
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
protocol PhotoCaptureViewControllerDelegate: AnyObject {
func photoCaptureViewController(_ photoCaptureViewController: PhotoCaptureViewController, didFinishProcessingAttachment attachment: SignalAttachment)
@ -274,14 +275,11 @@ class PhotoCaptureViewController: OWSViewController {
let transformFromOrientation: CGAffineTransform
switch captureOrientation {
case .portrait:
transformFromOrientation = .identity
case .portraitUpsideDown:
transformFromOrientation = CGAffineTransform(rotationAngle: .pi)
case .landscapeLeft:
transformFromOrientation = CGAffineTransform(rotationAngle: .halfPi)
case .landscapeRight:
transformFromOrientation = CGAffineTransform(rotationAngle: -1 * .halfPi)
case .portrait: transformFromOrientation = .identity
case .portraitUpsideDown: transformFromOrientation = CGAffineTransform(rotationAngle: .pi)
case .landscapeLeft: transformFromOrientation = CGAffineTransform(rotationAngle: .halfPi)
case .landscapeRight: transformFromOrientation = CGAffineTransform(rotationAngle: -1 * .halfPi)
@unknown default: transformFromOrientation = .identity
}
// Don't "unrotate" the switch camera icon if the front facing camera had been selected.

View File

@ -8,73 +8,75 @@ import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
class PhotoCollectionPickerViewModel: SessionTableViewModel<NoNav, PhotoCollectionPickerViewModel.Section, PhotoCollectionPickerViewModel.Item> {
// MARK: - Config
class PhotoCollectionPickerViewModel: SessionTableViewModel, ObservableTableSource {
typealias TableItem = String
public enum Section: SessionTableSection {
case content
}
public let dependencies: Dependencies
public let state: TableDataState<Section, TableItem> = TableDataState()
public let observableState: ObservableTableSourceState<Section, TableItem> = ObservableTableSourceState()
public struct Item: Equatable, Hashable, Differentiable {
let id: String
}
private let library: PhotoLibrary
private let onCollectionSelected: (PhotoCollection) -> Void
private var photoCollections: CurrentValueSubject<[PhotoCollection], Error>
// MARK: - Initialization
init(library: PhotoLibrary, onCollectionSelected: @escaping (PhotoCollection) -> Void) {
init(
library: PhotoLibrary,
onCollectionSelected: @escaping (PhotoCollection) -> Void,
using dependencies: Dependencies = Dependencies()
) {
self.dependencies = dependencies
self.library = library
self.onCollectionSelected = onCollectionSelected
self.photoCollections = CurrentValueSubject(library.allPhotoCollections())
}
// MARK: - Config
public enum Section: SessionTableSection {
case content
}
// MARK: - Content
override var title: String { "NOTIFICATIONS_STYLE_SOUND_TITLE".localized() }
override var observableTableData: ObservableData { _observableTableData }
let title: String = "NOTIFICATIONS_STYLE_SOUND_TITLE".localized()
private lazy var _observableTableData: ObservableData = {
self.photoCollections
.map { collections in
[
SectionModel(
model: .content,
elements: collections.map { collection in
let contents: PhotoCollectionContents = collection.contents()
let photoMediaSize: PhotoMediaSize = PhotoMediaSize(
thumbnailSize: CGSize(
width: IconSize.extraLarge.size,
height: IconSize.extraLarge.size
)
lazy var observation: TargetObservation = ObservationBuilder
.subject(photoCollections)
.map { collections -> [SectionModel] in
[
SectionModel(
model: .content,
elements: collections.map { collection in
let contents: PhotoCollectionContents = collection.contents()
let photoMediaSize: PhotoMediaSize = PhotoMediaSize(
thumbnailSize: CGSize(
width: IconSize.extraLarge.size,
height: IconSize.extraLarge.size
)
let lastAssetItem: PhotoPickerAssetItem? = contents.lastAssetItem(photoMediaSize: photoMediaSize)
return SessionCell.Info(
id: Item(id: collection.id),
leftAccessory: .iconAsync(size: .extraLarge, shouldFill: true) { imageView in
// Note: We need to capture 'lastAssetItem' otherwise it'll be released and we won't
// be able to load the thumbnail
lastAssetItem?.asyncThumbnail { [weak imageView] image in
imageView?.image = image
}
},
title: collection.localizedTitle(),
subtitle: "\(contents.assetCount)",
onTap: { [weak self] in
self?.onCollectionSelected(collection)
)
let lastAssetItem: PhotoPickerAssetItem? = contents.lastAssetItem(photoMediaSize: photoMediaSize)
return SessionCell.Info(
id: collection.id,
leftAccessory: .iconAsync(size: .extraLarge, shouldFill: true) { imageView in
// Note: We need to capture 'lastAssetItem' otherwise it'll be released and we won't
// be able to load the thumbnail
lastAssetItem?.asyncThumbnail { [weak imageView] image in
imageView?.image = image
}
)
}
)
]
}
.removeDuplicates()
.eraseToAnyPublisher()
.mapToSessionTableViewData(for: self)
}()
},
title: collection.localizedTitle(),
subtitle: "\(contents.assetCount)",
onTap: { [weak self] in
self?.onCollectionSelected(collection)
}
)
}
)
]
}
// MARK: PhotoLibraryDelegate

View File

@ -6,6 +6,7 @@ import Photos
import CoreServices
import SignalUtilitiesKit
import SignalCoreKit
import SessionUtilitiesKit
protocol PhotoLibraryDelegate: AnyObject {
func photoLibraryDidChange(_ photoLibrary: PhotoLibrary)

View File

@ -6,6 +6,7 @@ import Photos
import SignalUtilitiesKit
import SignalCoreKit
import SessionUIKit
import SessionUtilitiesKit
class SendMediaNavigationController: UINavigationController {
public override var preferredStatusBarStyle: UIStatusBarStyle {
@ -17,12 +18,14 @@ class SendMediaNavigationController: UINavigationController {
static let bottomButtonsCenterOffset: CGFloat = -50
private let threadId: String
private let threadVariant: SessionThread.Variant
private var disposables: Set<AnyCancellable> = Set()
// MARK: - Initialization
init(threadId: String) {
init(threadId: String, threadVariant: SessionThread.Variant) {
self.threadId = threadId
self.threadVariant = threadVariant
super.init(nibName: nil, bundle: nil)
}
@ -73,17 +76,15 @@ class SendMediaNavigationController: UINavigationController {
public weak var sendMediaNavDelegate: SendMediaNavDelegate?
@objc
public class func showingCameraFirst(threadId: String) -> SendMediaNavigationController {
let navController = SendMediaNavigationController(threadId: threadId)
public class func showingCameraFirst(threadId: String, threadVariant: SessionThread.Variant) -> SendMediaNavigationController {
let navController = SendMediaNavigationController(threadId: threadId, threadVariant: threadVariant)
navController.viewControllers = [navController.captureViewController]
return navController
}
@objc
public class func showingMediaLibraryFirst(threadId: String) -> SendMediaNavigationController {
let navController = SendMediaNavigationController(threadId: threadId)
public class func showingMediaLibraryFirst(threadId: String, threadVariant: SessionThread.Variant) -> SendMediaNavigationController {
let navController = SendMediaNavigationController(threadId: threadId, threadVariant: threadVariant)
navController.viewControllers = [navController.mediaLibraryViewController]
return navController
@ -232,6 +233,7 @@ class SendMediaNavigationController: UINavigationController {
let approvalViewController = AttachmentApprovalViewController(
mode: .sharedNavigation,
threadId: self.threadId,
threadVariant: self.threadVariant,
attachments: self.attachments
)
approvalViewController.approvalDelegate = self
@ -430,8 +432,22 @@ extension SendMediaNavigationController: AttachmentApprovalViewControllerDelegat
attachmentDraftCollection.remove(attachment: attachment)
}
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didApproveAttachments attachments: [SignalAttachment], forThreadId threadId: String, messageText: String?) {
sendMediaNavDelegate?.sendMediaNav(self, didApproveAttachments: attachments, forThreadId: threadId, messageText: messageText)
func attachmentApproval(
_ attachmentApproval: AttachmentApprovalViewController,
didApproveAttachments attachments: [SignalAttachment],
forThreadId threadId: String,
threadVariant: SessionThread.Variant,
messageText: String?,
using dependencies: Dependencies
) {
sendMediaNavDelegate?.sendMediaNav(
self,
didApproveAttachments: attachments,
forThreadId: threadId,
threadVariant: threadVariant,
messageText: messageText,
using: dependencies
)
}
func attachmentApprovalDidCancel(_ attachmentApproval: AttachmentApprovalViewController) {
@ -539,8 +555,8 @@ private struct MediaLibrarySelection: Hashable, Equatable {
let asset: PHAsset
let signalAttachmentPublisher: AnyPublisher<SignalAttachment, Error>
var hashValue: Int {
return asset.hashValue
func hash(into hasher: inout Hasher) {
asset.hash(into: &hasher)
}
var publisher: AnyPublisher<MediaLibraryAttachment, Error> {
@ -559,8 +575,8 @@ private struct MediaLibraryAttachment: Hashable, Equatable {
let asset: PHAsset
let signalAttachment: SignalAttachment
public var hashValue: Int {
return asset.hashValue
func hash(into hasher: inout Hasher) {
asset.hash(into: &hasher)
}
public static func == (lhs: MediaLibraryAttachment, rhs: MediaLibraryAttachment) -> Bool {
@ -764,7 +780,7 @@ private class DoneButton: UIView {
protocol SendMediaNavDelegate: AnyObject {
func sendMediaNavDidCancel(_ sendMediaNavigationController: SendMediaNavigationController?)
func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didApproveAttachments attachments: [SignalAttachment], forThreadId threadId: String, messageText: String?)
func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didApproveAttachments attachments: [SignalAttachment], forThreadId threadId: String, threadVariant: SessionThread.Variant, messageText: String?, using dependencies: Dependencies)
func sendMediaNavInitialMessageText(_ sendMediaNavigationController: SendMediaNavigationController) -> String?
func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didChangeMessageText newMessageText: String?)

View File

@ -9,6 +9,7 @@ import SessionMessagingKit
import SessionUtilitiesKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionSnodeKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
@ -88,11 +89,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
)
if Environment.shared?.callManager.wrappedValue?.currentCall == nil {
UserDefaults.sharedLokiProject?.set(false, forKey: "isCallOngoing")
UserDefaults.sharedLokiProject?[.isCallOngoing] = false
UserDefaults.sharedLokiProject?[.lastCallPreOffer] = nil
}
// No point continuing if we are running tests
guard !CurrentAppContext().isRunningTests else { return true }
guard !SNUtilitiesKit.isRunningTests else { return true }
self.window = mainWindow
CurrentAppContext().mainWindow = mainWindow
@ -212,7 +214,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
func applicationDidBecomeActive(_ application: UIApplication) {
guard !CurrentAppContext().isRunningTests else { return }
guard !SNUtilitiesKit.isRunningTests else { return }
UserDefaults.sharedLokiProject?[.isMainAppActive] = true
@ -248,7 +250,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if UIDevice.current.isIPad {
return .allButUpsideDown
return .all
}
return .portrait
@ -314,7 +316,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private func completePostMigrationSetup(calledFrom lifecycleMethod: LifecycleMethod, needsConfigSync: Bool) {
SNLog("Migrations completed, performing setup and ensuring rootViewController")
Configuration.performMainSetup()
JobRunner.add(executor: SyncPushTokensJob.self, for: .syncPushTokens)
JobRunner.setExecutor(SyncPushTokensJob.self, for: .syncPushTokens)
// Setup the UI if needed, then trigger any post-UI setup actions
self.ensureRootViewController(calledFrom: lifecycleMethod) { [weak self] success in
@ -322,7 +324,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// the user is in an invalid state (and should have already been shown a modal)
guard success else { return }
SNLog("RootViewController ready, readying remaining processes")
SNLog("RootViewController ready for state: \(Onboarding.State.current), readying remaining processes")
self?.initialLaunchFailed = false
/// Trigger any launch-specific jobs and start the JobRunner with `JobRunner.appDidFinishLaunching()` some
@ -415,7 +417,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Don't offer the 'Restore' option if it was a 'startupFailed' error as a restore is unlikely to
// resolve it (most likely the database is locked or the key was somehow lost - safer to get them
// to restart and manually reinstall/restore)
case .databaseError(StorageError.startupFailed): break
case .databaseError(StorageError.startupFailed), .databaseError(DatabaseError.SQLITE_LOCKED): break
// Offer the 'Restore' option if it was a migration error
case .databaseError:
@ -522,7 +524,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
startPollersIfNeeded()
if CurrentAppContext().isMainApp {
syncConfigurationIfNeeded()
handleAppActivatedWithOngoingCallIfNeeded()
}
}
@ -663,39 +664,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
/// we don't block user interaction while it's running
DispatchQueue.global(qos: .default).async {
let unreadCount: Int = Storage.shared
.read { db in
let userPublicKey: String = getUserHexEncodedPublicKey(db)
let thread: TypedTableAlias<SessionThread> = TypedTableAlias()
return try Interaction
.filter(Interaction.Columns.wasRead == false)
.filter(Interaction.Variant.variantsToIncrementUnreadCount.contains(Interaction.Columns.variant))
.filter(
// Only count mentions if 'onlyNotifyForMentions' is set
thread[.onlyNotifyForMentions] == false ||
Interaction.Columns.hasMention == true
)
.joining(
required: Interaction.thread
.aliased(thread)
.joining(optional: SessionThread.contact)
.filter(
// Ignore muted threads
SessionThread.Columns.mutedUntilTimestamp == nil ||
SessionThread.Columns.mutedUntilTimestamp < Date().timeIntervalSince1970
)
.filter(
// Ignore message request threads
SessionThread.Columns.variant != SessionThread.Variant.contact ||
!SessionThread.isMessageRequest(userPublicKey: userPublicKey)
)
)
.fetchCount(db)
}
.read { db in try Interaction.fetchUnreadCount(db) }
.defaulting(to: 0)
DispatchQueue.main.async {
CurrentAppContext().setMainAppBadgeNumber(unreadCount)
UIApplication.shared.applicationIconBadgeNumber = unreadCount
}
}
}
@ -868,36 +841,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
presentingVC.present(callVC, animated: true, completion: nil)
}
// MARK: - Config Sync
func syncConfigurationIfNeeded() {
// FIXME: Remove this once `useSharedUtilForUserConfig` is permanent
guard !SessionUtil.userConfigsEnabled else { return }
let lastSync: Date = (UserDefaults.standard[.lastConfigurationSync] ?? .distantPast)
guard Date().timeIntervalSince(lastSync) > (7 * 24 * 60 * 60) else { return } // Sync every 2 days
Storage.shared
.writeAsync(
updates: { db in
ConfigurationSyncJob.enqueue(db, publicKey: getUserHexEncodedPublicKey(db))
},
completion: { _, result in
switch result {
case .failure: break
case .success:
// Only update the 'lastConfigurationSync' timestamp if we have done the
// first sync (Don't want a new device config sync to override config
// syncs from other devices)
if UserDefaults.standard[.hasSyncedInitialConfiguration] {
UserDefaults.standard[.lastConfigurationSync] = Date()
}
}
}
)
}
}
// MARK: - LifecycleMethod
@ -934,7 +877,9 @@ private enum StartupError: Error {
var name: String {
switch self {
case .databaseError(StorageError.startupFailed): return "Database startup failed"
case .databaseError(StorageError.startupFailed), .databaseError(DatabaseError.SQLITE_LOCKED):
return "Database startup failed"
case .failedToRestore: return "Failed to restore"
case .databaseError: return "Database error"
case .startupTimeout: return "Startup timeout"
@ -943,7 +888,9 @@ private enum StartupError: Error {
var message: String {
switch self {
case .databaseError(StorageError.startupFailed): return "DATABASE_STARTUP_FAILED".localized()
case .databaseError(StorageError.startupFailed), .databaseError(DatabaseError.SQLITE_LOCKED):
return "DATABASE_STARTUP_FAILED".localized()
case .failedToRestore: return "DATABASE_RESTORE_FAILED".localized()
case .databaseError: return "DATABASE_MIGRATION_FAILED".localized()
case .startupTimeout: return "APP_STARTUP_TIMEOUT".localized()

View File

@ -1,8 +1,10 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionUtilitiesKit
import SignalUtilitiesKit
import SignalCoreKit
import SessionMessagingKit
public class AppEnvironment {
@ -11,7 +13,7 @@ public class AppEnvironment {
public class var shared: AppEnvironment {
get { return _shared }
set {
guard CurrentAppContext().isRunningTests else {
guard SNUtilitiesKit.isRunningTests else {
owsFailDebug("Can only switch environments in tests.")
return
}

View File

@ -1,17 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <SessionUtilitiesKit/AppContext.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString *const ReportedApplicationStateDidChangeNotification;
@interface MainAppContext : NSObject <AppContext>
- (instancetype)init;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,321 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "MainAppContext.h"
#import "Session-Swift.h"
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplicationStateDidChangeNotification";
@interface MainAppContext ()
@property (atomic) UIApplicationState reportedApplicationState;
@property (nonatomic, nullable) NSMutableArray<AppActiveBlock> *appActiveBlocks;
@end
#pragma mark -
@implementation MainAppContext
@synthesize mainWindow = _mainWindow;
@synthesize appLaunchTime = _appLaunchTime;
@synthesize wasWokenUpByPushNotification = _wasWokenUpByPushNotification;
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
self.reportedApplicationState = UIApplicationStateInactive;
_appLaunchTime = [NSDate new];
_wasWokenUpByPushNotification = false;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
// We can't use OWSSingletonAssert() since it uses the app context.
self.appActiveBlocks = [NSMutableArray new];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notifications
- (void)setReportedApplicationState:(UIApplicationState)reportedApplicationState
{
OWSAssertIsOnMainThread();
if (_reportedApplicationState == reportedApplicationState) {
return;
}
_reportedApplicationState = reportedApplicationState;
[[NSNotificationCenter defaultCenter] postNotificationName:ReportedApplicationStateDidChangeNotification
object:nil
userInfo:nil];
}
- (void)applicationWillEnterForeground:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateInactive;
OWSLogInfo(@"");
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillEnterForegroundNotification object:nil];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateBackground;
OWSLogInfo(@"");
[DDLog flushLog];
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidEnterBackgroundNotification object:nil];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateInactive;
OWSLogInfo(@"");
[DDLog flushLog];
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillResignActiveNotification object:nil];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateActive;
OWSLogInfo(@"");
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidBecomeActiveNotification object:nil];
[self runAppActiveBlocks];
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
OWSLogInfo(@"");
[DDLog flushLog];
}
#pragma mark -
- (BOOL)isMainApp
{
return YES;
}
- (BOOL)isMainAppAndActive
{
return [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
}
- (BOOL)isShareExtension {
return NO;
}
- (BOOL)isRTL
{
// FIXME: We should try to remove this as we've had to add a hack to ensure the first call to this runs on the main thread
static BOOL isRTL = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
isRTL = [[UIApplication sharedApplication] userInterfaceLayoutDirection]
== UIUserInterfaceLayoutDirectionRightToLeft;
});
return isRTL;
}
- (void)setStatusBarHidden:(BOOL)isHidden animated:(BOOL)isAnimated
{
[[UIApplication sharedApplication] setStatusBarHidden:isHidden animated:isAnimated];
}
- (CGFloat)statusBarHeight
{
return [UIApplication sharedApplication].statusBarFrame.size.height;
}
- (BOOL)isInBackground
{
return self.reportedApplicationState == UIApplicationStateBackground;
}
- (BOOL)isAppForegroundAndActive
{
return self.reportedApplicationState == UIApplicationStateActive;
}
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:
(BackgroundTaskExpirationHandler)expirationHandler
{
return [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
}
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)backgroundTaskIdentifier
{
[UIApplication.sharedApplication endBackgroundTask:backgroundTaskIdentifier];
}
- (void)ensureSleepBlocking:(BOOL)shouldBeBlocking blockingObjects:(NSArray<id> *)blockingObjects
{
if (UIApplication.sharedApplication.isIdleTimerDisabled != shouldBeBlocking) {
if (shouldBeBlocking) {
NSMutableString *logString =
[NSMutableString stringWithFormat:@"Blocking sleep because of: %@", blockingObjects.firstObject];
if (blockingObjects.count > 1) {
[logString appendString:[NSString stringWithFormat:@"(and %lu others)", blockingObjects.count - 1]];
}
OWSLogInfo(@"%@", logString);
} else {
OWSLogInfo(@"Unblocking Sleep.");
}
}
UIApplication.sharedApplication.idleTimerDisabled = shouldBeBlocking;
}
- (void)setMainAppBadgeNumber:(NSInteger)value
{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
[[NSUserDefaults sharedLokiProject] setInteger:value forKey:@"currentBadgeNumber"];
[[NSUserDefaults sharedLokiProject] synchronize];
}
- (nullable UIViewController *)frontmostViewController
{
return UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts;
}
- (nullable UIAlertAction *)openSystemSettingsAction
{
return [UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
accessibilityIdentifier:[NSString stringWithFormat:@"%@.%@", self.class, @"system_settings"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[UIApplication.sharedApplication openSystemSettings];
}];
}
- (BOOL)isRunningTests
{
return (NSProcessInfo.processInfo.environment[@"XCTestConfigurationFilePath"] != nil);
}
- (void)setNetworkActivityIndicatorVisible:(BOOL)value
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:value];
}
#pragma mark -
- (void)runNowOrWhenMainAppIsActive:(AppActiveBlock)block
{
OWSAssertDebug(block);
[Threading dispatchMainThreadSafe:^{
if (self.isMainAppAndActive) {
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
OWSBackgroundTask *_Nullable backgroundTask =
[OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
block();
OWSAssertDebug(backgroundTask);
backgroundTask = nil;
return;
}
[self.appActiveBlocks addObject:block];
}];
}
- (void)runAppActiveBlocks
{
OWSAssertIsOnMainThread();
OWSAssertDebug(self.isMainAppAndActive);
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
NSArray<AppActiveBlock> *appActiveBlocks = [self.appActiveBlocks copy];
[self.appActiveBlocks removeAllObjects];
for (AppActiveBlock block in appActiveBlocks) {
block();
}
OWSAssertDebug(backgroundTask);
backgroundTask = nil;
}
- (NSString *)appDocumentDirectoryPath
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectoryURL =
[[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
return [documentDirectoryURL path];
}
- (NSString *)appSharedDataDirectoryPath
{
NSURL *groupContainerDirectoryURL =
[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:SignalApplicationGroup];
return [groupContainerDirectoryURL path];
}
- (NSUserDefaults *)appUserDefaults
{
return [[NSUserDefaults alloc] initWithSuiteName:SignalApplicationGroup];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,248 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SignalCoreKit
import SessionUtilitiesKit
final class MainAppContext: NSObject, AppContext {
var reportedApplicationState: UIApplication.State
let appLaunchTime = Date()
let isMainApp: Bool = true
var isMainAppAndActive: Bool { UIApplication.shared.applicationState == .active }
var isShareExtension: Bool = false
var appActiveBlocks: [AppActiveBlock] = []
var mainWindow: UIWindow?
var wasWokenUpByPushNotification: Bool = false
private static var _isRTL: Bool = {
return (UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft)
}()
var isRTL: Bool { return MainAppContext._isRTL }
var statusBarHeight: CGFloat { UIApplication.shared.statusBarFrame.size.height }
var openSystemSettingsAction: UIAlertAction? {
let result = UIAlertAction(
title: "OPEN_SETTINGS_BUTTON".localized(),
style: .default
) { _ in UIApplication.shared.openSystemSettings() }
result.accessibilityIdentifier = "\(type(of: self)).system_settings"
return result
}
// MARK: - Initialization
override init() {
self.reportedApplicationState = .inactive
super.init()
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillEnterForeground(notification:)),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidEnterBackground(notification:)),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillResignActive(notification:)),
name: UIApplication.willResignActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive(notification:)),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillTerminate(notification:)),
name: UIApplication.willTerminateNotification,
object: nil
)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - Notifications
@objc private func applicationWillEnterForeground(notification: NSNotification) {
AssertIsOnMainThread()
self.reportedApplicationState = .inactive
OWSLogger.info("")
NotificationCenter.default.post(
name: .OWSApplicationWillEnterForeground,
object: nil
)
}
@objc private func applicationDidEnterBackground(notification: NSNotification) {
AssertIsOnMainThread()
self.reportedApplicationState = .background
OWSLogger.info("")
DDLog.flushLog()
NotificationCenter.default.post(
name: .OWSApplicationDidEnterBackground,
object: nil
)
}
@objc private func applicationWillResignActive(notification: NSNotification) {
AssertIsOnMainThread()
self.reportedApplicationState = .inactive
OWSLogger.info("")
DDLog.flushLog()
NotificationCenter.default.post(
name: .OWSApplicationWillResignActive,
object: nil
)
}
@objc private func applicationDidBecomeActive(notification: NSNotification) {
AssertIsOnMainThread()
self.reportedApplicationState = .active
OWSLogger.info("")
NotificationCenter.default.post(
name: .OWSApplicationDidBecomeActive,
object: nil
)
self.runAppActiveBlocks()
}
@objc private func applicationWillTerminate(notification: NSNotification) {
AssertIsOnMainThread()
OWSLogger.info("")
DDLog.flushLog()
}
// MARK: - AppContext Functions
func setStatusBarHidden(_ isHidden: Bool, animated isAnimated: Bool) {
UIApplication.shared.setStatusBarHidden(isHidden, with: (isAnimated ? .slide : .none))
}
func isAppForegroundAndActive() -> Bool {
return (reportedApplicationState == .active)
}
func isInBackground() -> Bool {
return (reportedApplicationState == .background)
}
func beginBackgroundTask(expirationHandler: @escaping BackgroundTaskExpirationHandler) -> UIBackgroundTaskIdentifier {
return UIApplication.shared.beginBackgroundTask(expirationHandler: expirationHandler)
}
func endBackgroundTask(_ backgroundTaskIdentifier: UIBackgroundTaskIdentifier) {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
}
func ensureSleepBlocking(_ shouldBeBlocking: Bool, blockingObjects: [Any]) {
if UIApplication.shared.isIdleTimerDisabled != shouldBeBlocking {
if shouldBeBlocking {
var logString: String = "Blocking sleep because of: \(String(describing: blockingObjects.first))"
if blockingObjects.count > 1 {
logString = "\(logString) (and \(blockingObjects.count - 1) others)"
}
OWSLogger.info(logString)
}
else {
OWSLogger.info("Unblocking Sleep.")
}
}
UIApplication.shared.isIdleTimerDisabled = shouldBeBlocking
}
func frontmostViewController() -> UIViewController? {
UIApplication.shared.frontmostViewControllerIgnoringAlerts
}
func setNetworkActivityIndicatorVisible(_ value: Bool) {
UIApplication.shared.isNetworkActivityIndicatorVisible = value
}
// MARK: -
func runNowOr(whenMainAppIsActive block: @escaping AppActiveBlock) {
Threading.dispatchMainThreadSafe { [weak self] in
if self?.isMainAppAndActive == true {
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
var backgroundTask: OWSBackgroundTask? = OWSBackgroundTask(label: #function)
block()
if backgroundTask != nil { backgroundTask = nil }
return
}
self?.appActiveBlocks.append(block)
}
}
func runAppActiveBlocks() {
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
var backgroundTask: OWSBackgroundTask? = OWSBackgroundTask(label: #function)
let appActiveBlocks: [AppActiveBlock] = self.appActiveBlocks
self.appActiveBlocks.removeAll()
appActiveBlocks.forEach { $0() }
if backgroundTask != nil { backgroundTask = nil }
}
func appDocumentDirectoryPath() -> String {
let targetPath: String? = FileManager.default
.urls(
for: .documentDirectory,
in: .userDomainMask
)
.last?
.path
owsAssertDebug(targetPath != nil)
return (targetPath ?? "")
}
func appSharedDataDirectoryPath() -> String {
let targetPath: String? = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: UserDefaults.applicationGroup)?
.path
owsAssertDebug(targetPath != nil)
return (targetPath ?? "")
}
func appUserDefaults() -> UserDefaults {
owsAssertDebug(UserDefaults.sharedLokiProject != nil)
return (UserDefaults.sharedLokiProject ?? UserDefaults.standard)
}
}

View File

@ -140,6 +140,7 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

View File

@ -82,7 +82,7 @@ public struct SessionApp {
)
}
/// The thread should generally exist at the time of calling this method, but on the off change it doesn't then we need to `fetchOrCreate` it and
/// The thread should generally exist at the time of calling this method, but on the off chance it doesn't then we need to `fetchOrCreate` it and
/// should do it on a background thread just in case something is keeping the DBWrite thread busy as in the past this could cause the app to hang
guard threadInfo?.threadExists == true else {
DispatchQueue.global(qos: .userInitiated).async {

View File

@ -7,54 +7,12 @@
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>File</key>
<string>Pods-GlobalDependencies-Session-settings-metadata</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<key>Key</key>
<string>name_preference</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<key>Key</key>
<string>enabled_preference</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
<string>PSChildPaneSpecifier</string>
</dict>
</array>
</dict>

View File

@ -7,4 +7,3 @@
#import "OWSBezierPathView.h"
#import "OWSMessageTimerView.h"
#import "OWSWindowManager.h"
#import "MainAppContext.h"

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "ملف مرفق";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "تعليق";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "نوع الملف: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "الحجم: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "تم بلوغ حد الرسالة";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "أرسل";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "ملف مرفق";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "خطأ في إرسال المرفق";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "غير قادر على تحويل الصوره.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "غير قادر على معالجة الفديو.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "غير قار على تحليل الصورة.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "غير قادر على حذف البيانات الوصفية من الصوره.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "غير قادر على تعديل الصورة.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "حجم المرفق عالي.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "المرفق يحتوي على بيانات غير صحيحة.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "صيغة المرفق غير صالحة.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "المرفق فارغ.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "لقد فشل اختيار الوثيقة.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "الرجاء إنشاء أرشيف مضغوط لهذا الملف أو المجلد ومحاولة إرسال ذلك بدلاً من ذلك.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "ملف غير مدعوم";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "رسالة صوتية";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "حظر";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "منع٪؜@؟";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "فتح المنع٪؜@؟";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "إلغاء الحظر";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ تم حظره";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "تم حظر المستخدم";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "تم حظر المستخدم %@.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "لن يتمكن المستخدمين المحظورين من الاتصال بك أو إرسال رسائل إليك.";
/* Label for generic done button. */
"BUTTON_DONE" = "تم";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "حدد";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "جاري البحث...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "لا يوجد تطابق";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "مطابقة واحدة";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d من %d مطابقة";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "حظر هذا المستخدم";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "اكتم المحادثة";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "بحث عن محادثة";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "تحريك وتعديل";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "قد يستغرق ذلك بضع دقائق.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "تحسين قاعدة البيانات";
/* The present; the current time. */
"DATE_NOW" = "الآن";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "الرسائل المؤقتة";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "تعديل المجموعة";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "ليس لديك أي وسائط في هذه المحادثة.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "جارٍ تحميل الوسائط الأحدث…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "جارٍ تحميل الوسائط الأقدم…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "فشل في جلب GIF. الرجاء التحقق من أنك متصل بالإنترنت.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "حدث خطأ غير معروف.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "تعذر اختيار GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "الرجاء إدخال الكلمة الأساسية للبحث.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "خطأ. اضغط لإعادة المحاولة.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "لا توجد نتائج.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "تم إنشاء المجموعة";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ انضم إلى المجموعة. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ غادر المجموعة. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "تمت إزالة %@ من المجموعة. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "تمت إزالة %@ من المجموعة. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "تم تغيير العنوان إلى '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "تم تحديث المجموعة.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "لقد غادرت المجموعة.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " تمت إزالتك من المجموعة. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "لا يمكنك مشاركة اكثر من %@ عنصر.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "فشل في تحديد المرفق.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "الملف الصوتي غير صالح.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "مغادرة";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "مغادرة المجموعة";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "جميع الوسائط";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "حذف %d رسالة";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "حذف الرسالة";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ في %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "أنت";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "هذا الشهر";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "فشل الإرسال.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "مقروءة";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "جاري الإرسال…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "مُرسل";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "يُرسل ملف…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ إلى %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "ملاحظة شخصية";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "ربما تلقيت رسائل أثناء إعادة تشغيل %@ الخاص بك.";
/* No comment provided by engineer. */
"BUTTON_OK" = "حسناً";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "عطّل %@ خاصية إختفاء الرسائل التلقائي.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ حدد وقت اختفاء الرسالة إلى %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "غير قادر على إلتقاط الصورة.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "غير قادر على إلتقاط الصورة.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "فشل في تهيئة الكاميرا.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "ألبوم بدون إسم";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "اعتبارها مقروءة";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "رد";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "يرجى المصادقة لفتح التطبيق.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "فشل التحقق";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "حذف الوسائط؟";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "تم تجاهل الوسائط";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@(الافتراضي)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "صوت الرسالة";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "لا شيء ";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ أيام";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@يوم";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ ساعات";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@ساعة";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ دقائق";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@دقيقة";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ ثواني";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@ثانية";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ يوم";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ ساعة";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ دقيقة";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ أسبوع";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ أسابيع";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@اسبوع";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "إلغاء";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "حذف";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "رسالة صوتية";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "اضغط باستمرار لتسجيل رسالة صوتية.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "رسالة صوتية";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "لقد قمت بتعطيل خاصية الرسائل المؤقتة.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "قمت بتعيين وقت اختفاء الرسالة إلى %@";
// MARK: - Session
"continue_2" = "التالي";
"copy" = "نسخ";
"invalid_url" = "عنوان URL غير صحيح";
"next" = "التالي";
"share" = "مشاركة";
"invalid_session_id" = "معرف سيشن غير صحيح";
"cancel" = "إلغاء";
"your_session_id" = "معرف سيشن الخاص بك";
"vc_landing_title_2" = "تبدأ جلستك هنا...";
"vc_landing_register_button_title" = "إنشاء معرف سيشن";
"vc_landing_restore_button_title" = "استئناف الجَلسة";
"vc_landing_link_button_title" = "ربط جهاز";
"view_fake_chat_bubble_1" = "ما (Session)؟";
"view_fake_chat_bubble_2" = "هو تطبيق مراسلة مشفر, لامركزي";
"view_fake_chat_bubble_3" = "إذن لا يجمع معلوماتي الشخصية ولا المعلومات حول محادثاتي؟ كيف يعمل؟";
"view_fake_chat_bubble_4" = "باِستخدام مدمج من تقنيات التشفير من الطرفين و توجيه مجهول المسار للمعلومات.";
"view_fake_chat_bubble_5" = "الأصدقاء لا يتركون أصدقائهم يستعملون تطبيق مراسلة مكشوف. مرحبا بك.";
"vc_register_title" = "رحب بعنوان تعريفك";
"vc_register_explanation" = "عنوان تعريفك هو عنوان وحيد خاص بك, يمكن للناس الاتصال بك عن طريقه. دون معرفة هويتك الحقيقية, هذا العنوان مصمم ليكون خاص و مجهول.";
"vc_restore_title" = "استرجع حسابك";
"vc_restore_explanation" = "أدخل عبارة الاسترجاع التي أُعطيت لك عندما سجلت الدخول لاِسترجاع حسابك.";
"vc_restore_seed_text_field_hint" = "أدخل عبارة الاسترجاع";
"vc_link_device_title" = "ربط جهاز";
"vc_link_device_scan_qr_code_tab_title" = "امسح رمز الاستجابة السريع";
"vc_display_name_title_2" = "اختر اسم العرض الخاص بك";
"vc_display_name_explanation" = "هذا سيكون اِسمك عندما تستخدم Session. قد يكون اِسمك الحقيقي, اِسم مستعار أو اي شئ آخر تريده.";
"vc_display_name_text_field_hint" = "أدخل اسم العرض";
"vc_display_name_display_name_missing_error" = "الرجاء اختيار اسم العرض";
"vc_display_name_display_name_too_long_error" = "الرجاء اختيار اسم عرض أقصر";
"vc_pn_mode_recommended_option_tag" = "مستحسن";
"vc_pn_mode_no_option_picked_modal_title" = "اِختر";
"vc_home_empty_state_message" = "ليس لديك أي جهة اتصال بعد";
"vc_home_empty_state_button_title" = "ابدأ Session";
"vc_seed_title" = "عبارة الاسترجاع الخاصة بك";
"vc_seed_title_2" = "هذه هي عبارة الاسترجاع الخاصة بك";
"vc_seed_explanation" = "عبارة الاسترجاع هي مفتاح لحسابك - يمكنك استخدامها لاسترجاع حسابك إذا فقدت الوصول لجهازك. احفظها في مكان آمن و لا تعطها أي أحد.";
"vc_seed_reveal_button_title" = "انقر مطولاً للكشف";
"view_seed_reminder_subtitle_1" = "أمّن حسابك بحفظ عبارة استرجاع الحساب";
"view_seed_reminder_subtitle_2" = "اضغط مع الاستمرار على الكلمات المخفاة للكشف عن عبارة الاسترداد الخاصة بم، ثم خزنها بأمان لحماية حسابك.";
"view_seed_reminder_subtitle_3" = "تأكد من الإحتفاظ بكلمات الإسترجاع الخاصة بك في مكان آمن";
"vc_path_title" = "مسار";
"vc_path_explanation" = "يقوم session بإخفاء عنوانIP الخاص بك بتمرير الرسائل عبر عدة خوادم في شبكة Session اللامركزية. هذه هي الدول التي يمر عبرها اتصالك:";
"vc_path_device_row_title" = "أنت";
"vc_path_guard_node_row_title" = "نقطة الدخول";
"vc_path_service_node_row_title" = "نقطة الخدمة";
"vc_path_destination_row_title" = "الوجهة";
"vc_path_learn_more_button_title" = "معرفة المزيد";
"vc_create_private_chat_title" = "رسالة جديدة";
"vc_create_private_chat_enter_session_id_tab_title" = "أدخِل عنوان التعريف";
"vc_create_private_chat_scan_qr_code_tab_title" = "امسح رمز الاستجابة السريع";
"vc_enter_public_key_explanation" = "ابدأ محادثة جديدة بإدخال معرف جلسة شخص ما أو مشاركة معرفك معهم.";
"vc_scan_qr_code_camera_access_explanation" = "تطبيق\"الجلسة\"يحتاج الوصول إلى الكاميرا لمسح رموز الاستجابة السريعة";
"vc_create_closed_group_title" = "انشئ مجموعة";
"vc_create_closed_group_text_field_hint" = "أدخل إسم المجموعة";
"vc_create_closed_group_empty_state_message" = "ليست لديك أية جهات اتصال حتى الآن";
"vc_create_closed_group_group_name_missing_error" = "الرجاء إدخال إسم للمجموعة";
"vc_create_closed_group_group_name_too_long_error" = "الرجاء إدخال إسم مجموعة أقصر";
"vc_create_closed_group_too_many_group_members_error" = "المجموعة المغلقة لا يمكن ان تحتوي على أكثر من ١٠٠ مستخدم";
"vc_join_public_chat_title" = "انضم إلى مجتمع";
"vc_join_public_chat_enter_group_url_tab_title" = "رابط المجتمع";
"vc_join_public_chat_scan_qr_code_tab_title" = "مسح رمز QR";
"vc_enter_chat_url_text_field_hint" = "أدخل رابط المجتمع";
"vc_settings_title" = "الإعدادات";
"vc_group_settings_title" = "إعدادات المجموعة";
"vc_settings_display_name_missing_error" = "الرجاء إختيار إسم العرض";
"vc_settings_display_name_too_long_error" = "الرجاء إختيار اسم عرض أقصر";
"vc_settings_privacy_button_title" = "الخصوصية";
"vc_settings_notifications_button_title" = "الإشعارات";
"vc_settings_recovery_phrase_button_title" = "عبارة الاسترجاع";
"vc_settings_clear_all_data_button_title" = "مسح البيانات";
"vc_qr_code_title" = "رمز الاستجابة السريع";
"vc_qr_code_view_my_qr_code_tab_title" = "اظهر لي\"رمز الاستجابة السريع\" الخاص بي";
"vc_qr_code_view_scan_qr_code_tab_title" = "مسح رمز QR";
"vc_qr_code_view_scan_qr_code_explanation" = "امسح رمز QR لشخص ما لبدء محادثة معهم";
"vc_view_my_qr_code_explanation" = "هذا هو رمز QR الخاص بك. يمكن للمستخدمين الآخرين فحصه لبدء جلسة معك.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "الوضع السريع";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "الوضع البطيئ";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Recovery Phrase";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Invite a Friend";
"copied" = "Copied";
"vc_conversation_settings_copy_session_id_button_title" = "Copy Session ID";
"vc_conversation_input_prompt" = "Message";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "Open";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "Unblock";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sending...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "إضافة أعضاء";
"modal_send_seed_title" = "تحذير";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "إرسل";
"vc_conversation_settings_notify_for_mentions_only_title" = "إشعار للإشارات فقط";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
"message_deleted" = "This message has been deleted";
"delete_message_for_me" = "حذف لي فقط";
"delete_message_for_everyone" = "حذف للجميع";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_reply" = "رد";
"context_menu_save" = "حفظ";
"context_menu_ban_user" = "حظر المستخدم";
"context_menu_ban_and_delete_all" = "حظر وحذف الكل";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "أضافه مرفقات";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "مستند";
"accessibility_library_button" = "مكتبة الصور";
"accessibility_camera_button" = "الكاميرا";
"accessibility_main_button_collapse" = "إغلاق خيارات المرفق";
"invalid_recovery_phrase" = "Invalid Recovery Phrase";
"DISMISS_BUTTON_TEXT" = "تجاهل";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "الإعدادات";
"call_outgoing" = "You called %@";
"call_incoming" = "%@ called you";
"call_missed" = "مكالمة فائتة من %@";
"APN_Message" = "لديك رسالة جديدة.";
"APN_Collapsed_Messages" = "لديك %@ رسائل جديدة.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Your Recovery Phrase";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Прыкладанне";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Загаловак";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Тып файла:% type%";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Памер: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Ліміт паведамленняў дасягнуты";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Адправіць";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Прыкладанне";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Памылка адпраўкі ўкладання";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Немагчыма канвертаваць малюнак.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Немагчыма апрацаваць відэа.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Немагчыма прааналізаваць малюнак.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Немагчыма выдаліць метададзеныя з малюнку.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Немагчыма змяніць памер малюнка.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Укладанне занадта вялікае.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Далучэнне змяшчае несапраўдны кантэнт.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Далучэнне мае няправільны фармат файла.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Failed to choose document.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Please create a compressed archive of this file or directory and try sending that instead.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Unsupported File";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Voice Message";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Блакаваць";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Block %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Разблакіраваць";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Карыстальнік заблакіраваны";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Заблакіраваныя карыстальнікі не змогуць тэлефанаваць вам або адпраўляць вам паведамленні.";
/* Label for generic done button. */
"BUTTON_DONE" = "Зроблена";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Выбраць";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "No matches";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 матч";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d of %d matches";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Заблакіраваць гэтага карыстальніка";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Без гуку";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Search Conversation";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Move and Scale";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimizing Database";
/* The present; the current time. */
"DATE_NOW" = "Цяпер";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Знікаючыя паведамленні";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Рэдагаваць групу";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "Вы не маеце ніякай інфармацыі ў гэтай тэме.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Загрузка новых медыя…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Загрузка старых медыя…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Не атрымалася атрымаць запытаны GIF. Упэўніцеся, што вы знаходзіцеся ў Інтэрнэце.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Адбылася невядомая памылка.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Немагчыма выбраць GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Калі ласка, увядзіце пошук.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Памылка. Націсніце, каб паўтарыць спробу.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Нічога не знойдзена.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Група створана";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Title is now '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Group updated.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "You have left the group.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from the group. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "You can't share more than %@ items.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Failed to select attachment.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Invalid audio file.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Пакінуць";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Пакінуць групу";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Усе медыя";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Выдаліць %d паведамленняў";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Выдаліць паведамленне";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ на %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "You";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "This Month";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Sending failed.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Read";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Адпраўка…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Адпраўлена";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Загрузка…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ да %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Нататка для сябе";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Заданне можа быць адноўлена з паведамленнямі пасля перазапуску.";
/* No comment provided by engineer. */
"BUTTON_OK" = "Добра";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ disabled disappearing messages.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ set disappearing message time to %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Unable to capture image.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Unable to capture image.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Failed to configure camera.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Unnamed Album";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Mark as Read";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Reply";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Authenticate to open Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Authentication Failed";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Discard Media?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Discard Media";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (default)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ days";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ hours";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutes";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ seconds";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ day";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ hour";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minute";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ week";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Cancel";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Delete";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Voice Message";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Tap and hold to record a voice message.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Voice Message";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You disabled disappearing messages.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
// MARK: - Session
"continue_2" = "Continue";
"copy" = "Copy";
"invalid_url" = "Invalid URL";
"next" = "Next";
"share" = "Share";
"invalid_session_id" = "Invalid Session ID";
"cancel" = "Cancel";
"your_session_id" = "Your Session ID";
"vc_landing_title_2" = "Your Session begins here...";
"vc_landing_register_button_title" = "Create Session ID";
"vc_landing_restore_button_title" = "Continue Your Session";
"vc_landing_link_button_title" = "Link a Device";
"view_fake_chat_bubble_1" = "What's Session?";
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
"vc_register_title" = "Say hello to your Session ID";
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"vc_restore_title" = "Restore your account";
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
"vc_restore_seed_text_field_hint" = "Enter your recovery phrase";
"vc_link_device_title" = "Link a Device";
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Code";
"vc_display_name_title_2" = "Pick your display name";
"vc_display_name_explanation" = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
"vc_display_name_text_field_hint" = "Enter a display name";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_pn_mode_recommended_option_tag" = "Recommended";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Start a Session";
"vc_seed_title" = "Your Recovery Phrase";
"vc_seed_title_2" = "Meet your recovery phrase";
"vc_seed_explanation" = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and dont give it to anyone.";
"vc_seed_reveal_button_title" = "Hold to reveal";
"view_seed_reminder_subtitle_1" = "Secure your account by saving your recovery phrase";
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"vc_path_title" = "Path";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "You";
"vc_path_guard_node_row_title" = "Entry Node";
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destination";
"vc_path_learn_more_button_title" = "Learn More";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Enter Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Settings";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
"vc_settings_privacy_button_title" = "Privacy";
"vc_settings_notifications_button_title" = "Notifications";
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
"vc_settings_clear_all_data_button_title" = "Clear Data";
"vc_qr_code_title" = "QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Code";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "Fast Mode";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "Slow Mode";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Recovery Phrase";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Invite a Friend";
"copied" = "Copied";
"vc_conversation_settings_copy_session_id_button_title" = "Copy Session ID";
"vc_conversation_input_prompt" = "Message";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "Open";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "Unblock";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sending...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "Add Members";
"modal_send_seed_title" = "Warning";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "Send";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Апавяшчэнне толькі для згадак";
"message_deleted" = "Гэта паведамленне было выдалена";
"delete_message_for_me" = "Выдаліць толькі для мяне";
"delete_message_for_everyone" = "Выдаліць для ўсіх";
"delete_message_for_me_and_recipient" = "Выдаліць для мяне і %@";
"context_menu_reply" = "Адказаць";
"context_menu_save" = "Захаваць";
"context_menu_ban_user" = "Забараніць карыстальніка";
"context_menu_ban_and_delete_all" = "Забараніць і выдаліць усе";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "Дадайце ўкладанні";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Дакумент";
"accessibility_library_button" = "Фотагалерэя";
"accessibility_camera_button" = "Камера";
"accessibility_main_button_collapse" = "Згарнуць параметры далучэння";
"invalid_recovery_phrase" = "Няправільная фраза аднаўлення";
"DISMISS_BUTTON_TEXT" = "Адхіліць";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Налады";
"call_outgoing" = "Вы патэлефанавалі";
"call_incoming" = "%@ тэлефанаваў(ла) Вам";
"call_missed" = "Missed Call from %@";
"APN_Message" = "You've got a new message.";
"APN_Collapsed_Messages" = "You've got %@ new messages.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Паведамленне";
"MESSAGE_REQUESTS_TITLE" = "Запыты паведамленняў";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Няма чаканых запытаў паведамленняў";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Ачысціць усё";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Вы ўпэўнены, што хочаце ачысціць усе запыты паведамленняў?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Ачысьціць";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Вы ўпэўнены, што жадаеце выдаліць гэты запыт на паведамленне?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Ваш запыт на паведамленне быў прыняты.";
"MESSAGE_REQUESTS_NOTIFICATION" = "У вас ёсць запыт на новае паведамленне";
"TXT_HIDE_TITLE" = "Схаваць";
"TXT_DELETE_ACCEPT" = "Прыняць";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Неабходныя дазволы на выклік";
"modal_call_permission_request_explanation" = "Вы можаце ўключыць дазвол «Галасавыя і відэазванкі» у наладах прыватнасці.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Your Recovery Phrase";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Прикачени";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Надпис";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Тип файл: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Големина:%@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Това е пределът на едно съобщение";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Изпрати";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Прикачен файл";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Грешка при прикачването на файл";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Изображението неможе да се преобразува";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Грешка при прикрепянето на видеофайла. Файлът не може да бъде конвертиран във формат MP4.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Изображението не може да бъде анализирано.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Не можахме да премахнем метаданните на файла.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Не можахме да преоразмерим изображението.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Размерът на файла е твърде голям.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Файлът съдържа невалидни или неправилни данни.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Неправилен формат на файла.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Прикаченият файл е празен. Липсват данни.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Провалено избиране на документ.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Моля, пробвайте да изпратите този файл или папка(директория) под формата на архив!";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Не се поддържа този формат";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Гласово съобщение";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Блокиране";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Блокирай%@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Разблокирай%@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Разблокиране";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@Беше блокиран.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Блокиран потребител";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@Беше разблокиран.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Блокираните потребители няма да могат да Ви изпращат съобщения, или гласови повиквания.";
/* Label for generic done button. */
"BUTTON_DONE" = "Завършено";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Избери";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Търсене...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Няма съвпадения";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 съвпадение";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%dот%d съвпадат";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Блокирай този потребител";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Заглуши";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Намери разговор";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Премести или преоразмери";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Това може да отнеме няколко минути.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Опресняване на данните";
/* The present; the current time. */
"DATE_NOW" = "Сега";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Изчезващи съобщения";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Редактирай участниците в групата";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "Вие нямате никакви файлове в този разговор.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Зареждане на скорошни файлове…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Зареждане на по-стари файлове…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Извличането на посочения GIF е неуспешно. Моля, проверете интернет връзката си.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Възникна неизвестна грешка.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Невъзможно извличане на посочения GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Моля въведете ключова дума за търсене.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Възникна грешка. Моля натиснете за повторно търсене.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Няма съвпадения.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Групата е създадена";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ се присъедини към групата. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ напусна групата. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ беше премахнат от групата. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ бяха премахнати от групата. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Името на групата е променено на '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Групата е обновена.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Вие напуснахте групата.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Вие бяхте премахнат от групата. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "Вие не можете да изберете повече от%@ елементи.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Фаилът не може да бъде прикачен.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Неподдържан формат на звуковия фаил.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Напускане";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Напускане на групата";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Виж всички файлове";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Изтрий %d съобщения";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Изтрий съобщението";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@на%@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "добави%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Ти";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Този Месец";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Изпращането е неуспешно.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Прочетено";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Изпращане…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Изпратено";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Прикачване…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@от%@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Лична бележка";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Възможно е да сте получили съобщения докато сте рестартирали вашият %@.";
/* No comment provided by engineer. */
"BUTTON_OK" = "Добре";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ е деактивирал или не поддържа изчезващи съобщения.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ настрои таймера за изчезващи съобщения на%@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Снимката не беше направена.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Възникна грешка при снимането.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Грешка в настройките на камерата.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Албум без име";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Маркирай като прочетено";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Отговори";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Идентифицирайте се за да отключите Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Възникна грешка при отключването";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Отмяна на изпращането?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Потвърдете отмяната на изпращането";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (по подразбиране)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Тон на съобщенията";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "Без звук";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@дни";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@д";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@часа";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@ч";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@минути";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@м";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@секунди";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@с";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ден";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@час";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@минута";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@седмица";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@седмици";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@сц";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Анулиране";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Изтриване";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Гласово съобщение";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Натиснете и задръжте за запис.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Задръжте по време на записването";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Вие деактивирахте изчезващите съобщения.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
// MARK: - Session
"continue_2" = "Continue";
"copy" = "Copy";
"invalid_url" = "Invalid URL";
"next" = "Next";
"share" = "Share";
"invalid_session_id" = "Invalid Session ID";
"cancel" = "Cancel";
"your_session_id" = "Your Session ID";
"vc_landing_title_2" = "Your Session begins here...";
"vc_landing_register_button_title" = "Create Session ID";
"vc_landing_restore_button_title" = "Continue Your Session";
"vc_landing_link_button_title" = "Link a Device";
"view_fake_chat_bubble_1" = "What's Session?";
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
"vc_register_title" = "Say hello to your Session ID";
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"vc_restore_title" = "Restore your account";
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
"vc_restore_seed_text_field_hint" = "Enter your recovery phrase";
"vc_link_device_title" = "Link a Device";
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Code";
"vc_display_name_title_2" = "Pick your display name";
"vc_display_name_explanation" = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
"vc_display_name_text_field_hint" = "Enter a display name";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_pn_mode_recommended_option_tag" = "Recommended";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Start a Session";
"vc_seed_title" = "Your Recovery Phrase";
"vc_seed_title_2" = "Meet your recovery phrase";
"vc_seed_explanation" = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and dont give it to anyone.";
"vc_seed_reveal_button_title" = "Hold to reveal";
"view_seed_reminder_subtitle_1" = "Secure your account by saving your recovery phrase";
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"vc_path_title" = "Path";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "Ти";
"vc_path_guard_node_row_title" = "Entry Node";
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destination";
"vc_path_learn_more_button_title" = "Научи повече";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Enter Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Settings";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
"vc_settings_privacy_button_title" = "Privacy";
"vc_settings_notifications_button_title" = "Notifications";
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
"vc_settings_clear_all_data_button_title" = "Clear Data";
"vc_qr_code_title" = "QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Code";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "Fast Mode";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "Slow Mode";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Recovery Phrase";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Покани приятел";
"copied" = "Copied";
"vc_conversation_settings_copy_session_id_button_title" = "Copy Session ID";
"vc_conversation_input_prompt" = "Message";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "Изтегляне";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "Open";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "Unblock";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Изпращане...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "Add Members";
"modal_send_seed_title" = "Warning";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "Send";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
"message_deleted" = "This message has been deleted";
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_reply" = "Reply";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
"context_menu_ban_and_delete_all" = "Ban and Delete All";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "Add attachments";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Document";
"accessibility_library_button" = "Photo library";
"accessibility_camera_button" = "Камера";
"accessibility_main_button_collapse" = "Collapse attachment options";
"invalid_recovery_phrase" = "Invalid Recovery Phrase";
"DISMISS_BUTTON_TEXT" = "Dismiss";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Settings";
"call_outgoing" = "You called %@";
"call_incoming" = "%@ called you";
"call_missed" = "Missed Call from %@";
"APN_Message" = "You've got a new message.";
"APN_Collapsed_Messages" = "You've got %@ new messages.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Your Recovery Phrase";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -1,55 +0,0 @@
#!/usr/bin/env bash
set -e
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$BIN_DIR/../../..
cd $REPO_ROOT
SSK_DIR="./SignalServiceKit/src"
SAE_DIR="./SignalShareExtension"
SM_DIR="./SignalMessaging"
SCK_DIR="../SignalCoreKit"
TARGETS="Signal/src ${SSK_DIR} ${SAE_DIR} ${SM_DIR} ${SCK_DIR}"
TMP="$(mktemp -d)"
STRINGFILE="Signal/translations/en.lproj/Localizable.strings"
# Assert preconditions before we do any work
# We're more likely to notice errors this way
for TARGET_DIR in $TARGETS
do
if [ ! -d $TARGET_DIR ]; then
echo "Unable to find required directory: ${TARGET_DIR}."
exit 1
fi
done
# Now that we've check all our pre-conditions, proceed with the work.
# Search directories for .m & .h files and collect string definitions with genstrings
find $TARGETS -name "*.m" -print0 -o -name "*.h" -print0 -o -name "*.swift" -print0 | xargs -0 genstrings -o $TMP
# We have to convert the new .strings files to UTF-8 in order to deal with them
# STRINGFILE is already UTF-8.
OLDUTF8=$(cat $STRINGFILE)
NEWUTF8=$(iconv -f UTF-16 -t UTF-8 $TMP/Localizable.strings)
# Let's merge the old with the new .strings file:
# 1. Select old string definition lines
# 2. Setup field separators
# 3. Read old string definitions as associative array
# 4. In new file, if possible, insert old definition
# 5. Add separator and semicolon only for string definition lines
# 6. Convert output back to UTF-16 to final location
echo "$OLDUTF8" | grep -Eo '^".*"' | \
awk 'BEGIN {FS = "[ ]*=[ ]*"; OFS = ""} \
NR == FNR {a[$1] = $2; next} \
{$2 = ($1 in a ? a[$1] : $2); \
if($2 ~ /"[;]*$/){$2 = " = "$2}; \
if($2 ~ /"$/){$2 = $2";"}; \
print}' - <(echo "$NEWUTF8") > $STRINGFILE

View File

@ -1,46 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $BIN_DIR/..
# Pull all translations which are at least 80% complete
tx pull -a --minimum-perc=80
# Legacy hack: pull *any existing* translations regardless of their completion.
# Once supported, we don't want to drop any translations.
tx pull --force
for dir in *.lproj
do
# en.lproj is already utf-8
if [[ "$dir" = "en.lproj" ]]; then
continue
fi
pushd $dir
# Transifex pulls utf-16, but our string linting script needs utf-8.
# Plus we can see the string diffs in GH this way.
iconv -f utf-16 -t utf-8 Localizable.strings > Localizable.strings.utf8
mv Localizable.strings.utf8 Localizable.strings
popd
done
# Get and build iStringsCheck from https://github.com/FredericJacobs/iStringsCheck
# This does some checks to make sure all strings are present and that interpolated strings have the right number of arguments
LINT_CMD=../../../l10n_lint/target/debug/l10n_lint
if [ -e $LINT_CMD ]
then
$LINT_CMD en.lproj/Localizable.strings .
else
echo "Missing string linter. See: https://github.com:WhisperSystems/l10n_lint"
exit 1
fi
echo "Make sure you register any new localizations in XCode! (Go to Project > Signal > Localizations > Add Localizations)"

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $BIN_DIR/..
tx push --source

View File

@ -1,35 +0,0 @@
#!/usr/bin/env bash
set -x
set -e
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $BIN_DIR/..
cat <<EOS
Begin Pushing translation source
################################
EOS
bin/push-translation-source
cat <<EOS
Done Pushing translation source
###############################
Begin Pulling translations
EOS
bin/pull-translations
cat <<EOS
Done Pulling translations
#########################
EOS

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "সংযুক্তি";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "ক্যাপশন";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "ফাইলের ধরণ:";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "আকার";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "বার্তা আকারের সীমায় পৌঁছে গেছেI";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "পাঠান";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "সংযুক্তি";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "সংযুক্তি প্রেরণে ত্রুটি৷";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "ছবি রূপান্তর করতে অক্ষম";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "ভিডিওগুলো লোড করতে অক্ষম";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "ছবি রূপান্তর করতে অক্ষম |";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "ছবি থেকে মেটাডেটা সরাতে অক্ষম ";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "চিত্রের আকার পরিবর্তন করতে অক্ষম৷";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "সংযুক্তি খুব বড়.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "সংযুক্তি অবৈধ বিষয়বস্তু অন্তর্ভুক্ত.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "সংযুক্তি মধ্যে একটি অবৈধ ফাইল বিন্যাস আছে.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "সংযুক্তি খালি.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "নথি চয়ন করতে ব্যর্থ হয়েছে.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "অনুগ্রহ করে এই ফাইল বা ডিরেক্টরির একটি সংকুচিত সংরক্ষণাগার তৈরি করুন এবং পরিবর্তে এটি পাঠানোর চেষ্টা করুন.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "অসমর্থিত ফাইল";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "ভয়েস বার্তা";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "ব্লক";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "ব্লক করবেন %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "%@ আনব্লক করবেন?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "আনব্লক করুন";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ ব্লক করা হয়েছে.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "ইউজার ব্লকড";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "অবরোধমুক্ত করা হয়েছে।";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "ব্লক করা ব্যবহারকারীরা আপনাকে কল করতে বা মেসেজ পাঠাতে পারবে না।";
/* Label for generic done button. */
"BUTTON_DONE" = "সম্পন্ন হয়েছে";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "নির্বাচন করুন";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "মিল নেই";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 টি মিল";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%dটি ম্যাচের মধ্যে %dটি";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "এই ব্যবহারকারীকে ব্লক করুন";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "নিঃশব্দ";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "কথোপকথন অনুসন্ধান করুন";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "সরান এবং মাপুন";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "এই কয়েক মিনিট সময় নিতে পারে.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "ডাটাবেস অপ্টিমাইজ করা হচ্ছে";
/* The present; the current time. */
"DATE_NOW" = "এখন";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "অদৃশ্য বার্তা";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "গ্রুপ সম্পাদনা করুন";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "এই কথোপকথনে আপনার কোনো মিডিয়া নেই।";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "নতুন মিডিয়া লোড হচ্ছে…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "পুরানো মিডিয়া লোড হচ্ছে…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "অনুরোধ করা GIF আনতে ব্যর্থ হয়েছে ৷ আপনি অনলাইন আছেন তা যাচাই করুন.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "একটি অজানা ত্রুটি ঘটেছে.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "GIF চয়ন করতে অক্ষম";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "আপনার অনুসন্ধান লিখুন.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "ত্রুটি. পুনরায় চেষ্টা করতে আলতো চাপুন.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "কোন ফলাফল নেই.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "গ্রুপ তৈরি হয়েছে";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "শিরোনাম এখন '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "গ্রুপ আপডেট করা হয়েছে.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "আপনি গ্রুপ থেকে চলে গেছেন.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " আপনাকে গ্রুপ থেকে বের করে দেওয়া হয়েছে. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "আপনি %@ এর বেশি আইটেম শেয়ার করতে পারবেন না.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "সংযুক্তি নির্বাচন করতে ব্যর্থ হয়েছে.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "অবৈধ অডিও ফর্ম্যাট.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "ছেড়ে যান";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "গ্রুপ পরিত্যাগ করুন";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "সমস্ত মিডিয়া";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "বার্তাগুলি %d মুছুন";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "বার্তা মুছুন";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ চালু %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "তুমি";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "এই মাসে";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "কথোপকথন অনুসন্ধান করুন.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "পড়া";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "প্রেরণ করা হচ্ছে…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "পাঠানো হয়েছে";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "আপলোড করা হচ্ছে…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ প্রতি %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "নিজেকে নোট করুন";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "আপনার %@ পুনঃসূচনা করার সময় আপনি বার্তাগুলি পেয়ে থাকতে পারেন.";
/* No comment provided by engineer. */
"BUTTON_OK" = "ঠিক আছে";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ disabled disappearing messages.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ অদৃশ্য বার্তার সময় সেট করুন %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "ইমেজ ক্যাপচার করতে অক্ষম.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "ইমেজ ক্যাপচার করতে অক্ষম.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "ক্যামেরা কনফিগার করতে ব্যর্থ হয়েছে.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "নামহীন অ্যালবাম";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "পঠিত হিসেবে চিহ্নিত করুন";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "উত্তর দিন";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "সেশন খুলতে প্রমাণীকরণ করুন.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "প্রমাণীকরণ ব্যর্থ হয়েছে";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "মিডিয়া বাতিল করবেন?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "মিডিয়া বাতিল করুন";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@(পূর্ব নির্ধারিত)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ days";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ hours";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutes";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ seconds";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ day";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ hour";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minute";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ week";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Cancel";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Delete";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Voice Message";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Tap and hold to record a voice message.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Voice Message";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You disabled disappearing messages.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
// MARK: - Session
"continue_2" = "Continue";
"copy" = "Copy";
"invalid_url" = "Invalid URL";
"next" = "Next";
"share" = "Share";
"invalid_session_id" = "Invalid Session ID";
"cancel" = "Cancel";
"your_session_id" = "Your Session ID";
"vc_landing_title_2" = "Your Session begins here...";
"vc_landing_register_button_title" = "Create Session ID";
"vc_landing_restore_button_title" = "Continue Your Session";
"vc_landing_link_button_title" = "Link a Device";
"view_fake_chat_bubble_1" = "What's Session?";
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
"vc_register_title" = "Say hello to your Session ID";
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"vc_restore_title" = "Restore your account";
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
"vc_restore_seed_text_field_hint" = "Enter your recovery phrase";
"vc_link_device_title" = "Link a Device";
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Code";
"vc_display_name_title_2" = "Pick your display name";
"vc_display_name_explanation" = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
"vc_display_name_text_field_hint" = "Enter a display name";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_pn_mode_recommended_option_tag" = "Recommended";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Start a Session";
"vc_seed_title" = "Your Recovery Phrase";
"vc_seed_title_2" = "Meet your recovery phrase";
"vc_seed_explanation" = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and dont give it to anyone.";
"vc_seed_reveal_button_title" = "Hold to reveal";
"view_seed_reminder_subtitle_1" = "Secure your account by saving your recovery phrase";
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"vc_path_title" = "Path";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "You";
"vc_path_guard_node_row_title" = "Entry Node";
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destination";
"vc_path_learn_more_button_title" = "Learn More";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Enter Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Settings";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
"vc_settings_privacy_button_title" = "Privacy";
"vc_settings_notifications_button_title" = "Notifications";
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
"vc_settings_clear_all_data_button_title" = "Clear Data";
"vc_qr_code_title" = "QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Code";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "Fast Mode";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "Slow Mode";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Recovery Phrase";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Invite a Friend";
"copied" = "Copied";
"vc_conversation_settings_copy_session_id_button_title" = "Copy Session ID";
"vc_conversation_input_prompt" = "Message";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "Open";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "Unblock";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sending...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "Add Members";
"modal_send_seed_title" = "Warning";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "Send";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
"message_deleted" = "This message has been deleted";
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_reply" = "Reply";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
"context_menu_ban_and_delete_all" = "Ban and Delete All";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "Add attachments";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Document";
"accessibility_library_button" = "Photo library";
"accessibility_camera_button" = "Camera";
"accessibility_main_button_collapse" = "Collapse attachment options";
"invalid_recovery_phrase" = "Invalid Recovery Phrase";
"DISMISS_BUTTON_TEXT" = "Dismiss";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Settings";
"call_outgoing" = "You called %@";
"call_incoming" = "%@ called you";
"call_missed" = "Missed Call from %@";
"APN_Message" = "You've got a new message.";
"APN_Collapsed_Messages" = "You've got %@ new messages.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Your Recovery Phrase";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Příloha";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Titulek";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Typ souboru: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Velikost: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Dosažen limit zprávy";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Odeslat";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Příloha";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Chyba při odesílání přílohy";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Obrázek nelze překonvertovat.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Video nelze zpracovat.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Obrázek nelze zpracovat.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Nelze odstranit metadata z obrázku.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Nelze změnit velikost obrázku.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Příloha je příliš velká.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Příloha obsahuje neplatný obsah.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Příloha má neplatný formát souboru.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Příloha je prázdná.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Nepovedlo se vybrat dokument.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Vytvořte prosím komprimovaný archiv tohoto souboru nebo adresáře a zkuste jej namísto toho odeslat.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Nepodporovaný soubor";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Hlasová zpráva";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Zablokovat";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Zablokovat %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Odblokovat %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Odblokovat";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ byl/a zablokován/a.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Uživatel zablokován";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ byl/a odblokován/a.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokovaní uživatelé vám nebudou moci volat ani vám posílat zprávy.";
/* Label for generic done button. */
"BUTTON_DONE" = "Hotovo";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Vybrat";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Vyhledávání...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Žádné shody";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 shoda";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d z %d shod";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Blokovat tohoto uživatele";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Ztlumit";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Vyhledat konverzaci";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Přesun a měřítko";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Může to trvat několik minut.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimalizace databáze";
/* The present; the current time. */
"DATE_NOW" = "Teď";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Mizející zprávy";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Upravit skupinu";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "V této konverzaci nemáte žádná média.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Načítání novějších médií…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Načítání starších médií…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Nepodařilo se načíst požadovaný GIF. Zkontrolujte připojení k internetu.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Došlo k neznámé chybě.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Nelze vybrat GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Zadejte své vyhledávání.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Chyba. Klepněte pro opakování.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Žádné výsledky.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Skupina vytvořena";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ se připojil/a ke skupině. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ opustil/a skupinu. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ byl/a odebrán/a ze skupiny. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ byli odebráni ze skupiny. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Název je nyní %@. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Skupina aktualizována.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Opustil/a jste skupinu.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Byli jste odebráni ze skupiny. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "Nemůžete sdílet více než %@ položek.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Nepodařilo se vybrat přílohu.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Neplatný zvukový soubor.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Opustit";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Opustit skupinu";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Všechna média";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Smazat %d zpráv";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Smazat zprávu";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ v %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Vy";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Tento měsíc";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Odeslání selhalo.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Přečteno";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Odesílání…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Odesláno";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Nahrávání…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ do %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Poznámka pro mně";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Možná jste obdrželi zprávy během restartování aplikace %@.";
/* No comment provided by engineer. */
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Uživatel %@ zakázal mizející zprávy.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ nastavil čas pro zmizení zpráv na %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Nelze pořídit obrázek.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Nelze pořídit obrázek.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Konfigurace kamery selhala.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Nepojmenované album";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Označit jako přečtené";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Odpověděť";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Ověření pro otevření Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Ověření se nezdařilo";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Zahodit média?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Zahodit média";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (výchozí)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Zvuk zprávy";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "Žádný";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ dní";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ h";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ min";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@min";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ s";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ dní";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ hodina";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minuta";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ týden";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ týdny";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@td";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Zrušit";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Smazat";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Hlasová zpráva";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Klepněte a podržte pro nahrání hlasové zprávy.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Hlasová zpráva";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Zakázali jste mizející zprávy.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Nastavil jste čas pro zmizení zpráv na %@";
// MARK: - Session
"continue_2" = "Pokračovat";
"copy" = "Kopírovat";
"invalid_url" = "Neplatná URL adresa";
"next" = "Další";
"share" = "Sdílet";
"invalid_session_id" = "Neplatná ID relace";
"cancel" = "Zrušit";
"your_session_id" = "Vaše ID relace";
"vc_landing_title_2" = "Vaše relace začíná zde...";
"vc_landing_register_button_title" = "Vytvořit ID relaci";
"vc_landing_restore_button_title" = "Pokračujte v relaci";
"vc_landing_link_button_title" = "Propojit zařízení";
"view_fake_chat_bubble_1" = "Co je Session?";
"view_fake_chat_bubble_2" = "Je to decentralizovaná, šifrovaná aplikace pro zasílání zpráv";
"view_fake_chat_bubble_3" = "Takže neshromažďuje mé osobní údaje ani metadata konverzace? Jak to funguje?";
"view_fake_chat_bubble_4" = "Použitím kombinace pokročilých anonymních směrovacích a end-to-end šifrovacích technologií.";
"view_fake_chat_bubble_5" = "Přátelé nenechávají přátelé používat kompromitované messengery. Není zač.";
"vc_register_title" = "Seznamte se se svým ID relace";
"vc_register_explanation" = "Vaše Session ID je jedinečná adresa, kterou mohou lidé použít ke kontaktu s vámi na Session. Vaše Session ID není nijak spojeno s vaší skutečnou identitou a je zcela anonymní a soukromé.";
"vc_restore_title" = "Obnovit účet";
"vc_restore_explanation" = "Zadejte frázi pro obnovení, která vám byla vygenerována během registrace účtu.";
"vc_restore_seed_text_field_hint" = "Zadejte frázi pro obnovení";
"vc_link_device_title" = "Propojit zařízení";
"vc_link_device_scan_qr_code_tab_title" = "Skenovat QR kód";
"vc_display_name_title_2" = "Vaše jméno";
"vc_display_name_explanation" = "Toto bude váš pseudonym během používání Session. Může to být vaše skutečné jméno, alias, nebo cokoliv jiného, co se vám líbí.";
"vc_display_name_text_field_hint" = "Zadejte zobrazované jméno";
"vc_display_name_display_name_missing_error" = "Zadejte prosím zobrazované jméno";
"vc_display_name_display_name_too_long_error" = "Vyberte prosím kratší zobrazované jméno";
"vc_pn_mode_recommended_option_tag" = "Doporučeno";
"vc_pn_mode_no_option_picked_modal_title" = "Vyberte si prosím jednu z možností";
"vc_home_empty_state_message" = "Zatím nemáte žádné kontakty";
"vc_home_empty_state_button_title" = "Zahájit relaci";
"vc_seed_title" = "Vaše fráze pro obnovení";
"vc_seed_title_2" = "Zadejte frázi pro obnovení";
"vc_seed_explanation" = "Vaše fráze pro obnovení je hlavním klíčem k vašemu Session ID- můžete ji použít k obnovení vašeho Session ID, pokud ztratíte přístup k zařízení. Uložte frázi pro obnovení na bezpečném místě a nikomu ji nesdělujte.";
"vc_seed_reveal_button_title" = "Podržte pro zobrazení";
"view_seed_reminder_subtitle_1" = "Zabezpečte svůj účet uložením fráze pro obnovení";
"view_seed_reminder_subtitle_2" = "Klepnutím a podržením redigovaných slov zobrazte frázi pro obnovení a poté ji bezpečně uložte, abyste zabezpečili vaše Session ID.";
"view_seed_reminder_subtitle_3" = "Ujistěte se, že jste frázi pro obnovení uložili na bezpečném místě";
"vc_path_title" = "Cesta";
"vc_path_explanation" = "Session skrývá vaši IP adresu tím, že směruje vaše zprávy přes několik provozních uzlů v decentralizované síti Session. Toto jsou země, přes které je vaše připojení aktuálně směrováno:";
"vc_path_device_row_title" = "Vy";
"vc_path_guard_node_row_title" = "Vstupní uzel";
"vc_path_service_node_row_title" = "Provozní uzel";
"vc_path_destination_row_title" = "Cíl";
"vc_path_learn_more_button_title" = "Zjistit více";
"vc_create_private_chat_title" = "Nová zpráva";
"vc_create_private_chat_enter_session_id_tab_title" = "Zadejte Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Načíst QR kód";
"vc_enter_public_key_explanation" = "Začněte novou konverzaci zadáním Session ID jiného uživatele a nebo sdílejte své Session ID s ostatními.";
"vc_scan_qr_code_camera_access_explanation" = "Session potřebuje ke skenování kódů QR přístup k fotoaparátu";
"vc_create_closed_group_title" = "Vytvořit skupinu";
"vc_create_closed_group_text_field_hint" = "Zadejte název skupiny";
"vc_create_closed_group_empty_state_message" = "Zatím nemáte žádné kontakty";
"vc_create_closed_group_group_name_missing_error" = "Zadejte prosím název skupiny";
"vc_create_closed_group_group_name_too_long_error" = "Zadejte prosím kratší název skupiny";
"vc_create_closed_group_too_many_group_members_error" = "Uzavřená skupina nemůže mít více než 100 členů";
"vc_join_public_chat_title" = "Připojit se ke komunitě";
"vc_join_public_chat_enter_group_url_tab_title" = "Adresa komunity";
"vc_join_public_chat_scan_qr_code_tab_title" = "Načíst QR kód";
"vc_enter_chat_url_text_field_hint" = "Zadejte adresu komunity";
"vc_settings_title" = "Nastavení";
"vc_group_settings_title" = "Nastavení skupiny";
"vc_settings_display_name_missing_error" = "Zadejte prosím zobrazované jméno";
"vc_settings_display_name_too_long_error" = "Zadejte prosím kratší zobrazované jméno";
"vc_settings_privacy_button_title" = "Soukromí";
"vc_settings_notifications_button_title" = "Oznámení";
"vc_settings_recovery_phrase_button_title" = "Fráze pro obnovení";
"vc_settings_clear_all_data_button_title" = "Vymazat data";
"vc_qr_code_title" = "QR kód";
"vc_qr_code_view_my_qr_code_tab_title" = "Zobrazit můj QR kód";
"vc_qr_code_view_scan_qr_code_tab_title" = "Naskenovat QR kód";
"vc_qr_code_view_scan_qr_code_explanation" = "Naskenujte něčí QR kód a začněte s nimi konverzaci";
"vc_view_my_qr_code_explanation" = "Toto je váš QR kód. Ostatní uživatelé jej mohou naskenovat, aby s vámi mohli začít konverzaci.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Budete informováni o nových zprávách spolehlivě a okamžitě pomocí oznamovacích serverů společnosti Apple.";
"fast_mode" = "Rychlý režim";
"slow_mode_explanation" = "Session občas zkontroluje nové zprávy na pozadí.";
"slow_mode" = "Pomalý režim";
"vc_pn_mode_title" = "Oznámení zprávy";
"vc_link_device_recovery_phrase_tab_title" = "Fráze pro obnovení";
"vc_link_device_scan_qr_code_explanation" = "Přejděte do Nastavení → Fráze pro obnovení na Vašem dalším zařízení a pro zobrazení QR kódu.";
"vc_enter_recovery_phrase_title" = "Fráze pro obnovení";
"vc_enter_recovery_phrase_explanation" = "Pro propojení vašeho zařízení zadejte frázi pro obnovení, která vám byla přidělena při registraci.";
"vc_enter_public_key_text_field_hint" = "Zadejte Session ID nebo název ONS";
"admin_group_leave_warning" = "Protože jste tvůrcem této skupiny, bude smazána pro všechny. Tuto akci nelze vrátit zpět.";
"vc_join_open_group_suggestions_title" = "Nebo se připojte k jedné z těchto...";
"vc_settings_invite_a_friend_button_title" = "Pozvat přítele";
"copied" = "Zkopírováno";
"vc_conversation_settings_copy_session_id_button_title" = "Kopírovat Session ID";
"vc_conversation_input_prompt" = "Zpráva";
"vc_conversation_voice_message_cancel_message" = "Pro zrušení přejeďte";
"modal_download_attachment_title" = "Důvěřovat %@?";
"modal_download_attachment_explanation" = "Opravdu chcete stáhnout přílohu od %@?";
"modal_download_button_title" = "Stáhnout";
"modal_open_url_title" = "Otevřít odkaz?";
"modal_open_url_explanation" = "Opravdu chcete otevřít %@?";
"modal_open_url_button_title" = "Otevřít";
"modal_copy_url_button_title" = "Kopírovat odkaz";
"modal_blocked_title" = "Odblokovat %@?";
"modal_blocked_explanation" = "Opravdu chcete odblokovat %@?";
"modal_blocked_button_title" = "Odblokovat";
"modal_link_previews_title" = "Umožnit náhledy odkazů?";
"modal_link_previews_explanation" = "Povolením náhledů odkazů budou zobrazeny náhledy URL adres, které odesíláte a přijímáte. To může být užitečné, ale Session se bude muset spojit s danou webovou stránkou pro generování náhledů. Náhled odkazů můžete kdykoli zakázat v nastavení Session.";
"modal_link_previews_button_title" = "Povolit";
"vc_share_title" = "Sdílet na Session";
"vc_share_loading_message" = "Připravování příloh...";
"vc_share_sending_message" = "Odesílání...";
"vc_share_link_previews_unsecure" = "Náhled nebyl načten pro nezabezpečený odkaz";
"vc_share_link_previews_error" = "Nelze načíst náhled";
"vc_share_link_previews_disabled_title" = "Náhledy odkazů vypnuty";
"vc_share_link_previews_disabled_explanation" = "Povolením náhledů odkazů se zobrazí náhledy sdílených adres URL. To může být užitečné, ale Session bude muset kontaktovat propojené webové stránky, aby vygenerovala náhledy.\n\nNáhledy odkazů můžete povolit v nastavení Session.";
"view_open_group_invitation_description" = "Otevřít pozvánku ke skupině";
"vc_conversation_settings_invite_button_title" = "Přidat členy";
"modal_send_seed_title" = "Varování";
"modal_send_seed_explanation" = "Toto je vaše obnovovací fráze. Pokud ji někomu pošlete, bude mít plný přístup k vašemu účtu.";
"modal_send_seed_send_button_title" = "Odeslat";
"vc_conversation_settings_notify_for_mentions_only_title" = "Upozorňovat pouze na zmínky";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Pokud je povoleno, budete upozorněni pouze na zprávy, které vás zmiňují.";
"view_conversation_title_notify_for_mentions_only" = "Upozorňování pouze na zmínky";
"message_deleted" = "Tato zpráva byla odstraněna";
"delete_message_for_me" = "Smazat pouze pro mě";
"delete_message_for_everyone" = "Smazat pro všechny";
"delete_message_for_me_and_recipient" = "Odstranit pro mě a %@";
"context_menu_reply" = "Odpověděť";
"context_menu_save" = "Uložit";
"context_menu_ban_user" = "Zablokovat uživatele";
"context_menu_ban_and_delete_all" = "Zablokovat a odstranit vše";
"context_menu_ban_user_error_alert_message" = "Nelze zablokovat uživatele";
"accessibility_expanding_attachments_button" = "Přidat přílohy";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Dokument";
"accessibility_library_button" = "Knihovna fotografií";
"accessibility_camera_button" = "Fotoaparát";
"accessibility_main_button_collapse" = "Sbalit možnosti přílohy";
"invalid_recovery_phrase" = "Neplatná fráze pro obnovení";
"DISMISS_BUTTON_TEXT" = "Odmítnout";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Nastavení";
"call_outgoing" = "Volal jste %@";
"call_incoming" = "%@ vám volal";
"call_missed" = "Zmeškaný hovor od %@";
"APN_Message" = "Máte novou zprávu.";
"APN_Collapsed_Messages" = "Máte %@ nových zpráv.";
"PIN_BUTTON_TEXT" = "Připnout";
"UNPIN_BUTTON_TEXT" = "Odepnout";
"modal_call_missed_tips_title" = "Zmeškaný hovor";
"modal_call_missed_tips_explanation" = "Zmeškaný hovor od \"%@\", protože musíte povolit oprávnění \"Hlasové a video hovory\" v nastavení soukromí.";
"media_saved" = "Uživatel %@ uložil média.";
"screenshot_taken" = "Uživatel %@ pořídil snímek obrazovky.";
"SEARCH_SECTION_CONTACTS" = "Kontakty a skupiny";
"SEARCH_SECTION_MESSAGES" = "Zprávy";
"MESSAGE_REQUESTS_TITLE" = "Žádosti o zprávy";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Žádné nevyřízené žádosti o zprávu";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Smazat vše";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Jste si jisti, že chcete vymazat všechny žádosti o zprávy?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Smazat";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Jste si jisti, že chcete odstranit tuto žádost o zprávu?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Opravdu chcete zablokovat tento kontakt?";
"MESSAGE_REQUESTS_INFO" = "Odesláním zprávy tomuto uživateli automaticky přijmete jejich požadavek na zprávu a odhalíte jim své Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Máte novou žádost o zprávu";
"TXT_HIDE_TITLE" = "Skrýt";
"TXT_DELETE_ACCEPT" = "Přijmout";
"TXT_BLOCK_USER_TITLE" = "Blokovat uživatele";
"ALERT_ERROR_TITLE" = "Chyba";
"modal_call_permission_request_title" = "Požadovaná oprávnění k volání";
"modal_call_permission_request_explanation" = "Oprávnění pro hlasové a video hovory můžete povolit v Nastavení soukromí.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Jejda, došlo k chybě";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Zkuste to prosím znovu později";
"LOADING_CONVERSATIONS" = "Načítání konverzací...";
"DATABASE_MIGRATION_FAILED" = "Při optimalizaci databáze došlo k chybě\n\nProtokoly aplikací můžete exportovat, abyste je mohli sdílet při řešení problémů, nebo můžete zařízení obnovit.\n\nVarování: Obnovení zařízení povede ke ztrátě všech dat starších než dva týdny";
"RECOVERY_PHASE_ERROR_GENERIC" = "Něco se pokazilo. Zkontrolujte prosím frázi pro obnovení a zkuste to znovu.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Vypadá to, že jste nezadali dostatek slov. Zkontrolujte prosím svou frázi pro obnovení a zkuste to znovu.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Zdá se, že vám chybí poslední slovo k frázi pro obnovení. Zkontrolujte, co jste zadali a zkuste to znovu.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Zdá se, že ve vaší frázi pro obnovení je neplatné slovo. Zkontrolujte, co jste zadali, a zkuste to znovu.";
"RECOVERY_PHASE_ERROR_FAILED" = "Vaši frázi pro obnovení se nepodařilo ověřit. Zkontrolujte, co jste zadali a zkuste to znovu.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "K ověření nebylo možné přistoupit.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Ověření se nezdařilo.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Příliš mnoho neúspěšných pokusů o ověření. Zkuste to prosím později.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Chcete-li používat zámek obrazovky, musíte v nastavení iOS povolit přístupový kód.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Chcete-li používat zámek obrazovky, musíte v nastavení iOS povolit přístupový kód.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Chcete-li používat zámek obrazovky, musíte v nastavení iOS povolit přístupový kód.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Odeslat";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Opakovat";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Zobrazit chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Zprávu se nepodařilo odeslat.";
"INVALID_SESSION_ID_MESSAGE" = "Zkontrolujte prosím Session ID a zkuste to znovu.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Zkontrolujte prosím frázi pro obnovení a zkuste to znovu.";
"MEDIA_TAB_TITLE" = "Média";
"DOCUMENT_TAB_TITLE" = "Dokumenty";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "V této konverzaci nemáte žádný dokument.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Načítání novějšího dokumentu…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Načítání staršího dokumentu…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Aktivity";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Zvířata a příroda";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Vlajky";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Jídlo a pití";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Předměty";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Naposledy použité";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smajlíci a lidé";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symboly";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Cestování a místa";
"EMOJI_REACTS_NOTIFICATION" = "%@ reaguje na zprávu s %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "A 1 další reagoval s %@ na tuto zprávu.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "A %@ další reagovali s %@ na tuto zprávu.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Zpomalte! Poslali jste příliš mnoho emoji reakcí. Zkuste to za chvilku.";
/* New conversation screen*/
"vc_new_conversation_title" = "Nová konverzace";
"CREATE_GROUP_BUTTON_TITLE" = "Vytvořit";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Připojit se k";
"PRIVACY_TITLE" = "Soukromí";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Zabezpečení obrazovky";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Zamknout Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Požaduje Touch ID, Face ID nebo kód pro odemčení Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Potvrzení o přečtení";
"PRIVACY_READ_RECEIPTS_TITLE" = "Potvrzení o přečtení";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Odeslat potvrzení o přečtení při konverzaci s jedním uživatelem.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indikátory psaní";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indikátory psaní";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Zobrazit a sdílet indikátor psaní v konverzaci s jedním uživatelem.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Náhledy odkazů";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Odesílat náhledy odkazů";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Vytvářet náhledy odkazů pro podporované URL adresy.";
"PRIVACY_SECTION_CALLS" = "Volání (Beta)";
"PRIVACY_CALLS_TITLE" = "Hlasové hovory a videohovory";
"PRIVACY_CALLS_DESCRIPTION" = "Zapne hlasové a video hovory k ostatním uživatelům i od nich.";
"PRIVACY_CALLS_WARNING_TITLE" = "Hlasové a video hovory (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Vaše IP adresa je při používání beta hovorů viditelná pro toho s kým si voláte i pro Oxen Foundation server. Jste si jisti, že chcete povolit hlasové a video hovory?";
"NOTIFICATIONS_TITLE" = "Upozornění";
"NOTIFICATIONS_SECTION_STRATEGY" = "Styl oznámení";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Použít rychlý režim";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Budete informováni o nových zprávách spolehlivě a okamžitě pomocí oznamovacích serverů společnosti Apple.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Přejít do nastavení upozornění pro toto zařízení";
"NOTIFICATIONS_SECTION_STYLE" = "Styl upozornění";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Zvuk";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Zvuk při otevření aplikace";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Obsah oznámení";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Informace uvedené v oznámeních.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Jméno a obsah";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Pouze jméno";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Ani jméno ani zprávu";
"CONVERSATION_SETTINGS_TITLE" = "Konverzace";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Pročištění zpráv";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Pročištění komunit";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Z komunit vymazat zprávy starší než 6 měsíců a ponechat maximálně 2000 nejnovějších zpráv v každé komunitě.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Zvukové zprávy";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Automaticky přehrát zvukové zprávy";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Automaticky přehrát po sobě následující zvukové zprávy.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blokované kontakty";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Nemáte žádné blokované kontakty.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Odblokovat";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Opravdu chcete odblokovat %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "tento kontakt";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Opravdu si přejete odblokovat %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "a %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "a %d dalších?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Odblokovat";
"APPEARANCE_TITLE" = "Vzhled";
"APPEARANCE_THEMES_TITLE" = "Motivy";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Výchozí barva";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Jak se máte?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Dobře, jak vy?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Skvěle, děkuji.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Automatický noční režim";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Použít nastavení systému";
"HELP_TITLE" = "Nápověda";
"HELP_REPORT_BUG_TITLE" = "Nahlásit chybu";
"HELP_REPORT_BUG_DESCRIPTION" = "Exportujte své logy, pak nahrajte soubor přes portál podpory Session.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Exportovat logy";
"HELP_TRANSLATE_TITLE" = "Přeložit Session";
"HELP_FEEDBACK_TITLE" = "Chtěli bychom znát váš názor";
"HELP_FAQ_TITLE" = "Časté dotazy";
"HELP_SUPPORT_TITLE" = "Podpora";
"modal_clear_all_data_title" = "Smazat všechny data";
"modal_clear_all_data_explanation" = "Tímto trvale smažete vaše zprávy a kontakty. Chcete vymazat data pouze na tomto zařízení, nebo odstranit také data ze sítě?";
"modal_clear_all_data_explanation_2" = "Jste si jisti, že chcete odstranit svá data ze sítě? Pokud budete pokračovat, nebudete moci obnovit své zprávy nebo kontakty.";
"modal_clear_all_data_device_only_button_title" = "Vymazat pouze data na zařízení";
"modal_clear_all_data_entire_account_button_title" = "Vymazat data na zařízení i na síti";
"dialog_clear_all_data_deletion_failed_1" = "Data nebyly smazány jedním provozním uzlem. ID provozního uzlu: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data nebyla odstraněna %@ provozními uzly. ID provozních uzlů: %@.";
"modal_clear_all_data_confirm" = "Vymazat";
"modal_seed_title" = "Vaše fráze pro obnovení";
"modal_seed_explanation" = "Obnovovací frázi můžete použít pro obnovení účtu nebo propojení zařízení.";
"modal_permission_explanation" = "Session potřebuje %@ přístup pro pokračování. Právo přístupu můžete zapnout v nastavení iOS.";
"modal_permission_settings_title" = "Nastavení";
"modal_permission_camera" = "kamera";
"modal_permission_microphone" = "mikrofon";
"modal_permission_library" = "knihovna";
"DISAPPEARING_MESSAGES_OFF" = "Vypnuto";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Vypnuto";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Zmizí po: %@";
"COPY_GROUP_URL" = "Kopírovat adresu skupiny";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakty";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Vyberte prosím alespoň jednoho člena skupiny";
"GROUP_CREATION_PLEASE_WAIT" = "Počkejte prosím, než se skupina vytvoří...";
"GROUP_CREATION_ERROR_TITLE" = "Vytvoření skupiny se nezdařilo";
"GROUP_CREATION_ERROR_MESSAGE" = "Zkontrolujte své připojení k Internetu a zkuste to znovu.";
"GROUP_UPDATE_ERROR_TITLE" = "Aktualizace skupiny se nezdařila";
"GROUP_UPDATE_ERROR_MESSAGE" = "Nelze odejít při přidávání nebo odebírání dalších členů.";
"GROUP_ACTION_REMOVE" = "Odstranit";
"GROUP_TITLE_MEMBERS" = "Členové";
"GROUP_TITLE_FALLBACK" = "Skupina";
"DM_ERROR_DIRECT_BLINDED_ID" = "Zprávy můžete posílat pouze na skryté ID v rámci komunity";
"DM_ERROR_INVALID" = "Zkontrolujte prosím své Session ID nebo název ONS a zkuste to znovu";
"COMMUNITY_ERROR_INVALID_URL" = "Zkontrolujte prosím zadanou URL a zkuste to znovu.";
"COMMUNITY_ERROR_GENERIC" = "Nelze se připojit";
"DISAPPERING_MESSAGES_TITLE" = "Mizející zprávy";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Odstranit typ";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Zmizet po přečtení";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Zprávy se po přečtení smažou.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Zmizet po odeslání";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Zprávy se po odeslání smažou.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Časovač";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Nastavit";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Toto nastavení se týká všech účastníků této konverzace.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Toto nastavení se týká všech účastníků této konverzace. Toto nastavení mohou změnit pouze správci skupiny.";
"DISAPPERING_MESSAGES_SUMMARY" = "Zmizí po: %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ nastavil/a zprávy tak, aby zmizely %@ poté, co byly %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ změnil/a zprávy tak, aby zmizely %@ poté, co byly %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ vypnul/a mizející zprávy";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "Při otevření databáze došlo k chybě\n\nProtokoly aplikací můžete exportovat, abyste je mohli sdílet při řešení problémů, nebo můžete zařízení obnovit.\n\nVarování: Obnovení zařízení povede ke ztrátě všech dat starších než dva týdny";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "Spouštění aplikace trvá dlouho\n\nMůžete pokračovat v čekání na spuštění aplikace, exportovat protokoly aplikace a sdílet je pro řešení problémů nebo můžete zkusit aplikaci otevřít znovu";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Ukončit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "Při otevírání obnovené databáze došlo k chybě\n\nProtokoly aplikace můžete exportovat do sdílené složky za účelem řešení problémů, ale abyste mohli relaci Session používat i nadále, bude možná nutné ji znovu nainstalovat";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Původní zpráva nebyla nalezena.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Zobrazit méně";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Žádosti o zprávy";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Požadavky na zprávy komunity";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Povolit požadavky na zprávy z konverzací komunity.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "Budete moci posílat hlasové zprávy a přílohy, jakmile příjemce schválí tuto žádost o zprávu";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Odesílání";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Odesláno";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Přečteno";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Odeslání se nezdařilo";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Odesláno";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Přijato";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "Od";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "ID souboru";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "Typ souboru";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "Velikost souboru";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Rozlišení";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Doba trvání";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Synchronizace se nezdařila";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Synchronizace";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Odeslání zprávy se nezdařilo";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Nepodařilo se synchronizovat zprávu s ostatními zařízeními";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Smazat ze všech mých zařízení";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Odeslat znovu";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Znovu synchronizovat";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Hledat GIFy?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session se připojí k Giphy pro poskytnutí výsledků vyhledávání. Při odesílání GIFů nebudete mít úplnou ochranu metadat.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Informace o zprávě";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Ztlumit";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Zrušit ztlumení";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Označit jako přečtené";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Označit jako nepřečtené";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Opustit skupinu";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Opustit komunitu";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Opravdu chcete opustit %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Opouštění...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Nepodařilo se opustit skupinu!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Nelze opustit skupinu, zkuste to prosím znovu";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Smazat skupinu";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Opravdu chcete smazat %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Smazat konverzaci";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Opravdu chcete smazat konverzaci s %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Skrýt Poznámku pro mně";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Opravdu chcete skrýt %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Nastavit zobrazovaný obrázek";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Uložit";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Odstranit";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Nelze odstranit obrázek avataru";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Překročena maximální velikost souboru";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Vyberte prosím menší fotografii a zkuste to znovu";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Nepodařilo se aktualizovat profil";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Zkontrolujte prosím připojení k internetu a zkuste to znovu";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Zadejte jméno";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Nepřečtené zprávy";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "Nemáte žádné zprávy od %@. Pošlete zprávu pro zahájení konverzace!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "V %@ nejsou žádné zprávy.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "V %@ nemáte žádné zprávy.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ má vypnuté žádosti o chat pocházející z komunit. Odeslání zprávy tedy není možné.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Některá z vašich zařízení používají zastaralé verze. Synchronizace může být nespolehlivá, dokud nebudou aktualizovány.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "Došlo k chybě při pokusu o načtení hesla pro obnovení.\n\nPro vyřešení problému prosím exportujte své logy a soubor nahrajte pomocí Session Help Desku.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "Došlo k chybě při ukládání odchozí zprávy pro odesílání, možná budete muset restartovat aplikaci, než budete moci odesílat zprávy.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "Při otevírání databáze se vyskytl problém. Prosím, restartujte aplikaci a zkuste to znovu.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "Toto nastavení se týká všech účastníků této konverzace.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Zprávy zmizí po odeslání.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "Nastavili jste mizení zpráv %@ po odeslání %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "Nastavili jste mizení zpráv %@ po jejich %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "Zakázali jste mizející zprávy";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Zastaralé";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Původní verze mizejících zpráv.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ používá zastaralého klienta. Mizející zprávy nemusí fungovat podle očekávání.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "Pokoušíte se aktualizovat z verze, která již nepodporuje aktualizaci\n\nChcete-li nadále používat Session, je potřeba obnovit zařízení\n\nVarování: Obnovení zařízení bude mít za následek ztrátu jakýchkoli dat starších než dva týdny";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "přečteno";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "odesláno";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Vedhæftning";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Billedtekst";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Filtype: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Filstørrelse: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Beskedgrænse nået";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Send";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Vedhæftning";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Fejl ved afsendelse af vedhæftning";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Kan ikke omkonvertere billede.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Kunne ikke behandle videofilen.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Kunne ikke analysere billedet.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Kunne ikke fjerne metadata fra billedet.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Kunne ikke ændre billedstørrelsen.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Vedhæftede fil er for stor.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Vedhæftning indeholder ugyldigt indhold.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Vedhæftning har et ugyldigt filformat.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Vedhæftning er tom.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Valg af dokument mislykkedes.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Opret venligst et komprimeret arkiv af denne fil eller mappe og prøv at sende den i stedet.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Filtypen er ikke understøttet";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Talebesked";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Bloker";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Bloker %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Fjern blokering af %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Fjern blokering";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ er blevet blokeret.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Bruger Blokeret";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Blokering af %@ er blevet fjernet.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokerede brugere vil ikke kunne ringe eller sende beskeder til dig.";
/* Label for generic done button. */
"BUTTON_DONE" = "Færdig";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Vælg";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Ingen matches";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 match";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d ud af %d matches";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Bloker Denne Bruger";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Ignorer";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Søg I Beskeder";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Flyt og Skalere";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Dette kan tage nogle minutter.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimerer Database";
/* The present; the current time. */
"DATE_NOW" = "Nu";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Forsvindende Beskeder";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Rediger Gruppe";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "Du har ingen medier i denne samtale.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Indlæser Nyere Medier…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Indlæser Ældre Medier…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Kunne ikke hente den ønskede GIF. Kontroller venligst at du er online.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Der opstod en ukendt fejl.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Kunne Ikke Vælge GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Indtast venligst din søgning.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Fejl. Tryk for at prøve igen.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Ingen Resultater.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Gruppe oprettet";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Titlen er nu '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Gruppe opdateret.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Du har forladt gruppen.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Du blev fjernet fra gruppen. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "Du kan ikke dele mere end %@ emner.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Den vedhæftede fil kunne ikke indlæses.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Ugyldig lydfil.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Forlad";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Forlad Gruppe";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Alle medier";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Slet %d Beskeder";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Slet Besked";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ på %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Dig";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Denne Måned";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Afsendelse mislykkedes.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Læst";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Sender…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Sendt";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Uploader…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ til %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Egen Note";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Du har kan modtaget beskeder, mens din %@ genstartede.";
/* No comment provided by engineer. */
"BUTTON_OK" = "Ok";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ deaktiverede forsvindende beskeder.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ indstillede udløbstid for forsvindende beskeder til %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Kunne ikke tage billede.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Kunne ikke tage billede.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Konfigurering af kamera mislykkedes.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Unavngivet Album";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Marker som læst";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Svar";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Godkend for at åbne session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Godkendelse mislykkedes";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Kassér Medie?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Kassér Medie";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (standard)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Besked Lyd";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "Ingen";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ dage";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ timer";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@t";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutter";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ sekunder";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ dag";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ time";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minut";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ uge";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ uger";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Afbryd";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Slet";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Talebesked";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Tryk og hold for at optage en talebesked.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Talebesked";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Du deaktiverede forsvindende beskeder.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Du indstillede udløbstid for forsvindende beskeder til %@";
// MARK: - Session
"continue_2" = "Fortsæt";
"copy" = "Kopier";
"invalid_url" = "Ugyldig URL";
"next" = "Næste";
"share" = "Del";
"invalid_session_id" = "Ugyldigt Session ID";
"cancel" = "Afbryd";
"your_session_id" = "Dit Session ID";
"vc_landing_title_2" = "Din Session begynder her...";
"vc_landing_register_button_title" = "Opret Session ID";
"vc_landing_restore_button_title" = "Gendan Session ID";
"vc_landing_link_button_title" = "Forbind en enhed";
"view_fake_chat_bubble_1" = "Hvad er Session?";
"view_fake_chat_bubble_2" = "Det er en decentraliseret, krypteret beskedtjeneste";
"view_fake_chat_bubble_3" = "Så den indsamler ikke min personlige information eller mine samtalers metadata? Hvordan virker den?";
"view_fake_chat_bubble_4" = "Den bruger en kombination af avanceret anonym routing og end-to-end krypteringsteknologier.";
"view_fake_chat_bubble_5" = "Venner lader ikke venner bruge kompromitterede beskedtjenester.";
"vc_register_title" = "Sig hej til dit Session ID";
"vc_register_explanation" = "Dit Session ID er den unikke adresse, andre kan bruge til at kontakte dig på Session. Uden tilknytning til din virkelige identitet, er dit Session ID fuldstændig anonymt og privat.";
"vc_restore_title" = "Gendan Session ID";
"vc_restore_explanation" = "Indtast den gendannelsessætning der blev vist, da du oprettede dit Session ID for at gendanne din konto.";
"vc_restore_seed_text_field_hint" = "Indtast din gendannelsessætning";
"vc_link_device_title" = "Forbind en enhed";
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Kode";
"vc_display_name_title_2" = "Vælg dit Brugernavn";
"vc_display_name_explanation" = "Dette vil være dit navn når du bruger Session. Det kan være dit rigtige navn, et alias, eller alt mulig andet du syntes.";
"vc_display_name_text_field_hint" = "Indtast et brugernavn";
"vc_display_name_display_name_missing_error" = "Vælg venligst et brugernavn";
"vc_display_name_display_name_too_long_error" = "Vælg venligst et kortere brugernavn";
"vc_pn_mode_recommended_option_tag" = "Anbefalet";
"vc_pn_mode_no_option_picked_modal_title" = "Vælg Venligst en Mulighed";
"vc_home_empty_state_message" = "Du har endnu ingen kontakter";
"vc_home_empty_state_button_title" = "Start en Session";
"vc_seed_title" = "Din Gendannelsessætning";
"vc_seed_title_2" = "Dette er din gendannelsessætning";
"vc_seed_explanation" = "Din gendannelsessætning er hovednøglen til dit Session ID - du kan bruge den til at gendanne dit Session ID hvis du mister adgang til din enhed. Opbevar din gendannelsessætning et sikkert sted, og giv den ikke til nogen.";
"vc_seed_reveal_button_title" = "Hold nede for at få vist";
"view_seed_reminder_subtitle_1" = "Sikre din konto ved at gemme din gendannelsessætning";
"view_seed_reminder_subtitle_2" = "Tryk og hold på de skjulte ord for at få vist din gendannelsessætning, opbevare dem derefter sikkert for at kunne gendanne dit Session ID.";
"view_seed_reminder_subtitle_3" = "Sørg for at opbevare din gendannelsessætning et sikkert sted";
"vc_path_title" = "Rute";
"vc_path_explanation" = "Session skjuler din IP adresse ved at sende dine beskeder igennem adskillige Service Noder i Session's decentraliserede netværk. Dette er de lande din forbindelse for nuværende bliver sendt igennem:";
"vc_path_device_row_title" = "Dig";
"vc_path_guard_node_row_title" = "Indgangs Node";
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destination";
"vc_path_learn_more_button_title" = "Lær mere";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Indtast Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Kode";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session behøver kameraadgang for at scanne QR Koder";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Indtast et gruppenavn";
"vc_create_closed_group_empty_state_message" = "Du har endnu ingen kontakter";
"vc_create_closed_group_group_name_missing_error" = "Indtast venligst et gruppenavn";
"vc_create_closed_group_group_name_too_long_error" = "Indtast venligst et kortere gruppenavn";
"vc_create_closed_group_too_many_group_members_error" = "En lukket gruppe kan ikke have over 100 medlemmer";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Kode";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Indstillinger";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Vælg venligst et brugernavn";
"vc_settings_display_name_too_long_error" = "Vælg venligst et kortere brugernavn";
"vc_settings_privacy_button_title" = "Privatliv";
"vc_settings_notifications_button_title" = "Notifikationer";
"vc_settings_recovery_phrase_button_title" = "Gendannelsessætning";
"vc_settings_clear_all_data_button_title" = "Ryd data";
"vc_qr_code_title" = "QR kode";
"vc_qr_code_view_my_qr_code_tab_title" = "Vis Min QR Kode";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Kode";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan en anden brugers QR kode for at starte en samtale med dem";
"vc_view_my_qr_code_explanation" = "Dette er din QR kode. Andre brugere kan scanne den for at starte en session med dig.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Du vil få notifikationer om nye beskeder øjeblikkeligt ved hjælp af Apples notifikations servere.";
"fast_mode" = "Hurtig Tilstand";
"slow_mode_explanation" = "Session vil indimellem kontrollere for for nye beskeder i baggrunden.";
"slow_mode" = "Langsom Tilstand";
"vc_pn_mode_title" = "Besked Notifikationer";
"vc_link_device_recovery_phrase_tab_title" = "Gendannelsessætning";
"vc_link_device_scan_qr_code_explanation" = "Gå til indstillinger → Gendannelsessætning på din anden enhed for at få vist din QR kode.";
"vc_enter_recovery_phrase_title" = "Gendannelsessætning";
"vc_enter_recovery_phrase_explanation" = "For at forbinde din enhed, Indtast den gendannelsessætning der blev vist, da du oprettede dit Session ID.";
"vc_enter_public_key_text_field_hint" = "Indtast Session ID eller ONS navn";
"admin_group_leave_warning" = "Fordi det er dig, der har oprettet denne gruppe, vil den blive slettet for alle. Dette kan ikke fortrydes.";
"vc_join_open_group_suggestions_title" = "Eller tilmeld dig en af disse...";
"vc_settings_invite_a_friend_button_title" = "Inviter en Ven";
"copied" = "Kopieret";
"vc_conversation_settings_copy_session_id_button_title" = "Kopier Session ID";
"vc_conversation_input_prompt" = "Besked";
"vc_conversation_voice_message_cancel_message" = "Swipe for at afbryde";
"modal_download_attachment_title" = "Hav tillid til %@?";
"modal_download_attachment_explanation" = "Er du sikker på du vil downloade medie sendt af %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Åben URL?";
"modal_open_url_explanation" = "Er du sikker på, at du ønsker at åbne %@?";
"modal_open_url_button_title" = "Åben";
"modal_copy_url_button_title" = "Kopier link";
"modal_blocked_title" = "Fjern blokering af %@?";
"modal_blocked_explanation" = "Er du sikker på du vil fjerne blokeringen af %@?";
"modal_blocked_button_title" = "Fjern Blokering";
"modal_link_previews_title" = "Aktiver Forhåndsvisning af Links?";
"modal_link_previews_explanation" = "Aktivering af link forhåndsvisning vil forhåndsvise URLs du sender og modtager. Dette kan være brugbart, men Session vil være nødt til at kontakte tilsluttede websider for at generere forhåndsvisninger. Du kan altid deaktivere link forhåndsvisning i Session's indstillinger.";
"modal_link_previews_button_title" = "Aktiver";
"vc_share_title" = "Del med Session";
"vc_share_loading_message" = "Forbereder vedhæftninger...";
"vc_share_sending_message" = "Sender...";
"vc_share_link_previews_unsecure" = "Forhåndsvisning ikke indlæst for usikkert link";
"vc_share_link_previews_error" = "Kunne ikke indlæse forhåndsvisning";
"vc_share_link_previews_disabled_title" = "Link Forhåndsvisninger Deaktiveret";
"vc_share_link_previews_disabled_explanation" = "Aktivering af link forhåndsvisning vil vise forhåndsvisninger for URLs du deler. Dette kan være brugbart, men Session bliver nødt til at kontakte linkede websider for at generere forhåndsvisninger.\n\nDu kan aktivere link forhåndsvisning i Session's indstillinger.";
"view_open_group_invitation_description" = "Åben gruppeinvitation";
"vc_conversation_settings_invite_button_title" = "Tilføj medlemmer";
"modal_send_seed_title" = "Advarsel";
"modal_send_seed_explanation" = "Det her er din gendannelsessætning. Hvis du sender den til nogen vil de have fuld adgang til din konto.";
"modal_send_seed_send_button_title" = "Send";
"vc_conversation_settings_notify_for_mentions_only_title" = "Underret kun når jeg bliver omtalt";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Når aktiveret, vil du kun blive underrettet når du bliver omtalt i en besked.";
"view_conversation_title_notify_for_mentions_only" = "Underret kun når jeg bliver omtalt";
"message_deleted" = "Denne besked er blevet slettet";
"delete_message_for_me" = "Slet kun for mig";
"delete_message_for_everyone" = "Slet for alle";
"delete_message_for_me_and_recipient" = "Slet for mig og %@";
"context_menu_reply" = "Svar";
"context_menu_save" = "Gem";
"context_menu_ban_user" = "Bloker bruger";
"context_menu_ban_and_delete_all" = "Bloker og Slet Alle";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "Tilføj vedhæftninger";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Dokument";
"accessibility_library_button" = "Foto bibliotek";
"accessibility_camera_button" = "Kamera";
"accessibility_main_button_collapse" = "Skjul vedhæftnings muligheder";
"invalid_recovery_phrase" = "Ugyldig Gendannelsessætning";
"DISMISS_BUTTON_TEXT" = "Afvis";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Indstillinger";
"call_outgoing" = "Du ringede til %@";
"call_incoming" = "%@ ringede til dig";
"call_missed" = "Ubesvaret opkald fra %@";
"APN_Message" = "Du har en ny besked.";
"APN_Collapsed_Messages" = "Du har %@ nye beskeder.";
"PIN_BUTTON_TEXT" = "Fastgør";
"UNPIN_BUTTON_TEXT" = "Frigør";
"modal_call_missed_tips_title" = "Mistet opkald";
"modal_call_missed_tips_explanation" = "Mistet opkald fra '%@' fordi du ikke har aktiveret Lyd- og videoopkald i Privatlivsindstillinger.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ tog et screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Beskeder";
"MESSAGE_REQUESTS_TITLE" = "Beskedanmodninger";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Ingen afventende beskedanmodninger";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Ryd Alle";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Er du sikker på du vil rydde alle beskedanmodninger?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Ryd";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Er du sikker på du vil slette denne beskedanmodning?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Din beskedanmodning er blevet accepteret.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Du har en ny beskedanmodning";
"TXT_HIDE_TITLE" = "Skjul";
"TXT_DELETE_ACCEPT" = "Accepter";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Opkalds Tilladelse Krævet";
"modal_call_permission_request_explanation" = "Du kan aktivere Lyd- og videoopkald I Privatlivsindstillinger.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Der opstod en fejl";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Prøv venligst igen senere";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Ryd Alle Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data ikke slettet af 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data ikke slettet af %@ Service Noder. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Din Gendannelsessætning";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -15,39 +15,39 @@
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Fehler beim Senden des Anhangs";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Bild kann nicht konvertiert werden.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Das Bild konnte nicht konvertiert werden.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Video kann nicht verarbeitet werden.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Das Video konnte nicht verarbeitet werden.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Bild kann nicht geparst werden.";
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Das Bild kann nicht analysiert werden.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Metadaten können nicht aus dem Bild entfernt werden.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Bildgröße kann nicht geändert werden.";
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Die Größe des Bildes kann nicht geändert werden.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Anhang ist zu groß.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Anhang besitzt ungültigen Inhalt.";
"ATTACHMENT_ERROR_INVALID_DATA" = "Der Anhang enthält ungültige Inhalte.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Anhang besitzt ein ungültiges Dateiformat.";
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Anlagenfehlermeldung für Anlagen mit einem ungültigen Dateiformat.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Anhang ist leer.";
"ATTACHMENT_ERROR_MISSING_DATA" = "Anlagenfehlermeldung für Anhänge ohne Daten.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Auswählen des Dokuments gescheitert.";
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Dokument konnte nicht ausgewählt werden.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Bitte erstelle ein komprimiertes Archiv von dieser Datei oder diesem Ordner und versuche stattdessen dieses zu versenden.";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Bitte erstelle ein komprimiertes Archiv dieser Datei oder dieses Verzeichnisses und versuche es erneut zu versenden.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Datei nicht unterstützt";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Dateiformat nicht unterstützt";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Sprachnachricht";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Blockieren";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "%@ blockieren?";
/* A format for the 'unblock conversation' action sheet title. Embeds the {{conversation title}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "%@ freigeben?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Blockierung von %@ aufheben?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Freigeben";
"BLOCK_LIST_UNBLOCK_BUTTON" = "Blockieren aufheben";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ wurde blockiert.";
/* The title of the 'user blocked' alert. */
@ -55,13 +55,13 @@
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ wurde freigegeben.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blockierte Benutzer können dich nicht mehr anrufen oder dir Nachrichten senden.";
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blockierte Nutzer können Dich nicht anrufen oder Dir Nachrichten senden.";
/* Label for generic done button. */
"BUTTON_DONE" = "Fertig";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Auswählen";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
"CONVERSATION_SEARCH_SEARCHING" = "Ok...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Keine Treffer";
/* keyboard toolbar label when exactly 1 message matches the search string */
@ -69,7 +69,7 @@
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d von %d Treffern";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Diesen Nutzer blockieren";
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Diesen Benutzer blockieren";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Stummschalten";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
@ -79,7 +79,7 @@
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Dies kann einige Minuten dauern.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Datenbankoptimierung";
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimiere Datenbank";
/* The present; the current time. */
"DATE_NOW" = "Jetzt";
/* table cell label in conversation settings */
@ -93,7 +93,7 @@
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Ältere Medieninhalte werden geladen …";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Abruf des angeforderten GIFs gescheitert. Bitte überprüfe, ob du online bist.";
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Abruf des angeforderten GIF gescheitert. Bitte überprüfe, ob du online bist.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Ein unbekannter Fehler ist aufgetreten.";
/* Shown when selected GIF couldn't be fetched */
@ -101,15 +101,15 @@
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Bitte gib deine Suche ein.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Fehler. Für erneuten Versuch antippen.";
"GIF_VIEW_SEARCH_ERROR" = "Fehler. Für erneuten Versuch tippen.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Keine Ergebnisse.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Gruppe erstellt.";
"GROUP_CREATED" = "Gruppe erstellt";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ ist der Gruppe beigetreten.";
"GROUP_MEMBER_JOINED" = "%@ ist der Gruppe beigetreten. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ hat die Gruppe verlassen.";
"GROUP_MEMBER_LEFT" = "%@ hat die Gruppe verlassen. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ wurde aus der Gruppe entfernt. ";
/* No comment provided by engineer. */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "Gruppe verlassen";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Alle Medieninhalte";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Fotogalerie";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "%d Nachrichten löschen";
/* Confirmation button text to delete selected media message from the gallery */
@ -165,7 +163,7 @@
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Du hast eventuell Nachrichten erhalten, während dein %@ neu gestartet wurde.";
/* No comment provided by engineer. */
"BUTTON_OK" = "Okay";
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ hat verschwindende Nachrichten deaktiviert.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
@ -237,7 +235,7 @@
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Du hast verschwindende Nachrichten deaktiviert.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Du hast die Zeit für verschwindende Nachrichten auf %@ festgelegt.";
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Du hast die Zeit für verschwindende Nachrichten auf %@ festgelegt";
// MARK: - Session
"continue_2" = "Fortsetzen";
"copy" = "Kopieren";
@ -246,78 +244,76 @@
"share" = "Teilen";
"invalid_session_id" = "Ungültige Session ID";
"cancel" = "Abbrechen";
"your_session_id" = "Ihre Session ID";
"vc_landing_title_2" = "Ihre Session beginnt hier...";
"your_session_id" = "Deine Session ID";
"vc_landing_title_2" = "Deine Session beginnt hier...";
"vc_landing_register_button_title" = "Session ID erstellen";
"vc_landing_restore_button_title" = "Ihre Session fortsetzen";
"vc_landing_restore_button_title" = "Deine Session fortsetzen";
"vc_landing_link_button_title" = "Mit einem bestehenden Konto verlinken";
"view_fake_chat_bubble_1" = "Was ist Session?";
"view_fake_chat_bubble_2" = "Es ist eine dezentrale, verschlüsselte Messaging-App.";
"view_fake_chat_bubble_3" = "Es werden also weder meine persönlichen Daten noch die Metadaten meiner Konversation erfasst? Wie funktioniert das?";
"view_fake_chat_bubble_4" = "Mit einer Kombination fortschrittlicher anonyme Routing- und End-to-End-Verschlüsselungstechnologien.";
"view_fake_chat_bubble_5" = "Freunde lassen Freunde keine kompromittierten Messenger verwenden. Herzlich Willkommen.";
"vc_register_title" = "Das ist Ihre Session ID.";
"view_fake_chat_bubble_2" = "Es ist eine dezentrale, verschlüsselte Messaging-App";
"view_fake_chat_bubble_3" = "Es werden also weder meine persönlichen Daten noch die Metadaten meiner Konversationen erfasst? Wie funktioniert das?";
"view_fake_chat_bubble_4" = "Mit einer Kombination aus fortschrittlicher anonymer Routing- und Ende-zu-Ende-Verschlüsselungstechnologie.";
"view_fake_chat_bubble_5" = "Freunde lassen Freunde keine kompromittierten Messenger verwenden. Gern geschehen.";
"vc_register_title" = "Sag Hallo zu deiner Session ID";
"vc_register_explanation" = "Ihre Session ID ist die eindeutige Adresse, unter der Personen Sie über Session kontaktieren können. Ihre Session ID ist nicht mit Ihrer realen Identität verbunden, völlig anonym und von Natur aus privat.";
"vc_restore_title" = "Ihr Konto wiederherstellen";
"vc_restore_explanation" = "Geben Sie den Wiederherstellungssatz ein, den Sie bei der Anmeldung zur Wiederherstellung Ihres Kontos erhalten haben.";
"vc_restore_seed_text_field_hint" = "Ihr Wiederherstellungssatz";
"vc_restore_explanation" = "Gib die Wiederherstellungsphrase ein, die Du bei der Anmeldung zur Wiederherstellung Deines Kontos erhalten hast.";
"vc_restore_seed_text_field_hint" = "Gib Deine Wiederherstellungsphrase ein";
"vc_link_device_title" = "Gerät verbinden";
"vc_link_device_scan_qr_code_tab_title" = "QR-Code scannen";
"vc_display_name_title_2" = "Wählen Sie Ihren Anzeigenamen";
"vc_display_name_explanation" = "Dies ist Ihr Name, wenn Sie Session verwenden. Es kann Ihr richtiger Name, ein Alias oder etwas andere sein.";
"vc_display_name_text_field_hint" = "Geben Sie einen Anzeigenamen ein";
"vc_display_name_display_name_missing_error" = "Bitte wählen Sie einen Anzeigenamen";
"vc_display_name_display_name_too_long_error" = "Bitte wählen Sie einen kürzeren Anzeigenamen";
"vc_display_name_explanation" = "Dies wird dein Name sein, wenn du Session verwendest. Es kann dein richtiger Name, ein Alias oder alles andere sein, was dir gefällt.";
"vc_display_name_text_field_hint" = "Gib einen Anzeigenamen ein";
"vc_display_name_display_name_missing_error" = "Bitte wähle einen Anzeigenamen";
"vc_display_name_display_name_too_long_error" = "Bitte wähle einen kürzeren Anzeigenamen";
"vc_pn_mode_recommended_option_tag" = "Empfohlen";
"vc_pn_mode_no_option_picked_modal_title" = "Bitte wählen Sie eine Option aus.";
"vc_home_empty_state_message" = "Sie haben noch keine Kontakte.";
"vc_pn_mode_no_option_picked_modal_title" = "Bitte wähle eine Option";
"vc_home_empty_state_message" = "Du hast noch keine Kontakte";
"vc_home_empty_state_button_title" = "Session starten";
"vc_seed_title" = "Ihr Wiederherstellungssatz";
"vc_seed_title_2" = "Das ist Ihr Wiederherstellungssatz.";
"vc_seed_explanation" = "Ihr Wiederherstellungssatz ist der Hauptschlüssel für Ihre Session ID. Mit diesem Satz können Sie Ihre Session ID wiederherstellen, wenn Sie den Zugriff auf Ihr Gerät verlieren. Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf und geben Sie ihn an niemandem weiter.";
"vc_seed_title" = "Ihre Wiederherstellungsphrase";
"vc_seed_title_2" = "Deine Wiederherstellungsphrase";
"vc_seed_explanation" = "Deine Wiederherstellungsphrase ist der Hauptschlüssel für Deine Session ID. Mit diesem Satz kannst Du Deine Session ID wiederherstellen, wenn Du den Zugriff auf Dein Gerät verlierst. Bewahre Deine Wiederherstellungsphrase an einem sicheren Ort auf und gib sie an niemandem weiter.";
"vc_seed_reveal_button_title" = "Zur Anzeige gedrückt halten";
"view_seed_reminder_subtitle_1" = "Sichern Sie Ihr Konto, indem Sie Ihren Wiederherstellungssatz speichern";
"view_seed_reminder_subtitle_2" = "Tippen und halten Sie die verborgenen Wörter, um Ihren Wiederherstellungssatz anzuzeigen, und speichern Sie ihn dann sicher, um Ihre Session ID zu sichern.";
"view_seed_reminder_subtitle_3" = "Bewahren Sie Ihren Wiederherstellungssatz an einem sicheren Ort auf.";
"view_seed_reminder_subtitle_1" = "Sichere Dein Konto, indem Du Deine Wiederherstellungsphrase speicherst";
"view_seed_reminder_subtitle_2" = "Tippe und halte die verborgenen Wörter, um Deine Wiederherstellungsphrase anzuzeigen, und speichere sie dann, um Deine Session ID zu sichern.";
"view_seed_reminder_subtitle_3" = "Stelle sicher, Deine Wiederherstellungsphrase an einem sicheren Ort aufzubewahren";
"vc_path_title" = "Pfad";
"vc_path_explanation" = "Session verbirgt Ihre IP-Adresse, indem Ihre Nachrichten über mehrere Dienstknoten im dezentralen Session-Netzwerk weitergeleitet werden. Dies sind die Länder, durch die Ihre Verbindung derzeit weitergeleitet wird:";
"vc_path_device_row_title" = "Sie";
"vc_path_device_row_title" = "Du";
"vc_path_guard_node_row_title" = "Eingangsknoten";
"vc_path_service_node_row_title" = "Dienstknoten";
"vc_path_destination_row_title" = "Ziel";
"vc_path_learn_more_button_title" = "Mehr erfahren";
"vc_create_private_chat_title" = "Neue Session";
"vc_create_private_chat_title" = "Neue Nachricht";
"vc_create_private_chat_enter_session_id_tab_title" = "Session ID eingeben";
"vc_create_private_chat_scan_qr_code_tab_title" = "QR-Code scannen";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_enter_public_key_explanation" = "Beginne eine neue Unterhaltung, indem du die Session-ID von jemandem eingibst oder deine Session-ID mit ihm teilt.";
"vc_scan_qr_code_camera_access_explanation" = "Session benötigt Kamerazugriff, um die QR-Codes scannen zu können.";
"vc_scan_qr_code_grant_camera_access_button_title" = "Kamerazugriff gewähren";
"vc_create_closed_group_title" = "Neue geschlossene Gruppe";
"vc_create_closed_group_text_field_hint" = "Geben Sie einen Gruppennamen ein.";
"vc_create_closed_group_empty_state_message" = "Sie haben noch keine Kontakte.";
"vc_create_closed_group_empty_state_button_title" = "Session starten";
"vc_create_closed_group_group_name_missing_error" = "Bitte geben Sie einen Gruppennamen ein.";
"vc_create_closed_group_group_name_too_long_error" = "Bitte geben Sie einen kürzeren Gruppennamen ein.";
"vc_create_closed_group_title" = "Gruppe erstellen";
"vc_create_closed_group_text_field_hint" = "Gib einen Gruppennamen ein";
"vc_create_closed_group_empty_state_message" = "Du hast noch keine Kontakte";
"vc_create_closed_group_group_name_missing_error" = "Bitte gib einen Gruppennamen ein";
"vc_create_closed_group_group_name_too_long_error" = "Bitte gib einen kürzeren Gruppennamen ein";
"vc_create_closed_group_too_many_group_members_error" = "Eine geschlossene Gruppe kann maximal 100 Mitglieder haben.";
"vc_join_public_chat_title" = "Offener Gruppe beitreten";
"vc_join_public_chat_enter_group_url_tab_title" = "Gruppen-URL öffnen";
"vc_join_public_chat_title" = "Community beitreten";
"vc_join_public_chat_enter_group_url_tab_title" = "Community-URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "QR-Code scannen";
"vc_enter_chat_url_text_field_hint" = "Geben Sie eine offene Gruppen-URL ein.";
"vc_enter_chat_url_text_field_hint" = "Community-URL eingeben";
"vc_settings_title" = "Einstellungen";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Bitte wählen Sie einen Anzeigenamen.";
"vc_settings_display_name_too_long_error" = "Bitte wählen Sie einen kürzeren Anzeigenamen.";
"vc_group_settings_title" = "Gruppen-Einstellungen";
"vc_settings_display_name_missing_error" = "Bitte wähle einen Anzeigenamen";
"vc_settings_display_name_too_long_error" = "Bitte wähle einen kürzeren Anzeigenamen";
"vc_settings_privacy_button_title" = "Datenschutz";
"vc_settings_notifications_button_title" = "Benachrichtigungen";
"vc_settings_recovery_phrase_button_title" = "Wiederherstellungssatz";
"vc_settings_recovery_phrase_button_title" = "Wiederherstellungsphrase";
"vc_settings_clear_all_data_button_title" = "Daten löschen";
"vc_qr_code_title" = "QR-Code";
"vc_qr_code_view_my_qr_code_tab_title" = "Meinen QR-Code anzeigen";
"vc_qr_code_view_scan_qr_code_tab_title" = "QR-Code scannen";
"vc_qr_code_view_scan_qr_code_explanation" = "Scannen Sie den QR-Code einer Person, um ein Gespräch mit ihr zu beginnen.";
"vc_qr_code_view_scan_qr_code_explanation" = "Scanne den QR-Code von jemandem, um eine Unterhaltung mit ihm zu beginnen";
"vc_view_my_qr_code_explanation" = "Das ist Ihr QR-Code. Andere Benutzer können ihn scannen, um eine Session mit Ihnen zu starten.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Du wirst zuverlässig und unmittelbar mit dem Push-Mitteilungsdienst von Apple über neue Nachrichten informiert.";
"fast_mode_explanation" = "Du wirst über neue Nachrichten zuverlässig und unmittelbar durch Apples Push-Mitteilungsdienst informiert.";
"fast_mode" = "Schneller Modus";
"slow_mode_explanation" = "Session sucht gelegentlich im Hintergrund nach neuen Nachrichten.";
"slow_mode" = "Langsam Modus";
@ -325,27 +321,27 @@
"vc_link_device_recovery_phrase_tab_title" = "Wiederherstellungsphrase";
"vc_link_device_scan_qr_code_explanation" = "Gehe zu Einstellungen → Wiederherstellungsphrase auf deinem anderen Gerät um deinen QR-Code anzeigen zu lassen.";
"vc_enter_recovery_phrase_title" = "Wiederherstellungsphrase";
"vc_enter_recovery_phrase_explanation" = "Geben Sie zum Verknüpfen Ihres Geräts die Wiederherstellungsphrase ein, die Sie bei der Anmeldung erhalten haben.";
"vc_enter_recovery_phrase_explanation" = "Gib zum Verknüpfen deines Geräts die Wiederherstellungsphrase ein, die du bei der Anmeldung erhalten hast.";
"vc_enter_public_key_text_field_hint" = "Session-ID oder ONS-Name eingeben";
"admin_group_leave_warning" = "Da du der Ersteller dieser Gruppe bist, wird sie für alle gelöscht. Dies kann nicht rückgängig gemacht werden.";
"vc_join_open_group_suggestions_title" = "Oder nehmen Sie an einer dieser Veranstaltungen teil...";
"vc_join_open_group_suggestions_title" = "Oder tritt einer von diesen bei...";
"vc_settings_invite_a_friend_button_title" = "Freund einladen";
"copied" = "Kopiert";
"vc_conversation_settings_copy_session_id_button_title" = "Session-ID kopieren";
"vc_conversation_input_prompt" = "Nachricht";
"vc_conversation_voice_message_cancel_message" = "Wischen um abzubrechen";
"modal_download_attachment_title" = "%@ vertrauen?";
"modal_download_attachment_explanation" = "Sind Sie sicher, dass Sie die von %@ gesendeten Medien herunterladen möchten?";
"modal_download_attachment_explanation" = "Bist du sicher, dass du die von %@ gesendeten Medien herunterladen möchtest?";
"modal_download_button_title" = "Herunterladen";
"modal_open_url_title" = "URL öffnen?";
"modal_open_url_explanation" = "Möchten Sie %@ wirklich öffnen?";
"modal_open_url_explanation" = "Bist du sicher, dass du %@ öffnen möchtest?";
"modal_open_url_button_title" = "Öffnen";
"modal_copy_url_button_title" = "Link kopieren";
"modal_blocked_title" = "%@ entsperren?";
"modal_blocked_explanation" = "Sind Sie sicher, dass Sie %@ entsperren möchten?";
"modal_blocked_explanation" = "Bist du sicher, dass du %@ entblocken möchtest?";
"modal_blocked_button_title" = "Entsperren";
"modal_link_previews_title" = "Link-Vorschau aktivieren?";
"modal_link_previews_explanation" = "Das Aktivieren von Link-Vorschauen zeigt Vorschaubilder für URLs, die Sie senden und empfangen. Dies kann nützlich sein, aber Session muss verlinkte Webseiten kontaktieren, um Vorschaubilder zu generieren. Du kannst die Link-Vorschau in den Session-Einstellungen immer deaktivieren.";
"modal_link_previews_explanation" = "Das Aktivieren von Link-Vorschauen zeigt Vorschaubilder für URLs, die du sendest und empfängst. Dies kann nützlich sein, aber Session muss verlinkte Webseiten kontaktieren, um Vorschaubilder zu generieren. Du kannst die Link-Vorschau in den Session-Einstellungen immer deaktivieren.";
"modal_link_previews_button_title" = "Aktivieren";
"vc_share_title" = "Mit Session teilen";
"vc_share_loading_message" = "Anlagen werden vorbereitet...";
@ -353,11 +349,11 @@
"vc_share_link_previews_unsecure" = "Vorschau nicht für unsicheren Link geladen";
"vc_share_link_previews_error" = "Ansicht konnte nicht geladen werden";
"vc_share_link_previews_disabled_title" = "Linkvorschau deaktiviert";
"vc_share_link_previews_disabled_explanation" = "Das Aktivieren von Link-Vorschauen zeigt Vorschaubilder für URLs, die Sie senden und empfangen. Dies kann nützlich sein, aber Session muss verlinkte Webseiten kontaktieren, um Vorschaubilder zu generieren. Du kannst die Link-Vorschau in den Session-Einstellungen immer deaktivieren.";
"vc_share_link_previews_disabled_explanation" = "Wenn du die Linkvorschau aktivierst, werden Vorschauen für URLs angezeigt, die du teilst. Dies kann nützlich sein, aber Session muss die verlinkten Webseiten kontaktieren, um Vorschauen zu erstellen. \n\nDu kannst die Linkvorschau in den Einstellungen von Session aktivieren.";
"view_open_group_invitation_description" = "Gruppeneinladung öffnen";
"vc_conversation_settings_invite_button_title" = "Mitglieder hinzufügen";
"modal_send_seed_title" = "Warnung";
"modal_send_seed_explanation" = "Dies ist dein Wiederherstellungssatz. Wenn du ihn jemandem schickst, hat er oder sie vollen Zugriff auf dein Konto.";
"modal_send_seed_explanation" = "Dies ist Deine Wiederherstellungsphrase. Wenn Du diese jemandem schickst, hat er oder sie vollen Zugriff auf Dein Konto.";
"modal_send_seed_send_button_title" = "Senden";
"vc_conversation_settings_notify_for_mentions_only_title" = "Nur für Erwähnungen benachrichtigen";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Wenn aktiviert, wirst du nur für Nachrichten benachrichtigt, die dich erwähnen.";
@ -366,12 +362,11 @@
"delete_message_for_me" = "Nur für mich löschen";
"delete_message_for_everyone" = "Für jeden löschen";
"delete_message_for_me_and_recipient" = "Für mich und %@ löschen";
"context_menu_info" = "Info";
"context_menu_reply" = "Antworten";
"context_menu_save" = "Speichern";
"context_menu_ban_user" = "Nutzer sperren";
"context_menu_ban_and_delete_all" = "Sperren und alles löschen";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"context_menu_ban_user_error_alert_message" = "Benutzer konnte nicht gesperrt werden";
"accessibility_expanding_attachments_button" = "Anhänge hinzufügen";
"accessibility_gif_button" = "GIF";
"accessibility_document_button" = "Dokument";
@ -383,7 +378,7 @@
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Einstellungen";
"call_outgoing" = "Du hast %@ angerufen";
"call_incoming" = "%@ rief Sie an";
"call_incoming" = "%@ hat angerufen";
"call_missed" = "Verpasster Anruf von %@";
"APN_Message" = "Du hast eine neue Nachricht";
"APN_Collapsed_Messages" = "Du hast %@ neue Nachrichten.";
@ -393,258 +388,428 @@
"modal_call_missed_tips_explanation" = "Verpasster Anruf von '%@', da du die Berechtigung 'Anrufe und Videoanrufe' in den Datenschutzeinstellungen aktivieren musst.";
"media_saved" = "Medien gespeichert von %@.";
"screenshot_taken" = "%@ hat ein Screenshot gemacht.";
"SEARCH_SECTION_CONTACTS" = "Kontakte und Gruppen";
"SEARCH_SECTION_CONTACTS" = "Kontakte & Gruppen";
"SEARCH_SECTION_MESSAGES" = "Nachrichten";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Möchten Sie wirklich alle Nachrichten löschen?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"MESSAGE_REQUESTS_TITLE" = "Nachrichtenanfragen";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Keine ausstehenden Nachrichtenanfragen";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Alles löschen";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Bist Du sicher, dass Du alle Nachrichtenanfragen löschen möchtest?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Löschen";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Bist du sicher, dass du diese Nachrichtenanfrage löschen willst?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Möchtest du den Kontakt wirklich blockieren?";
"MESSAGE_REQUESTS_INFO" = "Wenn du diesem Nutzer eine Nachricht sendest, wird die Nachrichtenanfrage akzeptiert und deine Session-ID übertragen.";
"MESSAGE_REQUESTS_ACCEPTED" = "Ihre Nachrichtenanfrage wurde angenommen.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Du hast eine neue Nachrichtenanfrage";
"TXT_HIDE_TITLE" = "Ausblenden";
"TXT_DELETE_ACCEPT" = "Zustimmen";
"TXT_BLOCK_USER_TITLE" = "Benutzer blockieren";
"ALERT_ERROR_TITLE" = "Fehler";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
"modal_call_permission_request_title" = "Anrufberechtigung erforderlich";
"modal_call_permission_request_explanation" = "Du kannst die Berechtigung für \"Sprach- und Videoanrufe\" in den Datenschutzeinstellungen aktivieren.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Hoppla, ein Fehler ist aufgetreten";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Bitte versuche es später erneut";
"LOADING_CONVERSATIONS" = "Chats werden geladen...";
"DATABASE_MIGRATION_FAILED" = "Bei der Optimierung der Datenbank ist ein Fehler aufgetreten\n\nSie können Ihre Anwendungsprotokolle exportieren, um sie zur Fehlerbehebung mit uns zu teilen oder Sie können Ihr Gerät wiederherstellen\n\nWarnung: Die Wiederherstellung Ihres Geräts führt zum Verlust von sämtlichen Daten, die älter als zwei Wochen sind";
"RECOVERY_PHASE_ERROR_GENERIC" = "Etwas ist schiefgelaufen. Bitte überprüfe deine Wiederherstellungsphrase und versuche es erneut.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Es sieht so aus, als ob du nicht genügend Wörter eingegeben hast. Bitte überprüfe deine Wiederherstellungsphrase und versuche es erneut.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Du scheinst das letzte Wort Deiner Wiederherstellungsphrase auszulassen. Bitte prüfe Deine Eingabe und versuche es erneut.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Es scheint ein ungültiges Wort in Deiner Wiederherstellungsphrase zu geben. Bitte überprüfe Deine Eingabe und versuche es erneut.";
"RECOVERY_PHASE_ERROR_FAILED" = "Deine Wiederherstellungsphrase konnte nicht verifiziert werden. Bitte überprüfe, was Du eingegeben hast, und versuche es erneut.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentifizierung konnte nicht abgerufen werden.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentifizierung gescheitert.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentifizierung fehlgeschlagen.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Zu viele gescheiterte Authentifizierungsversuche. Bitte versuche es später erneut.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Zu viele fehlgeschlagene Authentifizierungen. Bitte versuche es später erneut.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Um die Bildschirmsperre zu verwenden, musst du einen Code in den iOS-Einstellungen festlegen.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Um die Bildschirmsperre zu verwenden, musst du einen Code in den iOS-Einstellungen festlegen.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Du musst einen Passcode in deinen iOS-Einstellungen festlegen, um die Bildschirmsperre zu verwenden.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Du musst in den iOS-Einstellungen einen Code festlegen, um die Bildschirmsperre zu verwenden.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
"SEND_BUTTON_TITLE" = "Senden";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
"RETRY_BUTTON_TEXT" = "Wiederholen";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
"SHOW_THREAD_BUTTON_TITLE" = "Chat anzeigen";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
"SEND_FAILED_NOTIFICATION_BODY" = "Nachricht konnte nicht gesendet werden.";
"INVALID_SESSION_ID_MESSAGE" = "Bitte prüfe die Session-ID und versuche es erneut.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Bitte überprüfe die Wiederherstellungsphrase und versuche es erneut.";
"MEDIA_TAB_TITLE" = "Medien";
"DOCUMENT_TAB_TITLE" = "Dokumente";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "Diese Unterhaltung enthält keine Dokumente.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Lade neueres Dokument…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Älteres Dokument wird geladen…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Aktivitäten";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
"EMOJI_CATEGORY_ANIMALS_NAME" = "Tiere & Natur";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
"EMOJI_CATEGORY_FLAGS_NAME" = "Flaggen";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
"EMOJI_CATEGORY_FOOD_NAME" = "Essen & Trinken";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objekte";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
"EMOJI_CATEGORY_RECENTS_NAME" = "Zuletzt verwendet";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & Personen";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbole";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
"EMOJI_CATEGORY_TRAVEL_NAME" = "Reisen & Orte";
"EMOJI_REACTS_NOTIFICATION" = "%@ reagiert auf eine Nachricht mit %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Und 1 weiterer hat mit %@ auf diese Nachricht reagiert.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "Und %@ andere haben %@ auf diese Nachricht reagiert.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Langsam! Du hast zu viele Emoji-Reaktionen versendet. Versuche es später erneut.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"vc_new_conversation_title" = "Neue Unterhaltung";
"CREATE_GROUP_BUTTON_TITLE" = "Erstellen";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Beitreten";
"PRIVACY_TITLE" = "Datenschutz";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Bildschirmschutz";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_SCREEN_SECURITY" = "App-Sperre";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Sitzung sperren";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Zum Entsperren der Sitzung benötigst Du Touch ID, Face ID oder Dein Passwort.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Lesebestätigungen";
"PRIVACY_READ_RECEIPTS_TITLE" = "Lesebestätigungen";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Sende Lesebestätigungen in Einzelchats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Tipp-Indikatoren";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Tipp-Indikatoren";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Link-Vorschauen senden";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Zeige und teile Eingabeindikatoren in Einzelchats.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link-Vorschauen";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Sende Link-Vorschauen";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generiere Link-Vorschauen für unterstützte URLs.";
"PRIVACY_SECTION_CALLS" = "Anrufe (Beta)";
"PRIVACY_CALLS_TITLE" = "Sprach- und Videoanrufe";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"PRIVACY_CALLS_DESCRIPTION" = "Aktiviert Sprach- und Videoanrufe an und von anderen Benutzern.";
"PRIVACY_CALLS_WARNING_TITLE" = "Sprach- und Videoanrufe (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Deine IP-Adresse ist bei Beta-Anrufen für Deinen Gesprächspartner und einen Oxen Foundation Server sichtbar. Bist Du sicher, dass Du Sprach- und Videoanrufe aktivieren möchtest?";
"NOTIFICATIONS_TITLE" = "Benachrichtigungen";
"NOTIFICATIONS_SECTION_STRATEGY" = "Benachrichtigungsstrategie";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Schnellen Modus benutzen";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Mitteilungsinhalt";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Nur Name";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Kein Name oder Inhalt";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Schnellen Modus verwenden";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Du wirst über neue Nachrichten zuverlässig und unmittelbar durch Apples Push-Mitteilungsdienst informiert.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Gehe zu den Benachrichtigungseinstellungen";
"NOTIFICATIONS_SECTION_STYLE" = "Benachrichtigungsstil";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Ton";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Ton, wenn die App geöffnet ist";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Inhalt der Benachrichtigungen";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Die Informationen, die in den Benachrichtigungen angezeigt werden.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name und Inhalt";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Nur Kontaktname";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Weder Name noch Nachricht";
"CONVERSATION_SETTINGS_TITLE" = "Chats";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Nachricht kürzen";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Communities kürzen";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Lösche Nachrichten, die älter als 6 Monate sind, aus Communities mit über 2.000 Nachrichten.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio-Nachrichten";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Audio-Nachrichten automatisch abspielen";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Automatisches Abspielen aufeinanderfolgender Audio-Nachrichten.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blockierte Kontakte";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Du hast keine blockierten Kontakte.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Entblocken";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Bist Du sicher, dass Du den Benutzer {name} entblocken möchtest?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "Dieser Kontakt";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Bist Du sicher, dass Du den Benutzer {name} entblocken möchtest";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "und %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "und %d andere?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Entblocken";
"APPEARANCE_TITLE" = "Darstellung";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "Häufig gestellte Fragen";
"HELP_SUPPORT_TITLE" = "Support";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Grundfarbe";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Wie geht es Dir?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Mir geht es gut, danke, und Dir?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Mir geht es prima, danke.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto-Nachtmodus";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "An Systemeinstellungen anpassen";
"HELP_TITLE" = "Hilfe";
"HELP_REPORT_BUG_TITLE" = "Melde einen Fehler";
"HELP_REPORT_BUG_DESCRIPTION" = "Exportiere Deine Fehlerprotokolle und lade die Datei über Sessions Service-Center hoch.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Protokolle exportieren";
"HELP_TRANSLATE_TITLE" = "Session übersetzen";
"HELP_FEEDBACK_TITLE" = "Wir würden uns über Dein Feedback freuen";
"HELP_FAQ_TITLE" = "Häufig gestellte Fragen (FAQ)";
"HELP_SUPPORT_TITLE" = "Unterstützung";
"modal_clear_all_data_title" = "Alle Daten löschen";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"modal_clear_all_data_explanation" = "Dies wird Deine Nachrichten und Kontakte dauerhaft löschen. Möchtest Du nur dieses Gerät löschen oder Deine Daten aus dem Netzwerk löschen?";
"modal_clear_all_data_explanation_2" = "Bist Du sicher, dass Du Deine Daten aus dem Netzwerk löschen möchtest? Wenn Du fortfährst, kannst Du Deine Nachrichten oder Kontakte nicht wiederherstellen.";
"modal_clear_all_data_device_only_button_title" = "Nur Gerät löschen";
"modal_clear_all_data_entire_account_button_title" = "Geräte- und Netzwerkdaten löschen";
"dialog_clear_all_data_deletion_failed_1" = "Daten nicht gelöscht von Service Node 1. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Daten nicht gelöscht von %@ Service Noten. Service Noten IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Ihr Wiederherstellungssatz";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"modal_clear_all_data_confirm" = "Löschen";
"modal_seed_title" = "Deine Wiederherstellungsphrase";
"modal_seed_explanation" = "Du kannst Deine Wiederherstellungsphrase verwenden, um Dein Konto wiederherzustellen oder ein Gerät zu verknüpfen.";
"modal_permission_explanation" = "Session benötigt %@ Zugriff, um fortzufahren. Du kannst den Zugriff in den iOS-Einstellungen aktivieren.";
"modal_permission_settings_title" = "Einstellungen";
"modal_permission_camera" = "Kamera";
"modal_permission_microphone" = "Mikrofon";
"modal_permission_library" = "Bibliothek";
"DISAPPEARING_MESSAGES_OFF" = "Aus";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Aus";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Verschwinden nach: %@";
"COPY_GROUP_URL" = "Gruppen-URL kopieren";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakte";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Bitte wähle mindestens ein Gruppenmitglied aus";
"GROUP_CREATION_PLEASE_WAIT" = "Bitte warten, während die Gruppe erstellt wird...";
"GROUP_CREATION_ERROR_TITLE" = "Gruppe konnte nicht erstellt werden";
"GROUP_CREATION_ERROR_MESSAGE" = "Bitte überprüfe Deine Internetverbindung und versuche es erneut.";
"GROUP_UPDATE_ERROR_TITLE" = "Gruppe konnte nicht aktualisiert werden";
"GROUP_UPDATE_ERROR_MESSAGE" = "Du kannst die Gruppe nicht verlassen, während andere Mitglieder hinzugefügt oder entfernt werden.";
"GROUP_ACTION_REMOVE" = "Entfernen";
"GROUP_TITLE_MEMBERS" = "Mitglieder";
"GROUP_TITLE_FALLBACK" = "Gruppe";
"DM_ERROR_DIRECT_BLINDED_ID" = "Du kannst nur Nachrichten an Blinded IDs innerhalb einer Community senden";
"DM_ERROR_INVALID" = "Bitte überprüfe die Session-ID oder den ONS-Namen und versuche es erneut";
"COMMUNITY_ERROR_INVALID_URL" = "Bitte überprüfe die von Dir eingegebene URL und versuche es erneut.";
"COMMUNITY_ERROR_GENERIC" = "Beitritt fehlgeschlagen";
"DISAPPERING_MESSAGES_TITLE" = "Verschwindende Nachrichten";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Löschart";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Nach dem Lesen verschwinden";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Nachrichten löschen, nachdem sie gelesen wurden.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Nach dem Senden verschwinden";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Nachrichten löschen, nachdem sie gesendet worden sind.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Speichern";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Diese Einstellung gilt für alle in dieser Unterhaltung.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Diese Einstellung gilt für alle in dieser Unterhaltung. Nur Gruppenadministratoren können diese Einstellung ändern.";
"DISAPPERING_MESSAGES_SUMMARY" = "Verschwinden nach %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ hat eingestellt, dass die Nachrichten %@ verschwinden, nachdem sie %@ sind";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ hat eingestellt, dass die Nachrichten %@ verschwinden, nachdem sie %@ sind";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ hat verschwindende Nachrichten ausgeschaltet";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Συνημμένο";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Λεζάντα";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Τύπος αρχείου: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Μέγεθος: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Συμπληρώθηκε το όριο μηνυμάτων";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Αποστολή";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Συνημμένο";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Σφάλμα Αποστολής Συνημμένου";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Αδυναμία μετατροπής της εικόνας.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Αδυναμία επεξεργασίας του βίντεο.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Αδυναμία ανάλυσης της εικόνας.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Αδυναμία αφαίρεσης των μεταδεδομένων από την εικόνα.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Αδυναμία αλλαγής μεγέθους της εικόνας.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Το συνημμένο είναι πολύ μεγάλο.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Το συνημμένο περιλαμβάνει μη έγκυρο περιεχόμενο.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Το συνημμένο έχει μη έγκυρη μορφή αρχείου.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Το συνημμένο είναι κενό.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Αποτυχία επιλογής εγγράφου.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Παρακαλώ δημιουργήστε ένα συμπιεσμένο αρχείο αυτού του αρχείου ή καταλόγου και προσπαθήστε να στείλετε αυτό.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Μη υποστηριζόμενο Αρχείο";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Ηχητικό μήνυμα";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Φραγή";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Φραγή %@;";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Αναίρεση φραγής %@;";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Αναίρεση φραγής";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ έχει φραγεί.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Ο Χρήστης έχει Φραγεί";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Έγινε κατάργηση φραγής σε %@.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Οι φραγμένοι χρήστες δεν θα είναι σε θέση να σας καλούν ή να σας στέλνουν μηνύματα.";
/* Label for generic done button. */
"BUTTON_DONE" = "Ολοκληρώθηκε";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Επιλογή";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Αναζήτηση...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Χωρίς αποτελέσματα";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 αντιστοιχία";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d από %d αντιστοιχίσεις";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Φραγή Αυτού του Χρήστη";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Σίγαση";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Αναζήτηση στη Συνομιλία";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Μετακίνηση και Κλιμάκωση";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Αυτό μπορεί να διαρκέσει μερικά λεπτά.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Βελτιστοποίηση Βάσης Δεδομένων";
/* The present; the current time. */
"DATE_NOW" = "Τώρα";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Εξαφανιζόμενα Μηνύματα";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Επεξεργασία Ομάδας";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "Δεν έχετε κανένα πολυμέσο σε αυτή τη συνομιλία.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Φόρτωση Νεότερων Πολυμέσων...";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Φόρτωση Παλαιότερων Πολυμέσων...";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Αποτυχία ανάκτησης του GIF. Παρακαλώ επιβεβαιώστε ότι είστε συνδεδεμένοι.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Παρουσιάστηκε άγνωστο σφάλμα.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Αδυναμία επιλογής GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Παρακαλώ εισάγετε την αναζήτηση.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Σφάλμα. Πατήστε για επανάληψη.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Κανένα Αποτέλεσμα.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Η ομάδα δημιουργήθηκε";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ έγινε μέλος στην ομάδα. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ αποχώρησε από την ομάδα. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ αφαιρέθηκε από την ομάδα. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ αφαιρέθηκαν από την ομάδα. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Ο τίτλος είναι τώρα '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Η ομάδα ενημερώθηκε.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Αποχωρήσατε από την ομάδα.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Έχετε διαγραφεί από την ομάδα. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "Δεν μπορείτε να μοιραστείτε πάνω από %@ αντικείμενα.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Αποτυχία επιλογής συνημμένου.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Μη έγκυρο αρχείο ήχου.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Αποχώρηση";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Αποχώρηση από την ομάδα";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Όλα τα πολυμέσα";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Διαγραφή %d μηνυμάτων";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Διαγραφή Μηνύματος";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ στις %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Εσείς";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Αυτό το μήνα";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Η αποστολή απέτυχε.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Διαβάστηκε";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Γίνεται Αποστολή…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Στάλθηκε";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Μεταφόρτωση…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ σε %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Σημείωση προς εμένα";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Μπορεί να έχετε λάβει μηνύματα κατά την επανεκκίνηση του %@.";
/* No comment provided by engineer. */
"BUTTON_OK" = "ΟΚ";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ απενεργοποίησε τα εξαφανιζόμενα μηνύματα.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ όρισε το χρόνο εξαφάνισης μηνύματος σε %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Αδυναμία λήψης εικόνας.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Αδυναμία λήψης εικόνας.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Αποτυχία ρύθμισης της κάμερας.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Άλμπουμ Χωρίς Όνομα";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Σήμανση ως Αναγνωσμένο";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Απάντηση";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Πραγματοποιήστε έλεγχο ταυτότητας για να ανοίξετε το Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Ο Έλεγχος Ταυτότητας Απέτυχε";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Απόρριψη Πολυμέσων;";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Απόρριψη Πολυμέσων";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (προεπιλογή)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Ήχος Μηνύματος";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "Κανένας";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ ημέρες";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@ημ";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ ώρες";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@ώρ";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ λεπτά";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@λ";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ δευτερόλεπτα";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@δ";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ ημέρα";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ ώρα";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ λεπτό";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ εβδομάδα";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ εβδομάδες";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@εβδ";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Ακύρωση";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Διαγραφή";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Ηχητικό Μήνυμα";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Πατήστε παρατεταμένα για να ηχογραφήσετε ένα φωνητικό μήνυμα.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Ηχητικό Μήνυμα";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Απενεργοποιήσατε τα εξαφανιζόμενα μηνύματα.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Ορίσατε τον χρόνο του εξαφανιζόμενου μηνύματος σε %@";
// MARK: - Session
"continue_2" = "Συνέχεια";
"copy" = "Αντιγραφή";
"invalid_url" = "Μη έγκυρο URL";
"next" = "Επόμενο";
"share" = "Κοινοποίηση";
"invalid_session_id" = "Μη έγκυρο Session ID";
"cancel" = "Ακύρωση";
"your_session_id" = "Το Session ID σας";
"vc_landing_title_2" = "Το Session σας ξεκινά εδώ...";
"vc_landing_register_button_title" = "Δημιουργία Session ID";
"vc_landing_restore_button_title" = "Συνεχίστε το Session σας";
"vc_landing_link_button_title" = "Συνδέστε μια Συσκευή";
"view_fake_chat_bubble_1" = "Τι είναι το Session;";
"view_fake_chat_bubble_2" = "Είναι μια αποκεντρωμένη, κρυπτογραφημένη εφαρμογή ανταλλαγής μηνυμάτων";
"view_fake_chat_bubble_3" = "Άρα δε συλλέγει τα προσωπικά μου στοιχεία ή τα μεταδεδομένα της συνομιλίας μου; Πώς λειτουργεί;";
"view_fake_chat_bubble_4" = "Χρησιμοποιώντας έναν συνδυασμό προηγμένων τεχνολογιών ανώνυμης δρομολόγησης και κρυπτογράφησης από άκρο σε άκρο.";
"view_fake_chat_bubble_5" = "Οι φίλοι δεν αφήνουν τους φίλους να χρησιμοποιούν ευάλωτες εφαρμογές ανταλλαγής μηνυμάτων. Παρακαλώ.";
"vc_register_title" = "Πείτε γεια στο Session ID σας";
"vc_register_explanation" = "Το Session ID σας είναι η μοναδική διεύθυνση που μπορούν να χρησιμοποιήσουν κάποιοι για να επικοινωνήσουν μαζί σας στο Session. Χωρίς σύνδεση με την πραγματική σας ταυτότητα, το Session ID σας είναι σχεδιασμένο να είναι εντελώς ανώνυμο και ιδιωτικό.";
"vc_restore_title" = "Επαναφορά του λογαριασμού σας";
"vc_restore_explanation" = "Εισαγάγετε τη φράση ανάκτησης που σας δόθηκε κατά την εγγραφή σας για να επαναφέρετε τον λογαριασμό σας.";
"vc_restore_seed_text_field_hint" = "Εισαγάγετε τη φράση σας ανάκτησης";
"vc_link_device_title" = "Συνδέστε μια Συσκευή";
"vc_link_device_scan_qr_code_tab_title" = "Σάρωση Κωδικού QR";
"vc_display_name_title_2" = "Επιλέξτε το όνομα εμφάνισής σας";
"vc_display_name_explanation" = "Αυτό θα είναι το όνομά σας όταν χρησιμοποιείτε το Session. Μπορεί να είναι το πραγματικό σας όνομα, ένα ψευδώνυμο ή οτιδήποτε άλλο θέλετε.";
"vc_display_name_text_field_hint" = "Εισαγάγετε ένα όνομα εμφάνισης";
"vc_display_name_display_name_missing_error" = "Παρακαλώ επιλέξτε ένα όνομα εμφάνισης";
"vc_display_name_display_name_too_long_error" = "Παρακαλώ επιλέξτε ένα μικρότερο όνομα εμφάνισης";
"vc_pn_mode_recommended_option_tag" = "Προτείνεται";
"vc_pn_mode_no_option_picked_modal_title" = "Παρακαλώ Διαλέξτε μία από τις Επιλογές";
"vc_home_empty_state_message" = "Δεν έχετε επαφές ακόμα";
"vc_home_empty_state_button_title" = "Ξεκινήστε ένα Session";
"vc_seed_title" = "Η Φράση σας Ανάκτησης";
"vc_seed_title_2" = "Γνωρίστε τη φράση σας ανάκτησης";
"vc_seed_explanation" = "Η φράση σας ανάκτησης είναι το κύριο κλειδί στο Session ID σας - μπορείτε να τη χρησιμοποιήσετε για να επαναφέρετε το Session ID σας εάν χάσετε την πρόσβαση στη συσκευή σας. Αποθηκεύστε τη φράση ανάκτησης σε ένα ασφαλές μέρος, και μην τη δώσετε σε κανέναν.";
"vc_seed_reveal_button_title" = "Πατήστε για αποκάλυψη";
"view_seed_reminder_subtitle_1" = "Ασφαλίστε τον λογαριασμό σας αποθηκεύοντας τη φράση σας ανάκτησης";
"view_seed_reminder_subtitle_2" = "Πατήστε παρατεταμένα τις λέξεις που τροποποιήθηκαν για να αποκαλύψετε τη φράση ανάκτησης και μετά αποθηκεύστε την με ασφάλεια για να εξασφαλίσετε το αναγνωριστικό σας.";
"view_seed_reminder_subtitle_3" = "Φροντίστε να αποθηκεύσετε τη φράση ανάκτησής σας σε ασφαλές μέρος";
"vc_path_title" = "Διαδρομή";
"vc_path_explanation" = "Το Session αποκρύπτει την IP σας, δρομολογώντας τα μηνύματά σας μέσω αρκετών Κόμβων υπηρεσιών στο αποκεντρωμένο Session δίκτυο. Αυτές είναι οι χώρες που δρομολογείται η σύνδεσή σας αυτή τη στιγμή:";
"vc_path_device_row_title" = "Εσείς";
"vc_path_guard_node_row_title" = "Κόμβος Εισόδου";
"vc_path_service_node_row_title" = "Κόμβος Εξυπηρέτησης";
"vc_path_destination_row_title" = "Προορισμός";
"vc_path_learn_more_button_title" = "Μάθετε Περισσότερα";
"vc_create_private_chat_title" = "Νέο Μήνυμα";
"vc_create_private_chat_enter_session_id_tab_title" = "Εισαγάγετε το Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Σάρωση Κωδικού QR";
"vc_enter_public_key_explanation" = "Ξεκινήστε μια νέα συνομιλία εισάγοντας το Session ID κάποιου ή μοιραστείτε το δικό σας Session ID μαζί τους.";
"vc_scan_qr_code_camera_access_explanation" = "Το Session χρειάζεται πρόσβαση στην κάμερα για σάρωση κωδικών QR";
"vc_create_closed_group_title" = "Δημιουργία Ομάδας";
"vc_create_closed_group_text_field_hint" = "Εισαγάγετε ένα όνομα ομάδας";
"vc_create_closed_group_empty_state_message" = "Δεν έχετε επαφές ακόμη";
"vc_create_closed_group_group_name_missing_error" = "Παρακαλώ εισαγάγετε ένα όνομα ομάδας";
"vc_create_closed_group_group_name_too_long_error" = "Παρακαλώ εισαγάγετε ένα μικρότερο όνομα ομάδας";
"vc_create_closed_group_too_many_group_members_error" = "Μια κλειστή ομάδα δεν μπορεί να έχει περισσότερα από 100 μέλη";
"vc_join_public_chat_title" = "Γίνετε μέλος της Κοινότητας";
"vc_join_public_chat_enter_group_url_tab_title" = "URL Κοινότητας";
"vc_join_public_chat_scan_qr_code_tab_title" = "Σάρωση Κωδικού QR";
"vc_enter_chat_url_text_field_hint" = "Εισαγάγετε URL Κοινότητας";
"vc_settings_title" = "Ρυθμίσεις";
"vc_group_settings_title" = "Ρυθμίσεις Ομάδας";
"vc_settings_display_name_missing_error" = "Παρακαλώ επιλέξτε ένα όνομα εμφάνισης";
"vc_settings_display_name_too_long_error" = "Παρακαλώ επιλέξτε ένα μικρότερο όνομα εμφάνισης";
"vc_settings_privacy_button_title" = "Απόρρητο";
"vc_settings_notifications_button_title" = "Ειδοποιήσεις";
"vc_settings_recovery_phrase_button_title" = "Φράση Ανάκτησης";
"vc_settings_clear_all_data_button_title" = "Διαγραφή Δεδομένων";
"vc_qr_code_title" = "Κωδικός QR";
"vc_qr_code_view_my_qr_code_tab_title" = "Προβολή του Κωδικού QR Μου";
"vc_qr_code_view_scan_qr_code_tab_title" = "Σάρωση Κωδικού QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Σαρώστε τον κωδικό QR κάποιου για να ξεκινήσετε μια συνομιλία μαζί του";
"vc_view_my_qr_code_explanation" = "Αυτός είναι ο δικός σας κωδικός QR. Άλλοι χρήστες μπορούν να τον σαρώσουν για να ξεκινήσουν μια συνομιλία μαζί σας.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Θα ειδοποιηθείτε για νέα μηνύματα αξιόπιστα και άμεσα χρησιμοποιώντας τους διακομιστές ειδοποιήσεων της Apple.";
"fast_mode" = "Γρήγορη Λειτουργία";
"slow_mode_explanation" = "Το Session θα ελέγχει περιστασιακά για νέα μηνύματα στο παρασκήνιο.";
"slow_mode" = "Αργή Λειτουργία";
"vc_pn_mode_title" = "Ειδοποιήσεις Μηνυμάτων";
"vc_link_device_recovery_phrase_tab_title" = "Φράση Ανάκτησης";
"vc_link_device_scan_qr_code_explanation" = "Μεταβείτε στις Ρυθμίσεις → Φράση Ανάκτησης στην άλλη σας συσκευή για να εμφανίσετε τον κωδικό QR σας.";
"vc_enter_recovery_phrase_title" = "Φράση Ανάκτησης";
"vc_enter_recovery_phrase_explanation" = "Για να συνδέσετε τη συσκευή σας, εισάγετε τη φράση ανάκτησης που σας δόθηκε κατά την εγγραφή σας.";
"vc_enter_public_key_text_field_hint" = "Εισαγάγετε Session ID ή όνομα ONS";
"admin_group_leave_warning" = "Επειδή είστε ο δημιουργός αυτής της ομάδας θα διαγραφεί για όλους. Αυτό δεν μπορεί να αναιρεθεί.";
"vc_join_open_group_suggestions_title" = "Ή γίνετε μέλος σε ένα από αυτά...";
"vc_settings_invite_a_friend_button_title" = "Προσκαλέστε ένα Φίλο";
"copied" = "Αντιγράφηκε";
"vc_conversation_settings_copy_session_id_button_title" = "Αντιγραφή Session ID";
"vc_conversation_input_prompt" = "Μήνυμα";
"vc_conversation_voice_message_cancel_message" = "Σύρετε για Ακύρωση";
"modal_download_attachment_title" = "Εμπιστεύεστε την επαφή %@;";
"modal_download_attachment_explanation" = "Σίγουρα θέλετε να κάνετε λήψη των πολυμέσων που έχουν σταλεί από %@;";
"modal_download_button_title" = "Λήψη";
"modal_open_url_title" = "Άνοιγμα URL;";
"modal_open_url_explanation" = "Σίγουρα θέλετε να ανοίξετε το %@;";
"modal_open_url_button_title" = "Άνοιγμα";
"modal_copy_url_button_title" = "Αντιγραφή Συνδέσμου";
"modal_blocked_title" = "Κατάργηση φραγής %@;";
"modal_blocked_explanation" = "Σίγουρα θέλετε να καταργήσετε τη φραγή από %@;";
"modal_blocked_button_title" = "Κατάργηση φραγής";
"modal_link_previews_title" = "Ενεργοποίηση Προεπισκοπήσεων Συνδέσμου;";
"modal_link_previews_explanation" = "Η ενεργοποίηση προεπισκοπήσεων συνδέσμων θα εμφανίζει προεπισκοπήσεις για τα URL που στέλνετε και λαμβάνετε. Αυτό μπορεί να είναι χρήσιμο, αλλά το Session θα πρέπει να επικοινωνήσει με τους αντίστοιχους ιστότοπους για να δημιουργήσει προεπισκοπήσεις. Μπορείτε ανά πάσα στιγμή να απενεργοποιήσετε τις προεπισκοπήσεις συνδέσμων στις ρυθμίσεις του Session.";
"modal_link_previews_button_title" = "Ενεργοποίηση";
"vc_share_title" = "Κοινοποίηση στο Session";
"vc_share_loading_message" = "Προετοιμασία συνημμένων...";
"vc_share_sending_message" = "Αποστολή...";
"vc_share_link_previews_unsecure" = "Η προεπισκόπηση δε φορτώθηκε για μη ασφαλή σύνδεσμο";
"vc_share_link_previews_error" = "Αδυναμία φόρτωσης προεπισκόπησης";
"vc_share_link_previews_disabled_title" = "Προεπισκοπήσεις Συνδέσμου Απενεργοποιημένες";
"vc_share_link_previews_disabled_explanation" = "Η ενεργοποίηση προεπισκοπήσεων συνδέσμου θα εμφανίζει προεπισκοπήσεις για τα URL που κοινοποιείτε. Αυτό μπορεί να είναι χρήσιμο, αλλά το Session θα πρέπει να επικοινωνήσει με τους αντίστοιχους ιστότοπους για να δημιουργήσει προεπισκοπήσεις.\n\nΜπορείτε να ενεργοποιήσετε τις προεπισκοπήσεις συνδέσμου στις ρυθμίσεις του Session.";
"view_open_group_invitation_description" = "Πρόσκληση ανοιχτής ομάδας";
"vc_conversation_settings_invite_button_title" = "Προσθήκη Μελών";
"modal_send_seed_title" = "Προειδοποίηση";
"modal_send_seed_explanation" = "Αυτή είναι η φράση σας ανάκτησης. Αν τη στείλετε σε κάποιον θα έχει πλήρη πρόσβαση στον λογαριασμό σας.";
"modal_send_seed_send_button_title" = "Αποστολή";
"vc_conversation_settings_notify_for_mentions_only_title" = "Ειδοποίηση Μόνο για Αναφορές";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Όταν είναι ενεργοποιημένο, θα ειδοποιηθείτε μόνο για μηνύματα που σας αναφέρουν.";
"view_conversation_title_notify_for_mentions_only" = "Ειδοποιεί Μόνο για Αναφορές";
"message_deleted" = "Αυτό το μήνυμα έχει διαγραφεί";
"delete_message_for_me" = "Διαγραφή μόνο για εμένα";
"delete_message_for_everyone" = "Διαγραφή για όλους";
"delete_message_for_me_and_recipient" = "Διαγραφή για εμένα και %@";
"context_menu_reply" = "Απάντηση";
"context_menu_save" = "Αποθήκευση";
"context_menu_ban_user" = "Αποκλεισμός Χρήστη";
"context_menu_ban_and_delete_all" = "Αποκλεισμός και Διαγραφή Όλων";
"context_menu_ban_user_error_alert_message" = "Αδυναμία αποκλεισμού χρήστη";
"accessibility_expanding_attachments_button" = "Προσθήκη συνημμένων";
"accessibility_gif_button" = "GIF";
"accessibility_document_button" = "Έγγραφο";
"accessibility_library_button" = "Βιβλιοθήκη φωτογραφιών";
"accessibility_camera_button" = "Κάμερα";
"accessibility_main_button_collapse" = "Σύμπτυξη επιλογών συνημμένου";
"invalid_recovery_phrase" = "Μη έγκυρη Φράση Ανάκτησης";
"DISMISS_BUTTON_TEXT" = "Παράλειψη";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Ρυθμίσεις";
"call_outgoing" = "Καλέσατε %@";
"call_incoming" = "Είχατε κλήση από %@";
"call_missed" = "Αναπάντητη Κλήση από %@";
"APN_Message" = "Έχετε ένα νέο μήνυμα";
"APN_Collapsed_Messages" = "Έχετε %@ νέα μηνύματα.";
"PIN_BUTTON_TEXT" = "Καρφίτσωμα";
"UNPIN_BUTTON_TEXT" = "Ξεκαρφίτσωμα";
"modal_call_missed_tips_title" = "Αναπάντητη κλήση";
"modal_call_missed_tips_explanation" = "Η κλήση από «%@» χάθηκε επειδή πρέπει να ενεργοποιήσετε την άδεια «Κλήσεις Φωνής και Βίντεο» στις Ρυθμίσεις Απορρήτου.";
"media_saved" = "Αποθηκεύτηκαν πολυμέσα από %@.";
"screenshot_taken" = "Λήφθηκε στιγμιότυπο οθόνης από %@.";
"SEARCH_SECTION_CONTACTS" = "Επαφές & Ομάδες";
"SEARCH_SECTION_MESSAGES" = "Μηνύματα";
"MESSAGE_REQUESTS_TITLE" = "Αιτήματα Μηνύματος";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Δεν υπάρχουν αιτήματα μηνυμάτων σε εκκρεμότητα";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Διαγραφή Όλων";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Σίγουρα θέλετε να διαγράψετε όλα τα αιτήματα μηνύματος;";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Διαγραφή";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Σίγουρα θέλετε να διαγράψετε αυτό το αίτημα μηνύματος;";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Σίγουρα θέλετε να θέσετε σε φραγή αυτή την επαφή;";
"MESSAGE_REQUESTS_INFO" = "Η αποστολή μηνύματος σε αυτόν τον χρήστη θα αποδεχτεί αυτόματα το αίτημα μηνύματός του και θα αποκαλύψει το Session ID σας.";
"MESSAGE_REQUESTS_ACCEPTED" = "Το αίτημα μηνύματός σας έγινε δεκτό.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Έχετε ένα νέο αίτημα μηνύματος";
"TXT_HIDE_TITLE" = "Απόκρυψη";
"TXT_DELETE_ACCEPT" = "Αποδοχή";
"TXT_BLOCK_USER_TITLE" = "Φραγή Χρήστη";
"ALERT_ERROR_TITLE" = "Σφάλμα";
"modal_call_permission_request_title" = "Απαιτείται Άδεια Κλήσης";
"modal_call_permission_request_explanation" = "Μπορείτε να ενεργοποιήσετε την άδεια «Κλήσεις Φωνής και Βίντεο» στις Ρυθμίσεις Απορρήτου.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Ωχ, προέκυψε σφάλμα";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Παρακαλώ δοκιμάστε ξανά αργότερα";
"LOADING_CONVERSATIONS" = "Φόρτωση Συνομιλιών...";
"DATABASE_MIGRATION_FAILED" = "Παρουσιάστηκε σφάλμα κατά τη βελτιστοποίηση της βάσης δεδομένων\n\nΜπορείτε να εξάγετε τα αρχεία καταγραφής της εφαρμογής σας για να μπορείτε να τα μοιραστείτε για την αντιμετώπιση προβλημάτων ή μπορείτε να επαναφέρετε τη συσκευή σας\n\nΠροειδοποίηση: Η επαναφορά της συσκευής σας θα οδηγήσει σε απώλεια δεδομένων παλαιότερων από δύο εβδομάδες";
"RECOVERY_PHASE_ERROR_GENERIC" = "Κάτι πήγε στραβά. Παρακαλώ ελέγξτε τη φράση ανάκτησης και προσπαθήστε ξανά.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Φαίνεται ότι δεν εισαγάγατε αρκετές λέξεις. Παρακαλώ ελέγξτε τη φράση σας ανάκτησης και προσπαθήστε ξανά.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Φαίνεται πως λείπει η τελευταία λέξη από τη φράση σας ανάκτησης. Παρακαλώ ελέγξτε τι εισαγάγατε και προσπαθήστε ξανά.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Φαίνεται να υπάρχει μια μη έγκυρη λέξη στη φράση σας ανάκτησης. Παρακαλώ ελέγξτε τι εισαγάγατε και προσπαθήστε ξανά.";
"RECOVERY_PHASE_ERROR_FAILED" = "Η φράση ανάκτησης δεν μπόρεσε να επαληθευτεί. Παρακαλώ ελέγξτε τι εισαγάγατε και προσπαθήστε ξανά.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Δεν ήταν δυνατή η πρόσβαση στον έλεγχο ταυτότητας.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Ο έλεγχος ταυτότητας απέτυχε.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Πάρα πολλές αποτυχημένες προσπάθειες ταυτοποίησης. Παρακαλώ προσπαθήστε ξανά αργότερα.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Απαιτείται να ορίσετε έναν κωδικό πρόσβασης στις Ρυθμίσεις του iOS σας για να χρησιμοποιήσετε το Κλείδωμα Οθόνης.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Πρέπει να ορίσετε έναν κωδικό πρόσβασης στις Ρυθμίσεις του iOS σας για να χρησιμοποιήσετε το Κλείδωμα Οθόνης.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Πρέπει να ενεργοποιήσετε έναν κωδικό πρόσβασης στις Ρυθμίσεις του iOS σας για να χρησιμοποιήσετε το Κλείδωμα Οθόνης.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Αποστολή";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Επανάληψη";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Εμφάνιση Συνομιλίας";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Η αποστολή του μηνύματός σας απέτυχε.";
"INVALID_SESSION_ID_MESSAGE" = "Παρακαλώ ελέγξτε το Session ID και προσπαθήστε ξανά.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Παρακαλώ ελέγξτε τη Φράση Ανάκτησης και προσπαθήστε ξανά.";
"MEDIA_TAB_TITLE" = "Πολυμέσα";
"DOCUMENT_TAB_TITLE" = "Έγγραφα";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "Δεν έχετε κανένα έγγραφο σε αυτή τη συνομιλία.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Φόρτωση Νεότερου Εγγράφου...";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Φόρτωση Παλαιότερου Εγγράφου...";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Δραστηριότητες";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Ζώα & Φύση";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Σημαίες";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Φαγητό & Ποτό";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Αντικείμενα";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Πρόσφατα";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Χαμόγελα & Άνθρωποι";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Σύμβολα";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Ταξίδια & Τοποθεσίες";
"EMOJI_REACTS_NOTIFICATION" = "%@ αντέδρασε σε ένα μήνυμα με %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Και άλλος 1 αντέδρασε με %@ σε αυτό το μήνυμα.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "Και %@ άλλοι αντέδρασαν με %@ σε αυτό το μήνυμα.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Ηρεμήστε! Έχετε στείλει πάρα πολλές αντιδράσεις emoji. Δοκιμάστε ξανά σύντομα.";
/* New conversation screen*/
"vc_new_conversation_title" = "Νέα Συνομιλία";
"CREATE_GROUP_BUTTON_TITLE" = "Δημιουργία";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Γίνετε μέλος";
"PRIVACY_TITLE" = "Απόρρητο";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Ασφάλεια Οθόνης";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Κλείδωμα του Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Απαιτείται Touch ID, Face ID ή ο κωδικός πρόσβασης για να ξεκλειδώσετε το Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Αναφορές Ανάγνωσης";
"PRIVACY_READ_RECEIPTS_TITLE" = "Αναφορές Ανάγνωσης";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Αποστολή αναφορών ανάγνωσης σε ένας προς έναν συνομιλίες.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Δείκτες Πληκτρολόγησης";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Δείκτες Πληκτρολόγησης";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Δείτε και κοινοποιήστε δείκτες πληκτρολόγησης σε ένας προς έναν συνομιλίες.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Προεπισκοπήσεις Συνδέσμου";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Αποστολή Προεπισκοπήσεων Συνδέσμου";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Δημιουργία προεπισκοπήσεων συνδέσμου για υποστηριζόμενα URL.";
"PRIVACY_SECTION_CALLS" = "Κλήσεις (Beta)";
"PRIVACY_CALLS_TITLE" = "Κλήσεις Φωνής και Βίντεο";
"PRIVACY_CALLS_DESCRIPTION" = "Επιτρέπει κλήσεις φωνής και βίντεο από και προς άλλους χρήστες.";
"PRIVACY_CALLS_WARNING_TITLE" = "Κλήσεις Φωνής και Βίντεο (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Η IP διεύθυνσή σας είναι ορατή στον συνομιλητή σας και σε έναν Oxen Foundation server κατά τη χρήση κλήσεων beta. Σίγουρα θέλετε να ενεργοποιήσετε τις Κλήσεις Φωνής και Βίντεο;";
"NOTIFICATIONS_TITLE" = "Ειδοποιήσεις";
"NOTIFICATIONS_SECTION_STRATEGY" = "Στρατηγική Ειδοποιήσεων";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Χρήση Γρήγορης Λειτουργίας";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Θα ειδοποιηθείτε για νέα μηνύματα αξιόπιστα και άμεσα χρησιμοποιώντας τους διακομιστές ειδοποιήσεων της Apple.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Μεταβείτε στις ρυθμίσεις ειδοποιήσεων της συσκευής";
"NOTIFICATIONS_SECTION_STYLE" = "Στυλ Ειδοποιήσεων";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Ήχος";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Ήχος όταν η Εφαρμογή είναι Ανοιχτή";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Περιεχόμενο Ειδοποίησης";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Οι πληροφορίες που εμφανίζονται στις ειδοποιήσεις.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Όνομα & Περιεχόμενο";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Όνομα Μόνο";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Χωρίς Όνομα ή Περιεχόμενο";
"CONVERSATION_SETTINGS_TITLE" = "Συνομιλίες";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Περικοπή Μηνυμάτων";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Περικοπή Κοινοτήτων";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Διαγραφή μηνυμάτων παλαιότερων από 6 μήνες από Κοινότητες που έχουν πάνω από 2.000 μηνύματα.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Ηχητικά Μηνύματα";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Αυτόματη Αναπαραγωγή Ηχητικών Μηνυμάτων";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Αυτόματη αναπαραγωγή διαδοχικών ηχητικών μηνυμάτων.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Επαφές σε Φραγή";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Δεν έχετε επαφές σε φραγή.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Κατάργηση φραγής";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Σίγουρα θέλετε να καταργήσετε τη φραγή από %@;";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "αυτή την επαφή";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Σίγουρα θέλετε να καταργήσετε τη φραγή από %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "και %@;";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "και %d άλλους;";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Κατάργηση φραγής";
"APPEARANCE_TITLE" = "Εμφάνιση";
"APPEARANCE_THEMES_TITLE" = "Θέματα";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Κύριο χρώμα";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Πώς είσαι;";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Είμαι καλά ευχαριστώ, εσύ;";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Τα πάω τέλεια, ευχαριστώ.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Αυτόματη νυχτερινή λειτουργία";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Αντιστοίχιση ρυθμίσεων συστήματος";
"HELP_TITLE" = "Βοήθεια";
"HELP_REPORT_BUG_TITLE" = "Αναφορά Σφάλματος";
"HELP_REPORT_BUG_DESCRIPTION" = "Εξαγάγετε τα αρχεία καταγραφής σας και στη συνέχεια μεταφορτώστε το αρχείο μέσω του Help Desk του Session.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Εξαγωγή Αρχείων Καταγραφής";
"HELP_TRANSLATE_TITLE" = "Μετάφραση του Session";
"HELP_FEEDBACK_TITLE" = "Θα θέλαμε πολύ τα Σχόλιά σας";
"HELP_FAQ_TITLE" = "Συχνές Ερωτήσεις";
"HELP_SUPPORT_TITLE" = "Υποστήριξη";
"modal_clear_all_data_title" = "Διαγραφή Όλων των Δεδομένων";
"modal_clear_all_data_explanation" = "Αυτό θα διαγράψει μόνιμα τα μηνύματα και τις επαφές σας. Θα θέλατε να καθαρίσετε αυτή τη συσκευή μόνο ή να διαγράψετε και τα δεδομένα σας από το δίκτυο;";
"modal_clear_all_data_explanation_2" = "Σίγουρα θέλετε να διαγράψετε τα δεδομένα σας από το δίκτυο; Εάν συνεχίσετε, δε θα μπορείτε να επαναφέρετε τα μηνύματα ή τις επαφές σας.";
"modal_clear_all_data_device_only_button_title" = "Διαγραφή Μόνο Συσκευής";
"modal_clear_all_data_entire_account_button_title" = "Διαγραφή Συσκευής Και Δικτύου";
"dialog_clear_all_data_deletion_failed_1" = "Τα δεδομένα δε διαγράφηκαν από 1 Κόμβο Εξυπηρέτησης. ID Κόμβου Εξυπηρέτησης: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Τα δεδομένα δε διαγράφηκαν από %@ Κόμβους Εξυπηρέτησης. ID Κόμβων Εξυπηρέτησης: %@.";
"modal_clear_all_data_confirm" = "Διαγραφή";
"modal_seed_title" = "Η Φράση σας Ανάκτησης";
"modal_seed_explanation" = "Μπορείτε να χρησιμοποιήσετε τη φράση σας ανάκτησης για να επαναφέρετε τον λογαριασμό σας ή να συνδέσετε μια συσκευή.";
"modal_permission_explanation" = "Το Session χρειάζεται πρόσβαση σε %@ για να συνεχίσει. Μπορείτε να ενεργοποιήσετε την πρόσβαση στις ρυθμίσεις του iOS σας.";
"modal_permission_settings_title" = "Ρυθμίσεις";
"modal_permission_camera" = "κάμερα";
"modal_permission_microphone" = "μικρόφωνο";
"modal_permission_library" = "βιβλιοθήκη";
"DISAPPEARING_MESSAGES_OFF" = "Απενεργοποιημένο";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Απενεργοποιημένη";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Εξαφάνιση Μετά Από: %@";
"COPY_GROUP_URL" = "Αντιγραφή URL Ομάδας";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Επαφές";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Παρακαλώ επιλέξτε τουλάχιστον 1 μέλος από την ομάδα";
"GROUP_CREATION_PLEASE_WAIT" = "Παρακαλώ περιμένετε όσο δημιουργείται η ομάδα...";
"GROUP_CREATION_ERROR_TITLE" = "Αδυναμία Δημιουργίας Ομάδας";
"GROUP_CREATION_ERROR_MESSAGE" = "Παρακαλώ ελέγξτε τη σύνδεση σας στο διαδίκτυο και προσπαθήστε ξανά.";
"GROUP_UPDATE_ERROR_TITLE" = "Αδυναμία Ενημέρωσης Ομάδας";
"GROUP_UPDATE_ERROR_MESSAGE" = "Δεν είναι δυνατή η αποχώρηση από την ομάδα κατά την προσθήκη ή αφαίρεση άλλων μελών.";
"GROUP_ACTION_REMOVE" = "Αφαίρεση";
"GROUP_TITLE_MEMBERS" = "Μέλη";
"GROUP_TITLE_FALLBACK" = "Ομάδα";
"DM_ERROR_DIRECT_BLINDED_ID" = "Μπορείτε να στείλετε μόνο μηνύματα σε Blinded IDs από μέσα από μια Κοινότητα";
"DM_ERROR_INVALID" = "Παρακαλώ ελέγξτε το Session ID ή το όνομα ONS και δοκιμάστε ξανά";
"COMMUNITY_ERROR_INVALID_URL" = "Παρακαλώ ελέγξτε το URL που εισαγάγατε και προσπαθήστε ξανά.";
"COMMUNITY_ERROR_GENERIC" = "Αδυναμία Συμμετοχής";
"DISAPPERING_MESSAGES_TITLE" = "Εξαφανιζόμενα Μηνύματα";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Τύπος Διαγραφής";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Εξαφάνιση Μετά από Ανάγνωση";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Τα μηνύματα διαγράφονται αφού έχουν αναγνωσθεί.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Εξαφάνιση Μετά από Αποστολή";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Τα μηνύματα διαγράφονται αφού έχουν αποσταλεί.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Χρονόμετρο";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Ορισμός";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Αυτή η ρύθμιση ισχύει για όλους σε αυτή τη συνομιλία.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Αυτή η ρύθμιση ισχύει για όλους σε αυτή τη συνομιλία. Μόνο οι διαχειριστές της ομάδας μπορούν να αλλάξουν αυτή τη ρύθμιση.";
"DISAPPERING_MESSAGES_SUMMARY" = "Εξαφάνιση Μετά Από %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ όρισε τα μηνύματα να εξαφανίζονται %@ αφότου έχουν %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ άλλαξε τα μηνύματα να εξαφανίζονται %@ αφότου έχουν %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ απενεργοποίησε τα εξαφανιζόμενα μηνύματα";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "Leave Group";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "All Media";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Photo Library";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Delete %d Messages";
/* Confirmation button text to delete selected media message from the gallery */
@ -291,11 +289,9 @@
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_scan_qr_code_grant_camera_access_button_title" = "Grant Camera Access";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_empty_state_button_title" = "Start a Session";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
@ -366,7 +362,6 @@
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_info" = "Info";
"context_menu_reply" = "Reply";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
@ -414,10 +409,6 @@
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
@ -446,7 +437,6 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
@ -473,7 +463,6 @@
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
@ -584,67 +573,243 @@
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -0,0 +1,815 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Kunsendaĵo";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Apudskribo";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "File type: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Size: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Mesaĝa limito atingite";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Sendi";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Kunsendaĵo";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Error Sending Attachment";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Unable to convert image.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Unable to process video.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Unable to parse image.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Unable to remove metadata from image.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Unable to resize image.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Attachment is too large.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Attachment includes invalid content.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Attachment has an invalid file format.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Failed to choose document.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Please create a compressed archive of this file or directory and try sending that instead.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Unsupported File";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Voĉmesaĝo";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Bloki";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Ĉu bloki %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Malbloki";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
/* Label for generic done button. */
"BUTTON_DONE" = "Done";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Elekti";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Neniuj informpetitoj";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 informpetito";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d de %d informpetitoj";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block This User";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Silentigi";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Search Conversation";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Move and Scale";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimizing Database";
/* The present; the current time. */
"DATE_NOW" = "Nun";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Memviŝontaj Mesaĝoj";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Redakti Grupon";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "You don't have any media in this conversation.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Media…";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Loading Older Media…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Failed to fetch the requested GIF. Please verify you are online.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "An unknown error occurred.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Unable to Choose GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Please enter your search.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Error. Tap to Retry.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "No Results.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Grupo kreitite";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Title is now '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Group updated.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Vi forlasis la grupon.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Vi estas forigita el la grupo. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "You can't share more than %@ items.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Failed to select attachment.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Invalid audio file.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Forlasi";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Forlasi Grupon";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "All Media";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Forviĝi %d Mesaĝojn";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Forviŝi Mesaĝon";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ on %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Vi";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Ĉi Tiu Monato";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Sendante malsukcesis.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Legita";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Sendante…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Sendita";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Alŝutante…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ al %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Noto al Mi mem";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "You may have received messages while your %@ was restarting.";
/* No comment provided by engineer. */
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ disabled disappearing messages.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ set disappearing message time to %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Unable to capture image.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Unable to capture image.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Failed to configure camera.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Unnamed Album";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Mark as Read";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Respondi";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Authenticate to open Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Authentication Failed";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Discard Media?";
/* alert action, confirming the user wants to exit the media flow and abandon any photos they've taken */
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Discard Media";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (default)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ tagoj";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@t";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ horoj";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutoj";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ sekundoj";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ tago";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "%@ horo";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minuto";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "%@ week";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "Cancel";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Forviŝi";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Voĉmesaĝo";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Tap and hold to record a voice message.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Voĉmesaĝo";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You disabled disappearing messages.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
// MARK: - Session
"continue_2" = "Continue";
"copy" = "Kopii";
"invalid_url" = "Malvalida URL";
"next" = "Sekva";
"share" = "Kunhavigi";
"invalid_session_id" = "Malvalida Session ID";
"cancel" = "Cancel";
"your_session_id" = "Via Session ID";
"vc_landing_title_2" = "Via Sesio komenci ĉi tie...";
"vc_landing_register_button_title" = "Krei Session ID-on";
"vc_landing_restore_button_title" = "Continue Your Session";
"vc_landing_link_button_title" = "Ligi Aparaton";
"view_fake_chat_bubble_1" = "Kio estas Session?";
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
"vc_register_title" = "Diru saluton al via Session ID";
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"vc_restore_title" = "Restaŭri vian konton";
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
"vc_restore_seed_text_field_hint" = "Enter your recovery phrase";
"vc_link_device_title" = "Ligi Aparaton";
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Code";
"vc_display_name_title_2" = "Pick your display name";
"vc_display_name_explanation" = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
"vc_display_name_text_field_hint" = "Entajpu vidigan nomon";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_pn_mode_recommended_option_tag" = "Recommended";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Komenci Sesion";
"vc_seed_title" = "Via Ripara Frazo";
"vc_seed_title_2" = "Ekkonu vian riparan frazon";
"vc_seed_explanation" = "Via ripara frazo estas la ĉefŝlosilo de via Session ID — vi povas uzi ĝin por restaŭri vian Session ID-on se vi malgajros aliron al via aparato. Konservu vian riparan frazon en sekura loko, kaj donu ĝin al neniu.";
"vc_seed_reveal_button_title" = "Tuŝadu por malkaŝi";
"view_seed_reminder_subtitle_1" = "Sekurigi vian konton per konservi vian riparan frazon";
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"vc_path_title" = "Vojo";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "Vi";
"vc_path_guard_node_row_title" = "Enira Nodo";
"vc_path_service_node_row_title" = "Serva Nodo";
"vc_path_destination_row_title" = "Celo";
"vc_path_learn_more_button_title" = "Lerni pli";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Entajpi Session ID-on";
"vc_create_private_chat_scan_qr_code_tab_title" = "Skani QR-Kodon";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session bezonas fotilan aliron por skani QR-kodojn";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Entajpu grupnomon";
"vc_create_closed_group_empty_state_message" = "Vi ankoraŭ ne havas kontaktojn";
"vc_create_closed_group_group_name_missing_error" = "Bonvolu entajpi grupnomon";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Skani QR-Kodon";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Agordo";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
"vc_settings_privacy_button_title" = "Privateco";
"vc_settings_notifications_button_title" = "Sciigoj";
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
"vc_settings_clear_all_data_button_title" = "Clear Data";
"vc_qr_code_title" = "QR-Kodo";
"vc_qr_code_view_my_qr_code_tab_title" = "Vidi Mian QR-Kodon";
"vc_qr_code_view_scan_qr_code_tab_title" = "Skanu QR Kodon";
"vc_qr_code_view_scan_qr_code_explanation" = "Skani ies QR-kodon por komenci konversacion kun si";
"vc_view_my_qr_code_explanation" = "Ĉi tio estas via QR-kodo. Aliaj uzantoj povas skani ĝin por komenci sesion kun vi.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "Rapida Maniero";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "Malrapida Reĝimo";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Ripara Frazo";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Ripara Frazo";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Inviti Amikon";
"copied" = "Kopiite";
"vc_conversation_settings_copy_session_id_button_title" = "Kopii Session ID-on";
"vc_conversation_input_prompt" = "Mesaĝi";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "Malfermi";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Ĉu Malbloki %@?";
"modal_blocked_explanation" = "Ĉu vi certas, ke vi volas malbloki %@?";
"modal_blocked_button_title" = "Malbloki";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "Kunhavigi al Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sendante...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "Aldoni Anojn";
"modal_send_seed_title" = "Warning";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "Send";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
"message_deleted" = "This message has been deleted";
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_reply" = "Reply";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
"context_menu_ban_and_delete_all" = "Ban and Delete All";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "Add attachments";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Document";
"accessibility_library_button" = "Photo library";
"accessibility_camera_button" = "Camera";
"accessibility_main_button_collapse" = "Collapse attachment options";
"invalid_recovery_phrase" = "Invalid Recovery Phrase";
"DISMISS_BUTTON_TEXT" = "Dismiss";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Settings";
"call_outgoing" = "You called %@";
"call_incoming" = "%@ called you";
"call_missed" = "Missed Call from %@";
"APN_Message" = "You've got a new message.";
"APN_Collapsed_Messages" = "You've got %@ new messages.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Via Ripara Frazo";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -15,37 +15,37 @@
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Fallo al enviar archivo adjunto";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Bild kann nicht konvertiert werden.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Fallo al convertir imagen.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Video kann nicht verarbeitet werden.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Fallo al procesar el vídeo.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Bild kann nicht geparst werden.";
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Fallo al leer imagen.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Metadaten können nicht aus dem Bild entfernt werden.";
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Fallo al eliminar los metadatos de la imagen.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Bildgröße kann nicht geändert werden.";
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Fallo al redimensionar la imagen.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Anhang ist zu groß.";
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "El archivo adjunto es demasiado grande.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Anhang besitzt ungültigen Inhalt.";
"ATTACHMENT_ERROR_INVALID_DATA" = "El archivo adjunto incluye contenido inválido.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Anhang besitzt ein ungültiges Dateiformat.";
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "El archivo adjunto tiene un formato de archivo inválido.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Anhang ist leer.";
"ATTACHMENT_ERROR_MISSING_DATA" = "El archivo adjunto está vacío.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Fallo al seleccionar documento.";
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Fallo al seleccionar el documento.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Crea un archivo comprimido de este fichero o carpeta y prueba a enviar la versión comprimida.";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Por favor, crea un archivo comprimido de este fichero o carpeta y prueba a enviar la versión comprimida.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Archivo no admitido";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Nota de voz";
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Mensaje de Voz";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Bloquear";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "¿Bloquear %@?";
/* A format for the 'unblock conversation' action sheet title. Embeds the {{conversation title}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "¿Desbloquear %@?";
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "¿Bloquear a %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "¿Desbloquear a %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Desbloquear";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
@ -61,7 +61,7 @@
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Seleccionar";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
"CONVERSATION_SEARCH_SEARCHING" = "Buscando...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Sin resultados";
/* keyboard toolbar label when exactly 1 message matches the search string */
@ -89,33 +89,33 @@
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "No hay ningún adjunto en este chat.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Cargando adjuntos recientes ...";
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Cargando adjuntos recientes";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Cargando adjuntos previos ...";
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Cargando adjuntos anteriores…";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Fallo al descargar el GIF seleccionado. Verifica que el iPhone tiene conexión a internet.";
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Error al descargar el GIF seleccionado. Por favor, verifique que tiene conexión a internet.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Ocurrió un fallo desconocido.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "Fallo al seleccionar GIF";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "Introducir búsqueda.";
"GIF_PICKER_VIEW_MISSING_QUERY" = "Por favor, introduce el término de búsqueda.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Fallo. Toca para reintentar.";
"GIF_VIEW_SEARCH_ERROR" = "Error. Toque para volver a intentarlo.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "Sin resultados.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Grupo creado.";
"GROUP_CREATED" = "Grupo creado";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ se ha unido al grupo.";
"GROUP_MEMBER_JOINED" = "%@ se ha unido al grupo. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ ha abandonado el grupo.";
"GROUP_MEMBER_LEFT" = "%@ ha abandonado el grupo. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = " Fue eliminado del grupo. ";
"GROUP_MEMBER_REMOVED" = "%@ ha sido expulsado del grupo. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ fue eliminado del grupo. ";
"GROUP_MEMBERS_REMOVED" = "%@ han sido expulsados del grupo. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "El grupo se llama ahora «%@».";
"GROUP_TITLE_CHANGED" = "El grupo ahora se llama '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Grupo actualizado.";
/* No comment provided by engineer. */
@ -123,9 +123,9 @@
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " Has sido eliminado del grupo. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "No se pueden compartir más de %@ objetos.";
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "No se pueden compartir más de %@ imágenes.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Fallo al seleccionar adjunto.";
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Fallo al seleccionar el adjunto.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Archivo de audio inválido.";
/* Confirmation button within contextual alert */
@ -134,12 +134,10 @@
"LEAVE_GROUP_ACTION" = "Abandonar grupo";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Adjuntos";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Fototeca";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Eliminar %d mensajes";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Eliminar mensajes";
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Eliminar mensaje";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ el %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
@ -148,32 +146,32 @@
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Tú";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Este mes";
/* message status for message delivered to their recipient. */
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Fallo al enviar.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Leído";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Enviando ...";
"MESSAGE_STATUS_SENDING" = "Enviando";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Enviado";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Cargando ...";
"MESSAGE_STATUS_UPLOADING" = "Subiendo…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ en %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Notas personales";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Has recibido mensajes mientras tu %@ estaba reiniciándose.";
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Puede que hayas recibido mensajes mientras se reiniciaba tu %@.";
/* No comment provided by engineer. */
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ ha desactivado la desaparición de mensajes.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ ha fijado la desaparición de mensajes en %@.";
"OTHER_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ ha establecido la desaparición de mensajes en %@";
/* alert title, generic error preventing user from capturing a photo */
"PHOTO_CAPTURE_GENERIC_ERROR" = "Fallo al tomar foto.";
"PHOTO_CAPTURE_GENERIC_ERROR" = "Fallo al capturar la imagen.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Fallo al tomar foto.";
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Fallo al capturar la imagen.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Fallo al activar la cámara.";
/* label for system photo collections which have no name. */
@ -183,7 +181,7 @@
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Responder";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Autenticar para abrir Session.";
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Identifícate para acceder a Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Fallo al identificarse";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
@ -193,25 +191,25 @@
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (por defecto)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Notificaciones sonoras";
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Mensaje con sonido";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "Ninguno";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ días";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@ d";
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "%@ horas";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@ h";
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "%@ minutos";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@ m";
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "%@ segundos";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@ s";
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ día";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
@ -229,9 +227,9 @@
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Eliminar";
/* Filename for voice messages. */
"VOICE_MESSAGE_FILE_NAME" = "Nota de voz";
"VOICE_MESSAGE_FILE_NAME" = "Mensaje de voz";
/* Message for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Toca y mantén pulsado el icono del micrófono para grabar una nota de voz corta. Toca, arrastra hacia arriba y suelta para grabar notas de voz más largas.";
"VOICE_MESSAGE_TOO_SHORT_ALERT_MESSAGE" = "Toca y mantén presionado para enviar un mensaje de voz.";
/* Title for the alert indicating the 'voice message' needs to be held to be held down to record. */
"VOICE_MESSAGE_TOO_SHORT_ALERT_TITLE" = "Nota de voz";
/* Info Message when you disable disappearing messages */
@ -286,25 +284,23 @@
"vc_path_service_node_row_title" = "Nodo de Servicio";
"vc_path_destination_row_title" = "Destino";
"vc_path_learn_more_button_title" = "Saber Más";
"vc_create_private_chat_title" = "Nueva Session";
"vc_create_private_chat_title" = "Nuevo mensaje";
"vc_create_private_chat_enter_session_id_tab_title" = "Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Escanear código QR";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_enter_public_key_explanation" = "Empieza una nueva conversa poniendo el ID de sesión de alguien o comparte tu ID de sesión con ellos.";
"vc_scan_qr_code_camera_access_explanation" = "Session necesita acceso a la cámara para escanear códigos QR";
"vc_scan_qr_code_grant_camera_access_button_title" = "Permitir acceso a cámara";
"vc_create_closed_group_title" = "Nuevo grupo cerrado";
"vc_create_closed_group_title" = "Crear un grupo";
"vc_create_closed_group_text_field_hint" = "Ingresa un nombre de grupo";
"vc_create_closed_group_empty_state_message" = "Aún no tienes contactos";
"vc_create_closed_group_empty_state_button_title" = "Empezar una Session";
"vc_create_closed_group_group_name_missing_error" = "Por favor, ingresa un nombre de grupo";
"vc_create_closed_group_group_name_too_long_error" = "Por favor, ingresa un nombre de grupo más corto";
"vc_create_closed_group_too_many_group_members_error" = "Un grupo cerrado no puede tener más de 100 miembros";
"vc_join_public_chat_title" = "Únete al grupo abierto";
"vc_join_public_chat_enter_group_url_tab_title" = "URL de grupo abierto";
"vc_join_public_chat_title" = "Unirse a la comunidad";
"vc_join_public_chat_enter_group_url_tab_title" = "URL de la comunidad";
"vc_join_public_chat_scan_qr_code_tab_title" = "Escanear código QR";
"vc_enter_chat_url_text_field_hint" = "Ingresa una URL de grupo abierto";
"vc_enter_chat_url_text_field_hint" = "Introduzca el URL de la comunidad";
"vc_settings_title" = "Ajustes";
"vc_group_settings_title" = "Group Settings";
"vc_group_settings_title" = "Configuración del grupo";
"vc_settings_display_name_missing_error" = "Por favor, elige un nombre para mostrar";
"vc_settings_display_name_too_long_error" = "Por favor, elige un nombre para mostrar más corto";
"vc_settings_privacy_button_title" = "Privacidad";
@ -350,10 +346,10 @@
"vc_share_title" = "Compartir en Session";
"vc_share_loading_message" = "Preparando archivos adjuntos...";
"vc_share_sending_message" = "Enviando...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"vc_share_link_previews_unsecure" = "Vista previa no cargada por un enlace inseguro";
"vc_share_link_previews_error" = "No se puede cargar la previsualización";
"vc_share_link_previews_disabled_title" = "Previsualización de enlaces desactivada";
"vc_share_link_previews_disabled_explanation" = "Habilitar la previsualización de enlaces permitirá previsualizar URLs que compartas. Esto puede ser útil pero Session necesitará contactar sitios web vinculados para generar la previsualización.\n\nPuedes habilitar la previsualización de enlaces desde la sección de ajustes en Session.";
"view_open_group_invitation_description" = "Abrir invitación de grupo";
"vc_conversation_settings_invite_button_title" = "Añadir Miembros";
"modal_send_seed_title" = "Aviso";
@ -366,24 +362,23 @@
"delete_message_for_me" = "Eliminar solo para mí";
"delete_message_for_everyone" = "Eliminar para todos";
"delete_message_for_me_and_recipient" = "Eliminar para mí y para %@";
"context_menu_info" = "Info";
"context_menu_reply" = "Responder";
"context_menu_save" = "Guardar";
"context_menu_ban_user" = "Banear Usuario";
"context_menu_ban_and_delete_all" = "Banear y Eliminar Todo";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"context_menu_ban_user_error_alert_message" = "No es posible reportar al usuario";
"accessibility_expanding_attachments_button" = "Añadir adjuntos Añadir archivo adjunto";
"accessibility_gif_button" = "GIF";
"accessibility_document_button" = "Documento";
"accessibility_library_button" = "Fototeca";
"accessibility_camera_button" = "Cámara";
"accessibility_main_button_collapse" = "Collapse attachment options";
"accessibility_main_button_collapse" = "Colapsar opciones de adjuntar";
"invalid_recovery_phrase" = "Frase de Recuperación Incorrecta";
"DISMISS_BUTTON_TEXT" = "Descartar";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Ajustes";
"call_outgoing" = "Has llamado a %@";
"call_incoming" = "%@ called you";
"call_incoming" = "%@ te ha llamado";
"call_missed" = "Llamada Perdida de %@";
"APN_Message" = "Tienes un mensaje nuevo";
"APN_Collapsed_Messages" = "Tienes un mensaje nuevo.";
@ -391,260 +386,430 @@
"UNPIN_BUTTON_TEXT" = "Dejar de fijar";
"modal_call_missed_tips_title" = "Llamada perdida";
"modal_call_missed_tips_explanation" = "Llamada perdida de '%@' porque necesitas habilitar el permiso de 'Llamadas de voz y video' en la configuración de privacidad.";
"media_saved" = "Media saved by %@.";
"media_saved" = "Archivo guardado mediante %@.";
"screenshot_taken" = "%@ tomó una captura de pantalla.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_CONTACTS" = "Contactos & Grupos";
"SEARCH_SECTION_MESSAGES" = "Mensajes";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted.";
"MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request";
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Fallo";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
"MESSAGE_REQUESTS_TITLE" = "Peticiones de mensajes";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No hay solicitudes de mensajes pendientes";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Borrar todo";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "¿Estás seguro/a que quieres borrar todas las solicitudes de mensajes?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Borrar";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "¿Estás seguro de que quieres eliminar esta solicitud de mensaje?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "¿Estás seguro de que quieres bloquear este contacto?";
"MESSAGE_REQUESTS_INFO" = "Al enviar un mensaje a este usuario, automáticamente se aceptará su solicitud de mensaje y revelarás tu ID de Session.";
"MESSAGE_REQUESTS_ACCEPTED" = "Tu solicitud de mensaje ha sido aceptada.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Tienes una solicitud de mensaje nueva";
"TXT_HIDE_TITLE" = "Esconder";
"TXT_DELETE_ACCEPT" = "Aceptar";
"TXT_BLOCK_USER_TITLE" = "Bloquear Usuario";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Se requieren permisos de llamada";
"modal_call_permission_request_explanation" = "Puedes habilitar los permisos de \"llamada de voz y video\" en las Configuraciones de Privacidad.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Ups, se ha producido un error";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Inténtelo de nuevo más tarde";
"LOADING_CONVERSATIONS" = "Cargando Conversaciones...";
"DATABASE_MIGRATION_FAILED" = "Se ha producido un error al optimizar la base de datos\n\nPuedes exportar tus registros de aplicación para poder compartirlos para solucionar los problemas, o restaurar el dispositivo\n\nAdvertencia: Restaurar su dispositivo causará una pérdida de todos los datos que sean más antiguos a dos semanas";
"RECOVERY_PHASE_ERROR_GENERIC" = "Algo salió mal. Por favor revisa tu frase de recuperación y vuelve a intentarlo.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Parece que no has introducido suficientes palabras. Por favor comprueba tu frase de recuperación y vuelve a intentarlo.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Parece que falta la última palabra de tu frase de recuperación. Por favor compruébala e inténtalo de nuevo.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Parece que hay una palabra inválida en tu frase de recuperación. Por favor compruébala y vuelve a intentarlo.";
"RECOVERY_PHASE_ERROR_FAILED" = "Tu frase de recuperación no pudo ser verificada. Por favor compruébala y vuelve a intentarlo.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "No se ha podido acceder a la autenticación.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Fallo en la identificación.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Fallo al autenticarse.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Demasiados intentos fallidos. Prueda de nuevo más tarde.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Hubo demasiados intentos fallidos de autenticación. Por favor vuelve a intentarlo más tarde.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Tienes que habilitar un PIN en las configuraciones de tu iOS para poder usar el bloqueo de pantalla.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Debes habilitar un PIN en tus configuraciones de iOS para poder usar el bloqueo de pantalla.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Necesitas configurar un código en «Ajustes» de iOS para poder usar el bloqueo de acceso.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Debes habilitar un PIN en tus configuraciones de iOS para poder usar el bloqueo de pantalla.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
"SEND_BUTTON_TITLE" = "Enviar";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
"RETRY_BUTTON_TEXT" = "Reintentar";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
"SHOW_THREAD_BUTTON_TITLE" = "Mostrar Chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
"SEND_FAILED_NOTIFICATION_BODY" = "Hubo un error al enviar tu mensaje.";
"INVALID_SESSION_ID_MESSAGE" = "Por favor, comprueba el ID de Session y vuelve a intentarlo.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Por favor, comprueba la frase de recuperación y vuelve a intentarlo.";
"MEDIA_TAB_TITLE" = "Multimedia";
"DOCUMENT_TAB_TITLE" = "Documentos";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "No tienes ningún documento en esta conversación.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Cargando el documento más nuevo…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Cargando documento antiguo…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Actividades";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animales y Naturaleza";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
"EMOJI_CATEGORY_FLAGS_NAME" = "Banderas";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
"EMOJI_CATEGORY_FOOD_NAME" = "Comida y Bebida";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objetos";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
"EMOJI_CATEGORY_RECENTS_NAME" = "Recientes";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Caras y personas";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Símbolos";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
"EMOJI_CATEGORY_TRAVEL_NAME" = "Viajes y Lugares";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacciona a un mensaje con %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Y otro ha reaccionado %@ a este mensaje.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "Y %@ otros han reaccionado %@ a este mensaje.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "¡Relájate! Has enviado demasiadas reacciones. Inténtalo de nuevo más tarde.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"vc_new_conversation_title" = "Nueva conversación";
"CREATE_GROUP_BUTTON_TITLE" = "Crear";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Unirse";
"PRIVACY_TITLE" = "Privacidad";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Protección de pantalla";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Notificaciones de lectura";
"PRIVACY_READ_RECEIPTS_TITLE" = "Notificaciones de lectura";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indicador de tecleo";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indicador de tecleo";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Enviar previsualizaciones";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Seguridad de pantalla";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Bloquear Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Exigir Touch ID, Face ID o tu clave para desbloquear Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Confirmaciones de lectura";
"PRIVACY_READ_RECEIPTS_TITLE" = "Confirmaciones de lectura";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Enviar confirmaciones de lectura en chats individuales.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indicadores de escribiendo";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indicadores de escribiendo";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Ver y compartir el indicador de escritura en chats privados.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Previsualizar enlace";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Enviar vista previa de los enlaces";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Mostrar previsualización de enlaces para las URLs soportadas.";
"PRIVACY_SECTION_CALLS" = "Llamadas (beta)";
"PRIVACY_CALLS_TITLE" = "Llamadas de voz y video";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"PRIVACY_CALLS_DESCRIPTION" = "Habilita llamadas de voz y video hacia y desde otros usuarios.";
"PRIVACY_CALLS_WARNING_TITLE" = "Llamadas de Voz y Video (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Su dirección IP es visible para su socio de llamadas y un servidor de Oxen Fundación mientras usas llamadas beta. ¿Está seguro de que desea habilitar las llamadas de voz y videollamadas?";
"NOTIFICATIONS_TITLE" = "Notificaciones";
"NOTIFICATIONS_SECTION_STRATEGY" = "Estrategia de notificación";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Usar modo rápido";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Contenido de notificaciones";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Sólo remitente";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Ni remitente ni contenido";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Usar Modo Rápido";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Se le notificará de los nuevos mensajes de forma fiable e inmediata usando los servidores de notificaciones de Apple.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Ir a la configuración de notificaciones del dispositivo";
"NOTIFICATIONS_SECTION_STYLE" = "Estilo de notificación";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Audio";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sonido al abrir la aplicación";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Contenido de las notificaciones";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Información mostrada en las notificaciones.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Nombre y contenido";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Sólo nombre";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Sin nombre ni contenido";
"CONVERSATION_SETTINGS_TITLE" = "Conversaciones";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Acortado del mensaje";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Acortar comunidades";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Eliminar mensajes de hace más de 6 meses en comunidades con más de 2.000 mensajes.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Mensajes de audio";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Reproducir automáticamente los mensajes de audio";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Reproducir automáticamente mensajes de audio consecutivos.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Contactos bloqueados";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "No hay contactos bloqueados.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Desbloquear";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "¿Seguro que quieres desbloquear a %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "este contacto";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "¿Seguro que quieres desbloquear a %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "y %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "y a %d más?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Desbloquear";
"APPEARANCE_TITLE" = "Apariencia";
"APPEARANCE_THEMES_TITLE" = "Temas";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Color primario";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "¿Cómo estás?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Estoy bien, ¿y tú?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Estoy bien, gracias.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Modo nocturno automático";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Coincidir ajustes del sistema";
"HELP_TITLE" = "Ayuda";
"HELP_REPORT_BUG_TITLE" = "Reportar un problema";
"HELP_REPORT_BUG_DESCRIPTION" = "Exporta tus registros, luego sube el archivo a través del Help Desk de Session.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Exportar logs";
"HELP_TRANSLATE_TITLE" = "Traducir Session";
"HELP_FEEDBACK_TITLE" = "Nos encantaría conocer tu opinión";
"HELP_FAQ_TITLE" = "Preguntas Frecuentes";
"HELP_SUPPORT_TITLE" = "Support";
"HELP_SUPPORT_TITLE" = "Soporte";
"modal_clear_all_data_title" = "Borrar todos los datos";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"modal_clear_all_data_explanation" = "Esto eliminará permanentemente tus mensajes y contactos. ¿Quieres borrar solo este dispositivo o borrar también tus datos de la red?";
"modal_clear_all_data_explanation_2" = "¿Está seguro que desea eliminar sus datos de la red? Si continúa, no podrá restaurar sus mensajes o contactos.";
"modal_clear_all_data_device_only_button_title" = "Borrar solo dispositivo";
"modal_clear_all_data_entire_account_button_title" = "Borrar dispositivo y red";
"dialog_clear_all_data_deletion_failed_1" = "Datos no borrados por 1 nodo de servicio. ID del nodo de servicio: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Datos no borrados por %@ nodos de servicio. ID del nodo de servicio: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_clear_all_data_confirm" = "Borrar";
"modal_seed_title" = "Tu frase de recuperación";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"modal_seed_explanation" = "Puede utilizar su frase de recuperación para restaurar su cuenta o vincular un dispositivo.";
"modal_permission_explanation" = "Session necesita acceso %@ para continuar. Puedes habilitar el acceso en los ajustes de iOS.";
"modal_permission_settings_title" = "Ajustes";
"modal_permission_camera" = "cámara";
"modal_permission_microphone" = "micrófono";
"modal_permission_library" = "fototeca";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
"MESSAGE_INFO_SENT" = "Sent";
"MESSAGE_INFO_RECEIVED" = "Received";
"MESSAGE_INFO_FROM" = "From";
"ATTACHMENT_INFO_FILE_ID" = "File ID";
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
"ATTACHMENT_INFO_DURATION" = "Duration";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Desaparecer después de %@";
"COPY_GROUP_URL" = "Copiar URL del grupo";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contactos";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Elige al menos 1 miembro del grupo";
"GROUP_CREATION_PLEASE_WAIT" = "El grupo se está creando...";
"GROUP_CREATION_ERROR_TITLE" = "No se pudo crear el grupo";
"GROUP_CREATION_ERROR_MESSAGE" = "Por favor, compruebe su conexión a internet e inténtelo de nuevo.";
"GROUP_UPDATE_ERROR_TITLE" = "No se pudo actualizar el grupo";
"GROUP_UPDATE_ERROR_MESSAGE" = "No se puede salir mientras se agregan o eliminan miembros.";
"GROUP_ACTION_REMOVE" = "Eliminar";
"GROUP_TITLE_MEMBERS" = "Miembros";
"GROUP_TITLE_FALLBACK" = "Grupo";
"DM_ERROR_DIRECT_BLINDED_ID" = "Solo puede enviar mensajes a ID encubiertos desde dentro de una comunidad";
"DM_ERROR_INVALID" = "Por favor, compruebe el ID de Session o el nombre ONS e inténtelo de nuevo";
"COMMUNITY_ERROR_INVALID_URL" = "Por favor, compruebe el URL que ha introducido y vuelve a intentarlo.";
"COMMUNITY_ERROR_GENERIC" = "Error al unirse";
"DISAPPERING_MESSAGES_TITLE" = "Desaparición de mensajes";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Tipo de borrado";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Desaparece tras leerlo";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Los mensajes se borran después de haber sido leídos.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Desaparece tras enviarlo";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Los mensajes se borran después de haber sido enviados.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Cronómetro";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Definir";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Esta opción se aplica a todos los usuarios en esta conversación.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Esta opción se aplica a todos los usuarios en esta conversación.\nSolo los administradores del grupo la pueden cambiar.";
"DISAPPERING_MESSAGES_SUMMARY" = "Desaparece tras %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ ha establecido que los mensajes desaparezcan %@ tras haber sido %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ ha cambiado que los mensajes desaparezcan %@ tras haber sido %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ ha desactivado la desaparición de mensajes";
/* context_menu_info */
"context_menu_info" = "Información";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "Se ha producido un error al abrir la base de datos\n\nPuedes exportar tus registros de aplicación para compartirlos y solucionar los problemas, o restaurar el dispositivo\n\nAdvertencia: Restaurar su dispositivo causará una pérdida de todos los datos que sean más antiguos a dos semanas";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "La aplicación está tardando mucho tiempo para iniciar\n\nPuedes continuar esperando a que la aplicación se inicie, exportar los registros de tu aplicación y compartirlos para solucionar los problemas o puedes intentar volver a abrir la aplicación";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Salir";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "Se ha producido un error al abrir la base de datos restaurada\n\nPuede exportar los registros de su aplicación para compartir y solucionar problemas, pero para continuar usando Session puede que necesite reinstalarlo";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "No se encontró el mensaje original.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Ver menos";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Solicitudes de mensajes";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Solicitudes de mensaje de la comunidad";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Permitir peticiones de mensajes de conversaciones comunitarias.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "Podrás enviar mensajes de voz y archivos adjuntos cuando el destinatario haya aprobado esta solicitud de mensaje";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Enviando";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Enviado";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Leído";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Fallo al enviar";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Enviado";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Recibido";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "De";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "ID de archivo";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "Tipo de archivo";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "Tamaño del archivo";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolución";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duración";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Versión original de los mensajes desaparecidos.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ está usando un cliente desactualizado. Los mensajes que desaparecen pueden no funcionar correctamente.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "Estás intentando actualizar desde una versión que ya no soporta actualizar\n\nPara continuar usando Session, necesitas restaurar tu dispositivo\n\nAdvertencia: Restaurar tu dispositivo causará la pérdida de cualquier información anterior a dos semanas";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "leído";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "enviado";

View File

@ -17,7 +17,7 @@
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "امکان تبدیل تصویر وجود ندارد.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "مشکل در پردازش ویدئو.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "پردازش ویدئو امکان‌پذیر نیست.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "قادر به تجزیه تصویر نیست.";
/* Attachment error message for image attachments in which metadata could not be removed */
@ -31,7 +31,7 @@
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "فایل پیوستی، فرمت نامعتبر دارد.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "فایل پیوستی خالی می‌باشد.";
"ATTACHMENT_ERROR_MISSING_DATA" = "فایل پیوست شده خالی است.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "خطا در انتخاب سند.";
/* Alert body when picking a document fails because user picked a directory/bundle */
@ -45,9 +45,9 @@
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "%@ مسدود شود؟";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "%@ از حالت مسدود خارج شود؟";
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "%@از حالت مسدود خارج شود؟";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "دفع مسدودیت";
"BLOCK_LIST_UNBLOCK_BUTTON" = "آزادسازی کاربر";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ مسدود شد.";
/* The title of the 'user blocked' alert. */
@ -63,11 +63,11 @@
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "درحال جستجو...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "مشابهی یافت نشد";
"CONVERSATION_SEARCH_NO_RESULTS" = "مورد مشابهی یافت نشد";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "۱ مورد";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d از %d مورد یافت شد";
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d مورد مشابه با %d یافت شد";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "مسدود کردن کاربر";
/* label for 'mute thread' cell in conversation settings */
@ -75,21 +75,21 @@
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "جستجو در مکالمه";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "حرکت و مقیاس";
"CROP_SCALE_IMAGE_VIEW_TITLE" = "حرکت و تغییر سایز";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "ممکن است چند دقیقه زمان ببرد.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "در حال بهینه‌سازی پایگاه داده";
"DATABASE_VIEW_OVERLAY_TITLE" = "بهینه‌سازی پایگاه‌داده ها";
/* The present; the current time. */
"DATE_NOW" = "الان";
"DATE_NOW" = "هم اکنون";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "پیام‌های محوشونده";
"DISAPPEARING_MESSAGES" = "ناپدید کردن پیام ها";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "ویرایش گروه";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "شما در این مکالمه هیچ مدیایی ندارید.";
"GALLERY_TILES_EMPTY_GALLERY" = "شما در این مکالمه هیچ محتوای تصویری ندارید.";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "در حال بارگذاری مدیا جدیدتر...";
"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "در حال بارگذاری محتوای تصویری جدیدتر...";
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "بارگذاری مدیا قدیمی تر...";
/* Error displayed when there is a failure fetching a GIF from the remote service. */
@ -97,17 +97,17 @@
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "یک خطای ناشناخته رخ داد.";
/* Shown when selected GIF couldn't be fetched */
"GIF_PICKER_FAILURE_ALERT_TITLE" = "خطا در انتخاب گیف";
"GIF_PICKER_FAILURE_ALERT_TITLE" = "خطا در انتخاب فایل تصویری متحرک";
/* Alert message shown when user tries to search for GIFs without entering any search terms. */
"GIF_PICKER_VIEW_MISSING_QUERY" = "عبارت مورد نظر خود را وارد کنید.";
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "ایراد. برای تلاش دوباره لمس کنید.";
"GIF_VIEW_SEARCH_ERROR" = "خطا. برای تلاش دوباره لمس کنید.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "نتیجه‌ای یافت نشد.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "گروه ساخته شد.";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ به گروه اضافه شد. ";
"GROUP_MEMBER_JOINED" = "%@ به گروه اضافه شد.";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ از گروه خارج شد. ";
/* No comment provided by engineer. */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "ترک کردن گروه";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "تمام مدیا";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "گالری";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "حذف %d پیام";
/* Confirmation button text to delete selected media message from the gallery */
@ -291,11 +289,9 @@
"vc_create_private_chat_scan_qr_code_tab_title" = "اسکن کد QR";
"vc_enter_public_key_explanation" = "یک مکالمه جدید را با وارد کردن شناسه Session شخصی شروع کنید یا شناسه جلسه خود را با آنها به اشتراک بگذارید.";
"vc_scan_qr_code_camera_access_explanation" = "برای اسکن کدهای Session ،QR نیاز به دسترسی به دوربین دارد";
"vc_scan_qr_code_grant_camera_access_button_title" = "اعطای دسترسی دوربین";
"vc_create_closed_group_title" = "ایجاد گروه";
"vc_create_closed_group_text_field_hint" = "وارد کردن یک نام گروه";
"vc_create_closed_group_empty_state_message" = "هنوز هیچ مخاطبی ندارید";
"vc_create_closed_group_empty_state_button_title" = "شروع یک Session";
"vc_create_closed_group_group_name_missing_error" = "لطفاً یک نام گروه را وارد کنید";
"vc_create_closed_group_group_name_too_long_error" = "لطفاً یک نام گروه کوتاه‌تر را وارد کنید";
"vc_create_closed_group_too_many_group_members_error" = "یک گروه نمی‌تواند بیش از ۱۰۰ عضو داشته باشد.";
@ -304,7 +300,7 @@
"vc_join_public_chat_scan_qr_code_tab_title" = "اسکن کد QR";
"vc_enter_chat_url_text_field_hint" = "URL انجمن را وارد کنید";
"vc_settings_title" = "تنظیمات";
"vc_group_settings_title" = "Group Settings";
"vc_group_settings_title" = "تنظیمات گروه";
"vc_settings_display_name_missing_error" = "لطفا یک نام نمایشی را انتخاب کنید";
"vc_settings_display_name_too_long_error" = "لطفا یک نام نمایشی کوتاه‌تر انتخاب کنید";
"vc_settings_privacy_button_title" = "حریم خصوصی";
@ -355,7 +351,7 @@
"vc_share_link_previews_disabled_title" = "پیش نمایش های لینک غیرفعال شد";
"vc_share_link_previews_disabled_explanation" = "با فعال کردن این گزینه، پیش‌نمایش لینک‌ها در پیام‌های ارسالی و دریافتی دیده می‌شود. این گزینه می‌تواند مفید باشد اما Session باید با سایت ها ارتباط برقرار کند تا پیش‌نمایش را نشان دهد. n\\شما می‌توانید در تنظیمات این پیش‌نمایش را غیرفعال کنید.";
"view_open_group_invitation_description" = "باز کردن دعوت به گروه";
"vc_conversation_settings_invite_button_title" = "اضافه‌کردن اعضا";
"vc_conversation_settings_invite_button_title" = "افزودن اعضا";
"modal_send_seed_title" = "هشدار";
"modal_send_seed_explanation" = "این عبارت بازیابی شماست. اگر آن را برای شخصی ارسال کنید ، دسترسی کامل به حساب شما خواهد داشت.";
"modal_send_seed_send_button_title" = "ارسال";
@ -366,7 +362,6 @@
"delete_message_for_me" = "حذف برای من";
"delete_message_for_everyone" = "حذف برای همه";
"delete_message_for_me_and_recipient" = "حذف برای من و %@";
"context_menu_info" = "Info";
"context_menu_reply" = "پاسخ";
"context_menu_save" = "ذخیره";
"context_menu_ban_user" = "مسدود کردن کاربر";
@ -394,7 +389,7 @@
"media_saved" = "تصویر/ ویدیو توسط %@ ذخیره شد.";
"screenshot_taken" = "%@ از صفحه یک عکس گرفته است.";
"SEARCH_SECTION_CONTACTS" = "گروه‌ها و مخاطبین";
"SEARCH_SECTION_MESSAGES" = "پیامها";
"SEARCH_SECTION_MESSAGES" = "پیام ها";
"MESSAGE_REQUESTS_TITLE" = "درخواست های پیام";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "هیچ درخواست پیامی وجود ندارد";
"MESSAGE_REQUESTS_CLEAR_ALL" = "حذف همه";
@ -411,13 +406,9 @@
"ALERT_ERROR_TITLE" = "خطا";
"modal_call_permission_request_title" = "دسترسی تلفن مورد نیاز است";
"modal_call_permission_request_explanation" = "شما می‌توانید مجوز «تماس صوتی و تصویری» را در تنظیمات حریم خصوصی فعال کنید.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "متاسفانه خطایی رخ داده است";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "لطفا بعدا دوباره تلاش کنید";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "اوخ، یک خطا اتفاق افتاد";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "لطفاً مجدداً تلاش نمایید";
"LOADING_CONVERSATIONS" = "درحال بارگزاری پیام ها...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "هنگام بهینه‌سازی پایگاه داده خطایی روی داد\n\nشما می‌توانید گزارش‌های برنامه خود را صادر کنید تا بتوانید برای عیب‌یابی به اشتراک بگذارید یا می‌توانید دستگاه خود را بازیابی کنید\n\nهشدار: بازیابی دستگاه شما منجر به از دست رفتن داده‌های قدیمی‌تر از دو هفته می‌شود.";
"RECOVERY_PHASE_ERROR_GENERIC" = "مشکلی پیش آمد. لطفاً عبارت بازیابی خود را بررسی کنید و دوباره امتحان کنید.";
"RECOVERY_PHASE_ERROR_LENGTH" = "به نظر می رسد کلمات کافی وارد نکرده اید. لطفاً عبارت بازیابی خود را بررسی کنید و دوباره امتحان کنید.";
@ -433,9 +424,9 @@
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "برای استفاده از قفل صفحه نمایش می بایستی یک رمزعبور از تنظیمات iOS خود فعال کنید.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "باید ابتدا رمز عبور را در تنظیمات دستگاه فعال کنید تا بتوانید از قفل صفحه استفاده کنید.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "شما برای استفاده از قفل صفحه نمایس می بایستی یک رمزعبور از تنظیمات iOS خود فعال کنید.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "برای استفاده از قفل صفحه نمایش می بایستی یک رمزعبور از تنظیمات iOS خود فعال کنید.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "برای استفاده از قفل صفحه نمایش می بایستی یک رمزعبور از تنظیمات iOS فعال کنید.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "ارسال";
/* Generic text for button that retries whatever the last action was. */
@ -446,7 +437,6 @@
"SEND_FAILED_NOTIFICATION_BODY" = "پیام شما ارسال نشد.";
"INVALID_SESSION_ID_MESSAGE" = "لطفاً شناسه Session را مجدد بررسی کنید.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "لطفاً شناسه بازیابی را مجدد بررسی کنید.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "مدیا";
"DOCUMENT_TAB_TITLE" = "مدارک";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "شما در این مکالمه هیچ مدرکی ندارید.";
@ -473,15 +463,14 @@
"EMOJI_REACTS_NOTIFICATION" = "%@ به پیامی با %@ واکنش نشان می‌دهد. ";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "و ۱ نفر دیگر به این پیام واکنش %@ نشان داده است.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "و %@ نفر دیگر به این پیام واکنش %@ نشان داده‌اند.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "آهسته! شما بیش از اندازه ایموجی واکنش ارسال کرده اید. بزودی دوباره تلاش کنید.";
/* New conversation screen*/
"vc_new_conversation_title" = "مکالمه جدید";
"CREATE_GROUP_BUTTON_TITLE" = "ایجاد";
"JOIN_COMMUNITY_BUTTON_TITLE" = "محلق شدن";
"PRIVACY_TITLE" = "حریم خصوصی";
"PRIVACY_SECTION_SCREEN_SECURITY" = "امنیت صفحه";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "قفل Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "قفل سیسشن";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = " برای باز کردن قفل Session به شناسه لمسی، شناسه صورت و یا رمز عبوری ضرورت است.";
"PRIVACY_SECTION_READ_RECEIPTS" = "رسیدهای خواندن";
"PRIVACY_READ_RECEIPTS_TITLE" = "رسیدهای خواندن";
@ -573,7 +562,7 @@
"GROUP_TITLE_FALLBACK" = "گروه";
"DM_ERROR_DIRECT_BLINDED_ID" = "فقط از داخل یک انجمن می‌توانید به شناسه‌های نابینا پیام ارسال کنید";
"DM_ERROR_INVALID" = "لطفاً شناسه Session یا نام ONS را بررسی کنید و دوباره امتحان کنید";
"COMMUNITY_ERROR_INVALID_URL" = "";
"COMMUNITY_ERROR_INVALID_URL" = "لطفا لینک وارد شده را بررسی نموده و دوباره تلاش کنید.";
"COMMUNITY_ERROR_GENERIC" = "نمی‌توانید محلق شوید";
"DISAPPERING_MESSAGES_TITLE" = "پیام‌ها ناپدید میشوند";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "حذف تایپ";
@ -589,62 +578,238 @@
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ تنظیم کرده تا پیام‌ها %@ پس از آنکه %@ شدند، ناپدید شوند.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ پیام‌ها را تغییر داده تا %@ پس از آنکه %@ شدند، ناپدید شوند.";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ ناپدید‌شدن پیام ها را خاموش کرده است";
"MESSAGE_STATE_READ" = "خوانده شد";
"MESSAGE_STATE_SENT" = "ارسال شد";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -1,11 +1,11 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "Lisää liite";
"ATTACHMENT" = "Liite";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Otsikko";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Tiedoston formaatti: %@";
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Tiedostotyyppi: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Rajoitettu koko: %@";
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Koko: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Viestin suurin sallittu pituus saavutettu";
/* Label for 'send' button in the 'attachment approval' dialog. */
@ -15,15 +15,15 @@
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Virhe liitteen lähettämisessä";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Kuvaa ei voitu muuntaa.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Kuvan muunto ei onnistu.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Videon prosessointi ei onnistu.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Videon käsittely ei onnistu.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Kuvaa ei voitu jäsentää.";
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Kuvan jäsennys ei onnistu.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Metadatan poistaminen kuvasta epäonnistui.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Kuvan kokoa ei voitu muuttaa.";
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Kuvan koon muutos ei onnistu.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Liite on liian iso.";
/* Attachment error message for attachments with invalid data */
@ -43,25 +43,25 @@
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Estä";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Estä %@?";
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Estetäänkö %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Poista henkilön %@ esto?";
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Poistetaanko käyttäjän %@ esto?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Poista esto";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ on estetty.";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Käyttäjä estetty";
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Käyttäjä estettiin";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Henkilön %@ esto on poistettu.";
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "Käyttäjän %@ esto poistettiin.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Estetyt käyttäjät eivät voi soittaa sinulle tai lähettää sinulle viestejä.";
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Estetyt käyttäjät eivät voi soittaa tai lähettää sinulle viestejä.";
/* Label for generic done button. */
"BUTTON_DONE" = "Valmis";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Valitse";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
"CONVERSATION_SEARCH_SEARCHING" = "Etsitään...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "Ei tuloksia";
/* keyboard toolbar label when exactly 1 message matches the search string */
@ -69,7 +69,7 @@
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d/%d osumasta";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Estä tämä käyttäjä";
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Estä käyttäjä";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Hiljennä";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "Poistu ryhmästä";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Kaikki media";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Kuvakirjasto";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Poista %d viestiä";
/* Confirmation button text to delete selected media message from the gallery */
@ -241,44 +239,44 @@
// MARK: - Session
"continue_2" = "Jatka";
"copy" = "Kopioi";
"invalid_url" = "Virheellinen URL";
"invalid_url" = "Virheellinen URL-osoite";
"next" = "Seuraava";
"share" = "Jaa";
"invalid_session_id" = "Virheellinen Session ID";
"cancel" = "Peruuta";
"your_session_id" = "Sinun Session ID";
"vc_landing_title_2" = "Sinun sessio alkaa tästä...";
"your_session_id" = "Oma Session ID";
"vc_landing_title_2" = "Sessionisi alkaa tästä...";
"vc_landing_register_button_title" = "Luo Session ID";
"vc_landing_restore_button_title" = "Jatka Sessionin käyttöä";
"vc_landing_link_button_title" = "Yhdistä laite";
"vc_landing_link_button_title" = "Liitä laite";
"view_fake_chat_bubble_1" = "Mikä on Session?";
"view_fake_chat_bubble_2" = "Se on hajautettu sekä salattu viestipalvelu";
"view_fake_chat_bubble_3" = "Joten se ei kerää henkilökohtaisia tietojani tai keskustelujeni metadataa? Miten se sitten toimii?";
"view_fake_chat_bubble_4" = "Yhdistämällä edistynyttä reititys- ja salausteknologiaa päästä päätyyn.";
"view_fake_chat_bubble_5" = "Kaverit eivät anna kavereiden käyttää vaarantuneita viestipalveluita. Oleppa hyvä.";
"vc_register_title" = "Sano terve sinun Session ID:lle";
"vc_register_explanation" = "Session ID on sinun ainutlaatuinen osoite, jolla ihmiset voivat ottaa sinuun yhteyttä; ilman yhteyttä oikeaan identiteettiisi. Session ID on luonteeltaan täysin anonyymi ja yksityinen.";
"vc_restore_title" = "Palauta käyttäjätilisi";
"vc_restore_explanation" = "Palauttaaksesi tilisi, syötä palautusvirke, joka annettiin sinulle kun loit tämän tilin.";
"vc_restore_seed_text_field_hint" = "Syötä palautusvirkkeesi";
"vc_link_device_title" = "Yhdistä laite";
"vc_link_device_scan_qr_code_tab_title" = "Skannaa QR-koodi";
"vc_display_name_title_2" = "Valitse julkinen nimi";
"vc_display_name_explanation" = "Tämä on nimesi kun käytät Sessionia. Se voi olla oikea nimesi, alias tai halutessasi jotain ihan muuta.";
"vc_display_name_text_field_hint" = "Syötä julkinen nimi";
"vc_display_name_display_name_missing_error" = "Ole hyvä ja valitse julkinen nimi";
"vc_display_name_display_name_too_long_error" = "Ole hyvä ja valitse lyhyempi julkinen nimi";
"vc_register_title" = "Tervehdi Session ID:täsi";
"vc_register_explanation" = "Session ID on yksilöllinen osoite, jonka avulla muut voivat ottaa sinuun yhteyttä Sessionissa. Sillä ei ole yhteyttä todelliseen identiteettiisi ja se on suunniteltu täysin anonyymiksi ja yksityiseksi.";
"vc_restore_title" = "Palauta tilisi";
"vc_restore_explanation" = "Palauta tilisi syöttämällä palautuslauseke, jonka sait rekisteröitymisen yhteydessä.";
"vc_restore_seed_text_field_hint" = "Syötä palautuslausekkeesi";
"vc_link_device_title" = "Liitä laite";
"vc_link_device_scan_qr_code_tab_title" = "Lue QR-koodi";
"vc_display_name_title_2" = "Valitse näyttönimi";
"vc_display_name_explanation" = "Tämä on nimesi, kun käytät Sessionia. Se voi olla oikea nimesi, kutsumanimi tai mitä tahansa muuta haluat.";
"vc_display_name_text_field_hint" = "Syötä näyttönimi";
"vc_display_name_display_name_missing_error" = "Valitse näyttönimi";
"vc_display_name_display_name_too_long_error" = "Valitse lyhyempi näyttönimi";
"vc_pn_mode_recommended_option_tag" = "Suositeltu";
"vc_pn_mode_no_option_picked_modal_title" = "Ole hyvä ja valitse vaihtoehto";
"vc_home_empty_state_message" = "Sinulla ei ole vielä yhtään keskustelua";
"vc_home_empty_state_message" = "Sinulla ei ole yhteystietoja";
"vc_home_empty_state_button_title" = "Aloita keskustelu";
"vc_seed_title" = "Palautusvirkkeesi";
"vc_seed_title_2" = "Tapaa palautusvirkkeesi";
"vc_seed_explanation" = "Palautusvirkkeesi on sinun Session ID:n pääavain — voit palauttaa sillä Session ID:n, jos menetät pääsyn laitteeseesi. Sijoita palautusvirkkeesi turvalliseen paikkaan äläkä anna sitä kellekkään.";
"vc_seed_reveal_button_title" = "Pidä pohjassa paljastaaksesi";
"view_seed_reminder_subtitle_1" = "Turvaa tilisi ottamalla palautusvirkkeesi ylös";
"view_seed_reminder_subtitle_2" = "Paina ja pidä painettuna piilotettuja sanoja paljastaaksesi palautusvirkkeesi. Ota ne ylös ja sijoita turvalliseen paikkaan turvataksesi Session ID:si.";
"view_seed_reminder_subtitle_3" = "Varmista, että säilytät palautusvirkkeesi turvallisessa paikassa";
"vc_seed_title" = "Palautuslausekkeesi";
"vc_seed_title_2" = "Tutustu palautuslausekkeeseesi";
"vc_seed_explanation" = "Palautuslausekkeesi on Session ID -tunnuksesi pääavain, jonka avulla voit palauttaa ID:si, jos menetät pääsyn laitteeseesi. Säilytä palautuslausekkeesi turvallisesti, äläkä luovuta sitä muille.";
"vc_seed_reveal_button_title" = "Paljasta pitämällä pohjassa";
"view_seed_reminder_subtitle_1" = "Suojaa tilisi tallentamalla palautuslausekkeesi";
"view_seed_reminder_subtitle_2" = "Paljasta palautuslausekkeesi pitämällä piilotettuja sanoja painettuna ja tallenna se turvallisesti suojataksesi Session ID:si.";
"view_seed_reminder_subtitle_3" = "Varmista, että säilytät palautuslausekkeesi turvallisessa paikassa";
"vc_path_title" = "Polku";
"vc_path_explanation" = "Session piilottaa IP-osoitteesi ohjaamalla viestisi monen välittäjäreleen läpi Sessionin hajautetussa verkossa. Tässä ovat maat joiden kautta viestisi tällä hetkellä kulkevat:";
"vc_path_device_row_title" = "Sinä";
@ -286,78 +284,76 @@
"vc_path_service_node_row_title" = "Välittäjärele";
"vc_path_destination_row_title" = "Määränpää";
"vc_path_learn_more_button_title" = "Opi lisää";
"vc_create_private_chat_title" = "Uusi keskustelu";
"vc_create_private_chat_title" = "Uusi viesti";
"vc_create_private_chat_enter_session_id_tab_title" = "Syötä Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Skannaa QR-koodi";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session tarvitsee kameraa skannatakseen QR-koodeja";
"vc_scan_qr_code_grant_camera_access_button_title" = "Anna kameran käyttölupa";
"vc_create_closed_group_title" = "Uusi yksityinen ryhmä";
"vc_create_private_chat_scan_qr_code_tab_title" = "Lue QR-koodi";
"vc_enter_public_key_explanation" = "Aloita uusi keskustelu syöttämällä käyttäjän Session ID tai jaa oma ID:si heille.";
"vc_scan_qr_code_camera_access_explanation" = "Session tarvitsee QR-koodien lukua varten kameran käyttöoikeuden";
"vc_create_closed_group_title" = "Luo ryhmä";
"vc_create_closed_group_text_field_hint" = "Anna ryhmälle nimi";
"vc_create_closed_group_empty_state_message" = "Sinulla ei ole vielä yhtään keskustelua";
"vc_create_closed_group_empty_state_button_title" = "Aloita keskustelu";
"vc_create_closed_group_group_name_missing_error" = "Anna ryhmälle nimi";
"vc_create_closed_group_empty_state_message" = "Sinulla ei ole yhteystietoja";
"vc_create_closed_group_group_name_missing_error" = "Syötä ryhmän nimi";
"vc_create_closed_group_group_name_too_long_error" = "Anna ryhmälle lyhyempi nimi";
"vc_create_closed_group_too_many_group_members_error" = "Yksityisessä ryhmässä voi olla enintään 100 jäsentä";
"vc_join_public_chat_title" = "Liity julkiseen ryhmään";
"vc_join_public_chat_enter_group_url_tab_title" = "Julkisen ryhmän URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Skannaa QR-koodi";
"vc_enter_chat_url_text_field_hint" = "Syötä julkisen ryhmän URL";
"vc_create_closed_group_too_many_group_members_error" = "Suljetussa ryhmässä voi olla enintään 100 jäsentä";
"vc_join_public_chat_title" = "Liity yhteisöön";
"vc_join_public_chat_enter_group_url_tab_title" = "Yhteisön URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Lue QR-koodi";
"vc_enter_chat_url_text_field_hint" = "Syötä yhteisön URL-osoite";
"vc_settings_title" = "Asetukset";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Ole hyvä ja valitse julkinen nimi";
"vc_settings_display_name_too_long_error" = "Ole hyvä ja valitse lyhyempi julkinen nimi";
"vc_group_settings_title" = "Ryhmäasetukset";
"vc_settings_display_name_missing_error" = "Valitse näyttönimi";
"vc_settings_display_name_too_long_error" = "Valitse lyhyempi näyttönimi";
"vc_settings_privacy_button_title" = "Yksityisyys";
"vc_settings_notifications_button_title" = "Ilmoitukset";
"vc_settings_recovery_phrase_button_title" = "Palautusvirke";
"vc_settings_clear_all_data_button_title" = "Tyhjennä kaikki data";
"vc_settings_recovery_phrase_button_title" = "Palautuslauseke";
"vc_settings_clear_all_data_button_title" = "Tyhjennä tiedot";
"vc_qr_code_title" = "QR-koodi";
"vc_qr_code_view_my_qr_code_tab_title" = "Näytä QR-koodini";
"vc_qr_code_view_scan_qr_code_tab_title" = "Skannaa QR-koodi";
"vc_qr_code_view_scan_qr_code_explanation" = "Skannaa jonkun QR-koodi aloittaaksesi keskustelu heidän kanssaan";
"vc_view_my_qr_code_explanation" = "Tämä on QR-koodisi. Muut käyttäjät voivat skannata sen aloittaakseen keskustelun kanssasi.";
"vc_qr_code_view_my_qr_code_tab_title" = "Näytä oma QR-koodi";
"vc_qr_code_view_scan_qr_code_tab_title" = "Lue QR-koodi";
"vc_qr_code_view_scan_qr_code_explanation" = "Aloita keskustelu jonkun kanssa lukemalla heidän QR-koodinsa";
"vc_view_my_qr_code_explanation" = "Tämä on QR-koodisi. Muut käyttäjät voivat aloittaa keskustelun kanssasi lukemalla sen.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Sinulle ilmoitetaan uusista viesteistä luotettavasti ja viivyttelemättä Applen ilmoituspalvelua käyttäen.";
"fast_mode" = "Nopeasti";
"slow_mode_explanation" = "Session tarkistaa taustalla ajoittain uudet viestit.";
"slow_mode" = "Hitaasti";
"vc_pn_mode_title" = "Viesti-ilmoitukset";
"vc_link_device_recovery_phrase_tab_title" = "Palautusvirke";
"vc_link_device_scan_qr_code_explanation" = "Siirry asetuksiin → palautusvirke toisella laitteellasi näyttääksesi QR-koodisi.";
"vc_enter_recovery_phrase_title" = "Palautusvirke";
"vc_enter_recovery_phrase_explanation" = "Yhdistääksesi laitteesi, anna palautusvirke, jonka sait rekisteröitymisen yhteydessä.";
"vc_link_device_recovery_phrase_tab_title" = "Palautuslauseke";
"vc_link_device_scan_qr_code_explanation" = "Avaa Asetukset → Palautuslauseke toisella laitteellasi nähdäksesi QR-koodisi.";
"vc_enter_recovery_phrase_title" = "Palautuslauseke";
"vc_enter_recovery_phrase_explanation" = "Yhdistä laitteesi syöttämällä palautuslauseke, jonka sait rekisteröitymisen yhteydessä.";
"vc_enter_public_key_text_field_hint" = "Syötä Session ID tai ONS-nimi";
"admin_group_leave_warning" = "Koska loit tämän ryhmän, se poistetaan kaikilta. Tätä ei voi peruuttaa.";
"vc_join_open_group_suggestions_title" = "Tai liity yhteen näistä...";
"admin_group_leave_warning" = "Koska olet ryhmän luoja, poistetaan se kaikilta. Tämä ei ole peruttavissa.";
"vc_join_open_group_suggestions_title" = "Tai liity johonkin näistä...";
"vc_settings_invite_a_friend_button_title" = "Kutsu ystäviä";
"copied" = "Kopioitu";
"vc_conversation_settings_copy_session_id_button_title" = "Kopioi Session ID";
"vc_conversation_input_prompt" = "Viesti";
"vc_conversation_voice_message_cancel_message" = "Liuuta peruuttaaksesi";
"modal_download_attachment_title" = "Luotatko henkilöön %@?";
"modal_download_attachment_explanation" = "Oletko varma, että haluat ladata henkilön %@ lähettämää mediaa?";
"modal_download_attachment_explanation" = "Haluatko varmasti ladata käyttäjän %@ lähettämän median?";
"modal_download_button_title" = "Lataa";
"modal_open_url_title" = "Avataanko URL?";
"modal_open_url_explanation" = "Oletko varma, että haluat avata linkin %@?";
"modal_open_url_explanation" = "Haluatko varmasti avata osoitteen %@?";
"modal_open_url_button_title" = "Avaa";
"modal_copy_url_button_title" = "Kopioi Linkki";
"modal_blocked_title" = "Poistetaanko esto henkilöltä %@?";
"modal_blocked_explanation" = "Oletko varma, että haluat poistaa eston henkilöltä %@?";
"modal_copy_url_button_title" = "Kopioi linkki";
"modal_blocked_title" = "Poistetaanko käyttäjän %@ esto?";
"modal_blocked_explanation" = "Haluatko varmasti poistaa käyttäjän %@ eston?";
"modal_blocked_button_title" = "Poista esto";
"modal_link_previews_title" = "Luodaanko linkeistä esikatselut?";
"modal_link_previews_explanation" = "Linkkien esikatselu näyttää esikatselun saamiesi ja lähettämiesi linkkien sisällöstä. Tämä voi olla hyödyllistä, mutta Sessionin pitää vierailla linkatulla nettisivulla luodakseen esikatselun. Voit aina ottaa tämän toiminnon pois päältä Sessionin asetuksissa.";
"modal_link_previews_title" = "Otetaanko linkkien esikatselu käyttöön?";
"modal_link_previews_explanation" = "Linkkien esikatselu näyttää esikatselun lähetetyistä ja vastaanotetuista URL-osoitteiden sisällöstä. Tämä voi olla hyödyllistä, mutta Sessionin on yhdistettävä linkkeihin esikatseluiden luontia varten. Voit aina poistaa toiminnon käytöstä Sessionin asetuksista.";
"modal_link_previews_button_title" = "Ota käyttöön";
"vc_share_title" = "Jaa Sessioniin";
"vc_share_loading_message" = "Valmistellaan liitteitä...";
"vc_share_sending_message" = "Lähetetään...";
"vc_share_link_previews_unsecure" = "Esikatselua ei ladattu epäturvalliselle linkille";
"vc_share_link_previews_error" = "Esikatselun lataaminen epäonnistui";
"vc_share_link_previews_disabled_title" = "Linkin esikatselut otettu pois käytöstä";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Avaa ryhmäkutsu";
"vc_share_link_previews_unsecure" = "Esikatselua ei ladattu suojaamattomalle linkille";
"vc_share_link_previews_error" = "Esikatselua ei voida ladata";
"vc_share_link_previews_disabled_title" = "Linkkien esikatselu on poistettu käytöstä";
"vc_share_link_previews_disabled_explanation" = "Linkkien esikatselun käyttöönotto näyttää esikatselun jakamistasi URL-osoitteista. Tämä voi olla hyödyllistä, mutta esikatseluiden luontia varten Sessionin on yhdistettävä linkitettyihin sivustoihin.\n\nVoit ottaa linkkien esikatselun käyttöön Sessionin asetuksista.";
"view_open_group_invitation_description" = "Open Group -kutsu";
"vc_conversation_settings_invite_button_title" = "Lisää jäseniä";
"modal_send_seed_title" = "Varoitus";
"modal_send_seed_explanation" = "Tämä on palautuslauseesi. Jos lähetät sen jollekulle, heillä on täysin vapaa pääsy tililesi.";
"modal_send_seed_explanation" = "Tämä on palautuslausekkeesi. Jos lähetät sen jollekulle, on heillä täysi pääsy tililesi.";
"modal_send_seed_send_button_title" = "Lähetä";
"vc_conversation_settings_notify_for_mentions_only_title" = "Huomioi vain mainitut";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Vain viestit joissa sinut mainitaan, huomioidaan.";
@ -366,19 +362,18 @@
"delete_message_for_me" = "Poista vain minun nähtäväksi";
"delete_message_for_everyone" = "Poista kaikkien näkyviltä";
"delete_message_for_me_and_recipient" = "Poista minulta ja vastaanottajalta";
"context_menu_info" = "Info";
"context_menu_reply" = "Vastaa";
"context_menu_save" = "Tallenna";
"context_menu_ban_user" = "Estä Käyttäjä";
"context_menu_ban_user" = "Estä käyttäjä";
"context_menu_ban_and_delete_all" = "Estä ja Poista kaikki";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"context_menu_ban_user_error_alert_message" = "Käyttäjää ei voitu estää";
"accessibility_expanding_attachments_button" = "Lisää liitteitä";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Asiakirja";
"accessibility_library_button" = "Kuvakirjasto";
"accessibility_camera_button" = "Kamera";
"accessibility_main_button_collapse" = "Tiivistä liiteasetukset";
"invalid_recovery_phrase" = "Virheellinen Palautuslauseke";
"invalid_recovery_phrase" = "Virheellinen palautuslauseke";
"DISMISS_BUTTON_TEXT" = "Hylkää";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Asetukset";
@ -390,261 +385,431 @@
"PIN_BUTTON_TEXT" = "Kiinnitä";
"UNPIN_BUTTON_TEXT" = "Irrota";
"modal_call_missed_tips_title" = "Vastaamaton puhelu";
"modal_call_missed_tips_explanation" = "Vastaamaton puhelu käyttäjältä '%@', koska pahelut edellyttävät 'Ääni- ja videopuhelut' -käyttöoikeuden yksityisyysasetuksista.";
"modal_call_missed_tips_explanation" = "Puhelu käyttäjältä '%@' jäi vastaamatta, koska puheluita varten yksityisyysasetuksista on myönnettävä 'Ääni- ja videopuhelut' -käyttöoikeus.";
"media_saved" = "%@ tallensi median.";
"screenshot_taken" = "%@ otti kuvankaappauksen.";
"SEARCH_SECTION_CONTACTS" = "Henkilöt ja ryhmät";
"SEARCH_SECTION_CONTACTS" = "Yhteystiedot ja ryhmät";
"SEARCH_SECTION_MESSAGES" = "Viestit";
"MESSAGE_REQUESTS_TITLE" = "Viestipyynnöt";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Ei odottavia viestipyyntöjä";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Poista kaikki";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Oletko varma että haluat poistaa kaikki viestipyynnöt?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Poista";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Oletko varma että haluat poistaa tämän viestipyynnön?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_INFO" = "Viestin lähettäminen tälle henkilölle hyväksyy automaattisesti viestipyynnön.";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Tyhjennä kaikki";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Haluatko varmasti tyhjentää kaikki viestipyynnöt?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Tyhjennä";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Haluatko varmasti poistaa viestipyynnön?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Haluatko varmasti estää tämän yhteystiedon?";
"MESSAGE_REQUESTS_INFO" = "Viestin lähetys tälle käyttäjälle hyväksyy heidän viestipyyntönsä automaattisesti ja paljastaa Session ID:si.";
"MESSAGE_REQUESTS_ACCEPTED" = "Viestipyyntösi hyväksyttiin.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Sinulla on uusi viestipyyntö";
"TXT_HIDE_TITLE" = "Piilota";
"TXT_DELETE_ACCEPT" = "Hyväksy";
"TXT_BLOCK_USER_TITLE" = "Block User";
"TXT_BLOCK_USER_TITLE" = "Estä käyttäjä";
"ALERT_ERROR_TITLE" = "Virhe";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
"modal_call_permission_request_title" = "Puheluiden käyttöoikeus tarvitaan";
"modal_call_permission_request_explanation" = "Voit aktivoida 'Ääni- ja videopuhelut' -käyttöoikeuden yksityisyysasetuksista.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Hups, tapahtui virhe";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Yritä myöhemmin uudelleen";
"LOADING_CONVERSATIONS" = "Ladataan keskusteluita...";
"DATABASE_MIGRATION_FAILED" = "Tietokannan optimoinnissa tapahtui virhe\n\nVoit viedä sovelluksen lokitiedot vianselvitystä varten tai voit palauttaa laitteen\n\nVaroitus: Laitteen palautuksen seurauksena kaikki kahta viikkoa vanhemmat tiedot menetetään.";
"RECOVERY_PHASE_ERROR_GENERIC" = "Jotain meni pieleen. Tarkista palautuslausekkeesi ja yritä uudelleen.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Näyttää siltä, ettet syöttänyt riittävästi sanoja. Tarkista syöttämäsi teksti ja yritä uudelleen.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Palautuslausekkeesi viimeinen sana näyttää puuttuvan. Tarkista syöttämäsi teksti ja yritä uudelleen.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Palautuslausekkeessasi näyttää olevan virheellinen sana. Tarkista syöttämäsi teksti ja yritä uudelleen.";
"RECOVERY_PHASE_ERROR_FAILED" = "Palautuslausekettasi ei voitu vahvistaa. Tarkista syöttämäsi teksti ja yritä uudelleen.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Todennustapaa ei tavoitettu.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Tunnistautuminen epäonnistui";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Todennus epäonnistui.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Liian monta epäonnistunutta tunnistautumista. Yritä myöhemmin uudelleen.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Liian monta epäonnistunutta todennusyritystä. Yritä myöhemmin uudelleen.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Pääsykoodi on otettava iOS:n asetuksista käyttöön näytön lukituksen käyttämiseksi.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Pääsykoodi on otettava iOS:n asetuksista käyttöön näytön lukituksen käyttämiseksi.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Aseta pääsykoodi puhelimesi asetuksista, jotta voit käyttää näytön lukitusta.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Pääsykoodi on otettava iOS:n asetuksista käyttöön näytön lukituksen käyttämiseksi.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
"SEND_BUTTON_TITLE" = "Lähetä";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
"RETRY_BUTTON_TEXT" = "Yritä uudelleen";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
"SHOW_THREAD_BUTTON_TITLE" = "Näytä keskustelu";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"SEND_FAILED_NOTIFICATION_BODY" = "Viestin lähetys epäonnistui";
"INVALID_SESSION_ID_MESSAGE" = "Tarkista Session ID ja yritä uudelleen";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Tarkista palautuslauseke ja yritä uudelleen";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
"DOCUMENT_TAB_TITLE" = "Dokumentit";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "Sinulla ei ole dokumentteja tässä keskustelussa.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Ladataan uudempaa dokumenttia…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Ladataan vanhempaa dokumenttia…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Aktiviteetit";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
"EMOJI_CATEGORY_ANIMALS_NAME" = "Eläimet ja luonto";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
"EMOJI_CATEGORY_FLAGS_NAME" = "Liput";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
"EMOJI_CATEGORY_FOOD_NAME" = "Ruoka ja juoma";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
"EMOJI_CATEGORY_OBJECTS_NAME" = "Esineet";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
"EMOJI_CATEGORY_RECENTS_NAME" = "Viimeksi käytetyt";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Hymiöt ja ihmiset";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbolit";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
"EMOJI_CATEGORY_TRAVEL_NAME" = "Matkailu ja paikat";
"EMOJI_REACTS_NOTIFICATION" = "%@ reagoi viestiin: %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Ja 1 muu on reagoinut viestiin: %@.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "Ja %@ muuta on reagoinut viestiin: %@.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Hidasta! Olet lähettänyt liian monta emojireaktiota. Yritä hetken kuluttua uudelleen.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"vc_new_conversation_title" = "Uusi keskustelu";
"CREATE_GROUP_BUTTON_TITLE" = "Luo";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Liity";
"PRIVACY_TITLE" = "Yksityisyys";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Näytön suojaus";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lukitse Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Vaadi Sessionin avaukseen Touch ID, Face ID tai salasana.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Lukukuittaukset";
"PRIVACY_READ_RECEIPTS_TITLE" = "Lukukuittaukset";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Ilmaise aktiivinen kirjoitus";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Ilmaise aktiivinen kirjoitus";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Lähetä linkeistä esikatselu";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Lähetä lukukuittauksia kahdenkeskisissä keskusteluissa.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Kirjoitusindikaattorit";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Kirjoitusindikaattorit";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Näe ja jaa kirjoitusindikaattorit kahdenkeskisissä keskusteluissa.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Linkkien esikatselut";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Lähetä linkkien esikatselut";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Luo linkkien esikatselut tuetuille URL-osoitteille.";
"PRIVACY_SECTION_CALLS" = "Puhelut (beta)";
"PRIVACY_CALLS_TITLE" = "Ääni- ja videopuhelut";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"PRIVACY_CALLS_DESCRIPTION" = "Mahdollistaa ääni- ja videopuheluiden soiton ja vastaanoton.";
"PRIVACY_CALLS_WARNING_TITLE" = "Ääni- ja videopuhelut (beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "IP-osoitteesi paljastuu beta-puheluita käytettäessä puhelukumppanillesi ja Oxen Säätiön palvelimelle. Haluatko varmasti ottaa ääni- ja videopuhelut käyttöön?";
"NOTIFICATIONS_TITLE" = "Ilmoitukset";
"NOTIFICATIONS_SECTION_STRATEGY" = "Ilmoitustyyli";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Toimita nopeasti";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_SECTION_STRATEGY" = "Ilmoituskäytäntö";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Käytä nopeaa tilaa";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Uusista viesteistä ilmoitetaan luotettavasti ja viiveettä Applen ilmoituspalvelinten avulla.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Järjestelmän ilmoitusasetukset";
"NOTIFICATIONS_SECTION_STYLE" = "Ilmoitusten tyyli";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Ääni";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Ääni sovelluksen ollessa avoinna";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Ilmoituksen sisältö";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Ilmoituksissa näytettävät tiedot.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Nimi ja sisältö";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Vain nimi";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Ei nimeä tai sisältöä";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"CONVERSATION_SETTINGS_TITLE" = "Keskustelut";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Keskustelujen tiivistys";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Yhteisöjen tiivistys";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Poista yli 6 kuukauden ikäiset viestit yli 2000 viestin yhteisöistä.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Ääniviestit";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Toista ääniviestit automaattisesti";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Toista peräkkäiset ääniviestit automaattisesti.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Estetyt yhteystiedot";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Sinulla ei ole estettyjä yhteystietoja.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Poista esto";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Haluatko varmasti poistaa käyttäjän %@ eston?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "tämä yhteystieto";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Haluatko varmasti poistaa käyttäjän %@ eston";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "ja %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "ja %d muuta?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Poista esto";
"APPEARANCE_TITLE" = "Ulkoasu";
"APPEARANCE_THEMES_TITLE" = "Teemat";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Pääväri";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Mitä kuuluu?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Hyvää, kiitos. Mitäs sinne?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Erinomaista, kiitos.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Automaattinen yötila";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Seuraa järjestelmän asetusta";
"HELP_TITLE" = "Tuki";
"HELP_REPORT_BUG_TITLE" = "Ilmoita virheestä";
"HELP_REPORT_BUG_DESCRIPTION" = "Vie lokitiedot ja lähetä tiedosto Sessionin tukipalvelusta.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Vie lokitiedot";
"HELP_TRANSLATE_TITLE" = "Käännä Session";
"HELP_FEEDBACK_TITLE" = "Haluaisimme kuulla mielipiteesi";
"HELP_FAQ_TITLE" = "UKK";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Tyhjennä kaikki data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Dataa ei poistettu yhdestä palvelusolmusta. Palvelusolmun tunnus: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Dataa ei poistettu %@ palvelusolmusta. Palvelusolmujen tunnukset: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Palatusvirkkeesi";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
"HELP_SUPPORT_TITLE" = "Tue";
"modal_clear_all_data_title" = "Tyhjennä kaikki tiedot";
"modal_clear_all_data_explanation" = "Tämä poistaa viestisi ja yhteystietosi pysyvästi. Haluatko poistaa tietosi vain tältä laitteelta vai myös verkosta?";
"modal_clear_all_data_explanation_2" = "Haluatko varmasti poistaa tietosi verkosta? Jos jatkat, et voi palauttaa viestejäsi etkä yhteystietojasi.";
"modal_clear_all_data_device_only_button_title" = "Tyhjennä vain laitteelta";
"modal_clear_all_data_entire_account_button_title" = "Tyhjennä laitteelta ja verkosta";
"dialog_clear_all_data_deletion_failed_1" = "Tietoja ei poistettu 1 palvelusolmusta. Solmun ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Tietoja ei poistettu %@ palvelusolmusta. Solmujen ID:t: %@.";
"modal_clear_all_data_confirm" = "Tyhjennä";
"modal_seed_title" = "Palautuslausekkeesi";
"modal_seed_explanation" = "Palautuslausekkeesi avulla voit palauttaa tilisi tai liittää laitteen.";
"modal_permission_explanation" = "Jatkaakseen Session tarvitsee \"%@\" -käyttöoikeuden. Voit myöntää sen iOS:n järjestelmäsetuksista.";
"modal_permission_settings_title" = "Asetukset";
"modal_permission_camera" = "kamera";
"modal_permission_microphone" = "mikrofoni";
"modal_permission_library" = "kirjasto";
"DISAPPEARING_MESSAGES_OFF" = "Pois käytöstä";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Pois käytöstä";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Katoa, kun on kulunut: %@";
"COPY_GROUP_URL" = "Kopioi ryhmän URL-osoite";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Yhteystiedot";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Valitse ainakin 1 ryhmän jäsen";
"GROUP_CREATION_PLEASE_WAIT" = "Odota kunnes ryhmä on luotu...";
"GROUP_CREATION_ERROR_TITLE" = "Ryhmää ei voitu luoda";
"GROUP_CREATION_ERROR_MESSAGE" = "Tarkista Internet-yhteytesi ja yritä uudelleen.";
"GROUP_UPDATE_ERROR_TITLE" = "Ryhmää ei voitu päivittää";
"GROUP_UPDATE_ERROR_MESSAGE" = "Ei voida poistua lisättäessä tai poistettaessa muita jäseniä.";
"GROUP_ACTION_REMOVE" = "Poista";
"GROUP_TITLE_MEMBERS" = "Jäsenet";
"GROUP_TITLE_FALLBACK" = "Ryhmä";
"DM_ERROR_DIRECT_BLINDED_ID" = "Voit lähettää viestejä vain sokaistuille ID:ille yhteisöstä";
"DM_ERROR_INVALID" = "Tarkista Session ID tai ONS-nimi ja yritä uudelleen";
"COMMUNITY_ERROR_INVALID_URL" = "Tarkista syöttämäsi URL-osoite ja yritä uudelleen.";
"COMMUNITY_ERROR_GENERIC" = "Ei voitu liittyä";
"DISAPPERING_MESSAGES_TITLE" = "Katoavat viestit";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Poista tyyppi";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Katoa, kun luettu";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Viestit poistuvat, kun ne on luettu.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Katoa lähetyksen jälkeen";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Viestit poistuvat, kun ne on lähetetty.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Ajastin";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Aseta";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Tämä asetus koskee kaikkia tässä keskustelussa.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Tämä asetus koskee kaikkia tässä keskustelussa. Vain ryhmän ylläpitäjät voivat muuttaa asetusta.";
"DISAPPERING_MESSAGES_SUMMARY" = "Katoa, kun %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ on asettanut viestit katoamaan %@, kun ne on %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ on vahtanut viestit katoamaan %@, kun ne on %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ poisti katoavat viestit käytöstä";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -1,19 +1,19 @@
/* No comment provided by engineer. */
"ATTACHMENT" = "ඇමුණුම";
"ATTACHMENT" = "Mga isinama";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Caption";
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Pamagat";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "ගොනුවේ වර්ගය: %@";
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Uri ng talaksan: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "ප්‍රමාණය: %@";
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Laki: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Message limit reached";
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Inabot ang hangganan ng mensahe";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "යවන්න";
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Ipadala";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "ඇමුණුම";
"ATTACHMENT_DEFAULT_FILENAME" = "Mga isinama";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Error Sending Attachment";
"ATTACHMENT_ERROR_ALERT_TITLE" = "May pagkakamali sa pagpapadala ng mga isinama";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Unable to convert image.";
/* Attachment error message for video attachments which could not be converted to MP4 */
@ -25,29 +25,29 @@
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Unable to resize image.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Attachment is too large.";
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Masyadong malaki ang nakalakip na file.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Attachment includes invalid content.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Attachment has an invalid file format.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty.";
"ATTACHMENT_ERROR_MISSING_DATA" = "Walang laman ang attachment.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Failed to choose document.";
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "May kamalian sa pagpili ng dokumento.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Please create a compressed archive of this file or directory and try sending that instead.";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Pakigawan ng pinaliit na archive ang talaksan o sanggunian at subukang ipadala muli.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "සහාය නොදක්වන ගොනුවකි";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Hindi suportadong Talaksan";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Voice Message";
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Boses na Mensahe";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "අවහිර";
"BLOCK_LIST_BLOCK_BUTTON" = "I-block";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Block %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Unblock";
"BLOCK_LIST_UNBLOCK_BUTTON" = "I-unblock";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked.";
/* The title of the 'user blocked' alert. */
@ -57,35 +57,35 @@
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
/* Label for generic done button. */
"BUTTON_DONE" = "Done";
"BUTTON_DONE" = "Tapos na";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Select";
"BUTTON_SELECT" = "Piliin";
/* keyboard toolbar label when starting to search with no current results */
"CONVERSATION_SEARCH_SEARCHING" = "Searching...";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "No matches";
"CONVERSATION_SEARCH_NO_RESULTS" = "Walang katugma";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 match";
"CONVERSATION_SEARCH_ONE_RESULT" = "1 katugma";
/* keyboard toolbar label when more than 1 message matches the search string. Embeds {{number/position of the 'currently viewed' result}} and the {{total number of results}} */
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d of %d matches";
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d sa %d na katugma";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block This User";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Mute";
"CONVERSATION_SETTINGS_MUTE_LABEL" = "I-mute";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Search Conversation";
/* Title for the 'crop/scale image' dialog. */
"CROP_SCALE_IMAGE_VIEW_TITLE" = "Move and Scale";
/* Subtitle shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "Maaaring tatagal ito ng ilang mga minuto.";
/* Title shown while the app is updating its database. */
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimizing Database";
/* The present; the current time. */
"DATE_NOW" = "දැන්";
"DATE_NOW" = "Ngayon";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Disappearing Messages";
"DISAPPEARING_MESSAGES" = "Nawawalang mensahe";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "සමූහය සංස්කරණය";
"EDIT_GROUP_ACTION" = "Edit Group";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "You don't have any media in this conversation.";
/* Label indicating loading is in progress */
@ -103,13 +103,13 @@
/* Indicates that an error occurred while searching. */
"GIF_VIEW_SEARCH_ERROR" = "Error. Tap to Retry.";
/* Indicates that the user's search had no results. */
"GIF_VIEW_SEARCH_NO_RESULTS" = "ප්‍රතිඵල නැත.";
"GIF_VIEW_SEARCH_NO_RESULTS" = "No Results.";
/* No comment provided by engineer. */
"GROUP_CREATED" = "Group created";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = " %@ සමූහය හැරගියා. ";
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
@ -119,49 +119,47 @@
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Group updated.";
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "You have left the group.";
"GROUP_YOU_LEFT" = "Ikaw ay umalis sa grupo.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from the group. ";
"YOU_WERE_REMOVED" = " Ikaw ay inalis sa grupong ito. ";
/* Momentarily shown to the user when attempting to select more images than is allowed. Embeds {{max number of items}} that can be shared. */
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "You can't share more than %@ items.";
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "Hindi maaring mag-share ng higit sa %@ items";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Failed to select attachment.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Invalid audio file.";
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "Hindi wasto ang audio file.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "හැරයන්න";
"LEAVE_BUTTON_TITLE" = "Umalis";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "සමූහය හැරයන්න";
"LEAVE_GROUP_ACTION" = "Umalis sa grupo";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "සියළුම මාධ්‍යය";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Photo Library";
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Lahat ng media";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Delete %d Messages";
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Burahin ang %d mensahe ";
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Delete Message";
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Burahin ang mensahe";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ on %@";
/* Format for the 'more items' indicator for media galleries. Embeds {{the number of additional items}}. */
"MEDIA_GALLERY_MORE_ITEMS_FORMAT" = "+%@";
/* Short sender label for media sent by you */
"MEDIA_GALLERY_SENDER_NAME_YOU" = "ඔබ";
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Ikaw";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "මෙම මාසය";
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Ngayong buwan";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Sending failed.";
"MESSAGE_STATUS_FAILED" = "Hindi tumuloy ang pagpapadala.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Read";
"MESSAGE_STATUS_READ" = "Basahin";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Sending…";
"MESSAGE_STATUS_SENDING" = "Pinapadala…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Sent";
"MESSAGE_STATUS_SENT" = "Naipadala";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Uploading…";
"MESSAGE_STATUS_UPLOADING" = "Nag-uupload…";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ to %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Note to Self";
"NOTE_TO_SELF" = "Mga paalaala";
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "You may have received messages while your %@ was restarting.";
/* No comment provided by engineer. */
@ -177,11 +175,11 @@
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Failed to configure camera.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Unnamed Album";
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Hindi napangalanan ang Album";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Mark as Read";
"PUSH_MANAGER_MARKREAD" = "Markahan bilang nabasa";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "පිළිතුරු";
"PUSH_MANAGER_REPLY" = "Sagutin";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
"SCREEN_LOCK_REASON_UNLOCK_SCREEN_LOCK" = "Authenticate to open Session.";
/* Title for alert indicating that screen lock could not be unlocked. */
@ -193,39 +191,39 @@
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (default)";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "පණිවිඩ ශබ්දය";
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
"SOUNDS_NONE" = "Wala";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "දවස් %@";
"TIME_AMOUNT_DAYS" = "%@ days";
/* Label text below navbar button, embeds {{number of days}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5d' not '5 d'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS_SHORT_FORMAT" = "%@d";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS" = "පැය %@";
"TIME_AMOUNT_HOURS" = "%@ hours";
/* Label text below navbar button, embeds {{number of hours}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5h' not '5 h'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_HOURS_SHORT_FORMAT" = "%@h";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES" = "විනාඩි %@";
"TIME_AMOUNT_MINUTES" = "%@ minutes";
/* Label text below navbar button, embeds {{number of minutes}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5m' not '5 m'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_MINUTES_SHORT_FORMAT" = "%@m";
/* {{number of seconds}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 seconds}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS" = "තත්පර %@";
"TIME_AMOUNT_SECONDS" = "%@ seconds";
/* Label text below navbar button, embeds {{number of seconds}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5s' not '5 s'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SECONDS_SHORT_FORMAT" = "%@s";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "දවස් %@";
"TIME_AMOUNT_SINGLE_DAY" = "%@ day";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_HOUR" = "පැය %@";
"TIME_AMOUNT_SINGLE_HOUR" = "%@ hour";
/* {{1 minute}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 minute}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_MINUTE" = "විනාඩි %@";
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minute";
/* {{1 week}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 week}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_WEEK" = "සති %@";
"TIME_AMOUNT_SINGLE_WEEK" = "%@ week";
/* {{number of weeks}}, embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 weeks}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS" = "සති %@";
"TIME_AMOUNT_WEEKS" = "%@ weeks";
/* Label text below navbar button, embeds {{number of weeks}}. Must be very short, like 1 or 2 characters, The space is intentionally omitted between the text and the embedded duration so that we get, e.g. '5w' not '5 w'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_WEEKS_SHORT_FORMAT" = "%@w";
/* Label for the cancel button in an alert or action sheet. */
"TXT_CANCEL_TITLE" = "අවලංගු";
"TXT_CANCEL_TITLE" = "Cancel";
/* No comment provided by engineer. */
"TXT_DELETE_TITLE" = "Delete";
/* Filename for voice messages. */
@ -239,24 +237,24 @@
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
// MARK: - Session
"continue_2" = "ඉදිරියට";
"copy" = "පිටපත්";
"invalid_url" = "ඒ.ස.නි. වලංගු නොවේ";
"next" = "ඊළඟ";
"share" = "බෙදාගන්න";
"continue_2" = "Continue";
"copy" = "Copy";
"invalid_url" = "Invalid URL";
"next" = "Next";
"share" = "Share";
"invalid_session_id" = "Invalid Session ID";
"cancel" = "අවලංගු";
"cancel" = "Cancel";
"your_session_id" = "Your Session ID";
"vc_landing_title_2" = "Your Session begins here...";
"vc_landing_register_button_title" = "Create Session ID";
"vc_landing_restore_button_title" = "Continue Your Session";
"vc_landing_link_button_title" = "Link a Device";
"view_fake_chat_bubble_1" = "සෙෂන් යනු කුමක්ද?";
"view_fake_chat_bubble_1" = "What's Session?";
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
"vc_register_title" = "ඔබගේ සෙෂන් හැඳු. ආයුබෝවන් කියන්න";
"vc_register_title" = "Say hello to your Session ID";
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
"vc_restore_title" = "Restore your account";
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
@ -268,7 +266,7 @@
"vc_display_name_text_field_hint" = "Enter a display name";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_pn_mode_recommended_option_tag" = "නිර්දේශිතයි";
"vc_pn_mode_recommended_option_tag" = "Recommended";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Start a Session";
@ -281,7 +279,7 @@
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"vc_path_title" = "Path";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "ඔබ";
"vc_path_device_row_title" = "You";
"vc_path_guard_node_row_title" = "Entry Node";
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destination";
@ -291,11 +289,9 @@
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_scan_qr_code_grant_camera_access_button_title" = "Grant Camera Access";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_empty_state_button_title" = "Start a Session";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
@ -303,17 +299,17 @@
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "සැකසුම්";
"vc_settings_title" = "Settings";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
"vc_settings_privacy_button_title" = "පෞද්ගලිකත්වය";
"vc_settings_notifications_button_title" = "දැනුම්දීම්";
"vc_settings_privacy_button_title" = "Privacy";
"vc_settings_notifications_button_title" = "Notifications";
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
"vc_settings_clear_all_data_button_title" = "Clear Data";
"vc_qr_code_title" = "QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "Ipakita Ang aking QR Code";
"vc_qr_code_view_scan_qr_code_tab_title" = "I-scan ang QR Code";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
// MARK: - Not Yet Translated
@ -321,7 +317,7 @@
"fast_mode" = "Fast Mode";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode" = "Slow Mode";
"vc_pn_mode_title" = "පණිවිඩ දැනුම්දීම්";
"vc_pn_mode_title" = "Message Notifications";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
"vc_link_device_scan_qr_code_explanation" = "Navigate to Settings → Recovery Phrase on your other device to show your QR code.";
"vc_enter_recovery_phrase_title" = "Recovery Phrase";
@ -330,35 +326,35 @@
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_settings_invite_a_friend_button_title" = "Invite a Friend";
"copied" = "පිටපත් විය";
"copied" = "Copied";
"vc_conversation_settings_copy_session_id_button_title" = "Copy Session ID";
"vc_conversation_input_prompt" = "පණිවිඩය";
"vc_conversation_input_prompt" = "Message";
"vc_conversation_voice_message_cancel_message" = "Slide to Cancel";
"modal_download_attachment_title" = "%@ විශ්වාස ද?";
"modal_download_attachment_title" = "Trust %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_button_title" = "බාගන්න";
"modal_open_url_title" = "ඒ.ස.නි. විවෘත?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Open URL?";
"modal_open_url_explanation" = "Are you sure you want to open %@?";
"modal_open_url_button_title" = "විවෘත";
"modal_copy_url_button_title" = "සබැඳිය පිටපත්";
"modal_blocked_title" = "%@ අනවහිර?";
"modal_open_url_button_title" = "Open";
"modal_copy_url_button_title" = "Copy Link";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "අනවහිර";
"modal_blocked_button_title" = "Unblock";
"modal_link_previews_title" = "Enable Link Previews?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "සබල කරන්න";
"vc_share_title" = "සෙෂන් වෙත බෙදාගන්න";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "යැවෙමින්...";
"modal_link_previews_button_title" = "Enable";
"vc_share_title" = "I-share sa Session";
"vc_share_loading_message" = "Inihahanda ang attachments...";
"vc_share_sending_message" = "Ipinapadala...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "සාමාජිකයින් එක්කරන්න";
"modal_send_seed_title" = "අවවාදයයි";
"vc_conversation_settings_invite_button_title" = "Magdagdag ng Miyembro";
"modal_send_seed_title" = "Babala";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_send_button_title" = "යවන්න";
"modal_send_seed_send_button_title" = "Ipadala";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
@ -366,22 +362,21 @@
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_info" = "Info";
"context_menu_reply" = "පිළිතුරු";
"context_menu_save" = "සුරකින්න";
"context_menu_reply" = "Sagutin";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
"context_menu_ban_and_delete_all" = "Ban and Delete All";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"accessibility_expanding_attachments_button" = "ඇමුණුම් එක්කරන්න";
"accessibility_expanding_attachments_button" = "Add attachments";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "ලේඛනය";
"accessibility_document_button" = "Document";
"accessibility_library_button" = "Photo library";
"accessibility_camera_button" = "Camera";
"accessibility_main_button_collapse" = "Collapse attachment options";
"invalid_recovery_phrase" = "Invalid Recovery Phrase";
"DISMISS_BUTTON_TEXT" = "Dismiss";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "සැකසුම්";
"OPEN_SETTINGS_BUTTON" = "Settings";
"call_outgoing" = "You called %@";
"call_incoming" = "%@ called you";
"call_missed" = "Missed Call from %@";
@ -389,12 +384,12 @@
"APN_Collapsed_Messages" = "You've got %@ new messages.";
"PIN_BUTTON_TEXT" = "Pin";
"UNPIN_BUTTON_TEXT" = "Unpin";
"modal_call_missed_tips_title" = "Call missed";
"modal_call_missed_tips_title" = "Nakaligtaang tawag";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "පණිවිඩ";
"SEARCH_SECTION_MESSAGES" = "Mga mensahe";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
@ -414,10 +409,6 @@
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
@ -446,7 +437,6 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
@ -473,31 +463,30 @@
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "පෞද්ගලිකත්වය";
"PRIVACY_SECTION_SCREEN_SECURITY" = "තිරයේ ආරක්ෂාව";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "කියවූ බවට ලදුපත්";
"PRIVACY_READ_RECEIPTS_TITLE" = "කියවූ බවට ලදුපත්";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "සබැඳියේ පෙරදසුන් යවන්න";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "දැනුම්දීම්";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
@ -505,11 +494,11 @@
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "දැනුම්දීමේ අන්තර්ගතය";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "නම පමණි";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "නමක් හෝ අන්තර්ගතයක් නැත";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
@ -540,7 +529,7 @@
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "නිති පැණ";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
@ -584,67 +573,243 @@
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -35,7 +35,7 @@
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Échec de sélection du document.";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Veuillez créer une archive compressée de ce fichier ou de ce répertoire et essayez d'envoyer cette archive.";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Veuillez créer une archive compressée de ce fichier ou de ce répertoire et ensuite essayez d'envoyer cette archive.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Fichier non pris en charge";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
@ -85,7 +85,7 @@
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Messages éphémères";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Modifier le groupe";
"EDIT_GROUP_ACTION" = "Réglage du groupe";
/* Label indicating media gallery is empty */
"GALLERY_TILES_EMPTY_GALLERY" = "Vous navez aucun média dans cette conversation.";
/* Label indicating loading is in progress */
@ -107,9 +107,9 @@
/* No comment provided by engineer. */
"GROUP_CREATED" = "Le groupe a été créé.";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ sest joint au groupe.";
"GROUP_MEMBER_JOINED" = "%@ a rejoint le groupe. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ a quitté le groupe.";
"GROUP_MEMBER_LEFT" = "%@ a quitté le groupe. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ a été retiré du groupe. ";
/* No comment provided by engineer. */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "Quitter le groupe ";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Tous les médias";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Photothèque";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Supprimer %d messages";
/* Confirmation button text to delete selected media message from the gallery */
@ -148,7 +146,7 @@
"MEDIA_GALLERY_SENDER_NAME_YOU" = "Vous";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "Ce mois-ci";
/* message status for message delivered to their recipient. */
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Échec denvoi.";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Lu";
@ -165,7 +163,7 @@
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "Vous avez peut-être reçu des messages alors que votre %@ redémarrait.";
/* No comment provided by engineer. */
"BUTTON_OK" = "Valider";
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ a désactivé les messages éphémères.";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
@ -246,9 +244,9 @@
"share" = "Partager";
"invalid_session_id" = "Session ID non valide";
"cancel" = "Annuler";
"your_session_id" = "Votre Session ID";
"your_session_id" = "Votre ID Session ";
"vc_landing_title_2" = "Votre Session débute ici...";
"vc_landing_register_button_title" = "Créer un Session ID";
"vc_landing_register_button_title" = "Créer un ID Session ";
"vc_landing_restore_button_title" = "Continuez votre Session";
"vc_landing_link_button_title" = "Relier à un compte existant";
"view_fake_chat_bubble_1" = "Qu'est-ce que Session ?";
@ -256,13 +254,13 @@
"view_fake_chat_bubble_3" = "Elle ne recueille donc pas mes informations personnelles ou mes métadonnées de conversations ? Comment ça marche ?";
"view_fake_chat_bubble_4" = "En utilisant une combinaison de technologies avancées de routage anonyme et de chiffrement de bout en bout.";
"view_fake_chat_bubble_5" = "Les vrais amis ne laissent pas leurs amis utiliser des outils de messagerie compromis. De rien.";
"vc_register_title" = "Dites bonjour à votre Session ID";
"vc_register_explanation" = "Votre Session ID est l'identifiant unique que les gens utilisent pour vous contacter dans Session. Sans lien avec votre identité réelle, votre Session ID est complètement anonyme et privé.";
"vc_register_title" = "Dites bonjour à votre ID Session ";
"vc_register_explanation" = "Votre ID Session est l'identifiant unique que les gens utilisent pour vous contacter dans Session. Sans lien avec votre identité réelle, votre Session ID est complètement anonyme et privé.";
"vc_restore_title" = "Restaurez votre compte";
"vc_restore_explanation" = "Pour restaurer votre compte, veuillez entrer la phrase de récupération qui vous a été fournie lors de la création de votre compte.";
"vc_restore_seed_text_field_hint" = "Saisissez votre phrase de récupération";
"vc_link_device_title" = "Relier un appareil";
"vc_link_device_scan_qr_code_tab_title" = "Scanner un code QR";
"vc_link_device_scan_qr_code_tab_title" = "Scanner un QR code ";
"vc_display_name_title_2" = "Choisissez votre nom d'utilisateur";
"vc_display_name_explanation" = "Ce sera votre nom lorsque vous utiliserez Session. Il peut s'agir de votre vrai nom, d'un pseudo ou de ce que vous voulez.";
"vc_display_name_text_field_hint" = "Saisissez un nom d'utilisateur";
@ -274,10 +272,10 @@
"vc_home_empty_state_button_title" = "Démarrez une Session";
"vc_seed_title" = "Votre phrase de récupération";
"vc_seed_title_2" = "Voici votre phrase de récupération";
"vc_seed_explanation" = "Votre phrase de récupération est la clé principale de votre Session ID - vous pouvez l'utiliser pour restaurer votre Session ID si vous perdez l'accès à votre appareil. Conservez la dans un endroit sûr et ne la donnez à personne.";
"vc_seed_explanation" = "Votre phrase de récupération est la clé principale de votre ID Session - vous pouvez l'utiliser pour restaurer votre ID Session si vous perdez l'accès à votre appareil. Conservez la dans un endroit sûr et ne la donnez à personne.";
"vc_seed_reveal_button_title" = "Appuyer pour révéler";
"view_seed_reminder_subtitle_1" = "Sécurisez votre compte en sauvegardant votre phrase de récupération";
"view_seed_reminder_subtitle_2" = "Appuyez et maintenez les mots masqués pour révéler votre phrase de récupération, puis stockez-la en toute sécurité pour sécuriser votre Session ID.";
"view_seed_reminder_subtitle_2" = "Appuyez et maintenez les mots masqués pour révéler votre phrase de récupération, puis stockez-la en toute sécurité pour sécuriser votre ID Session.";
"view_seed_reminder_subtitle_3" = "Assurez-vous de conserver votre phrase de récupération dans un endroit sûr";
"vc_path_title" = "Chemin";
"vc_path_explanation" = "Session occulte votre adresse IP en envoyant vos messages via plusieurs nœuds de service dans le réseau décentralisé de Session. Voici les pays par le biais desquels votre connexion est actuellement envoyée :";
@ -286,46 +284,44 @@
"vc_path_service_node_row_title" = "Noeud de service";
"vc_path_destination_row_title" = "Destination";
"vc_path_learn_more_button_title" = "En savoir plus";
"vc_create_private_chat_title" = "Nouvelle Session";
"vc_create_private_chat_enter_session_id_tab_title" = "Saisir un Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scanner un Code QR";
"vc_enter_public_key_explanation" = "Démarrez une nouvelle conversation en saisissant l'ID Session de quelqu'un ou en partageant votre ID Session avec eux.";
"vc_scan_qr_code_camera_access_explanation" = "Session a besoin d'accéder à l'appareil photo pour scanner les codes QR";
"vc_scan_qr_code_grant_camera_access_button_title" = "Autoriser l'accès";
"vc_create_closed_group_title" = "Nouveau groupe privé";
"vc_create_private_chat_title" = "Nouveau message";
"vc_create_private_chat_enter_session_id_tab_title" = "Saisir un ID Session";
"vc_create_private_chat_scan_qr_code_tab_title" = "Scanner un QR Code";
"vc_enter_public_key_explanation" = "Commencez une nouvelle conversation en entrant l'ID Session de quelqu'un ou en lui partageant votre ID Session.";
"vc_scan_qr_code_camera_access_explanation" = "Session a besoin d'accéder à l'appareil photo pour scanner les QR codes";
"vc_create_closed_group_title" = "Créer un groupe";
"vc_create_closed_group_text_field_hint" = "Saisissez un nom de groupe";
"vc_create_closed_group_empty_state_message" = "Vous n'avez pas encore de contacts";
"vc_create_closed_group_empty_state_button_title" = "Démarrer une session";
"vc_create_closed_group_group_name_missing_error" = "Veuillez saisir un nom de groupe";
"vc_create_closed_group_group_name_too_long_error" = "Veuillez saisir un nom de groupe plus court";
"vc_create_closed_group_too_many_group_members_error" = "Un groupe privé ne peut pas avoir plus de 100 membres";
"vc_join_public_chat_title" = "Joindre un groupe public";
"vc_join_public_chat_enter_group_url_tab_title" = "URL du groupe public";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scannez le code QR";
"vc_enter_chat_url_text_field_hint" = "Saisissez une URL de groupe public";
"vc_join_public_chat_title" = "Rejoindre la communauté";
"vc_join_public_chat_enter_group_url_tab_title" = "URL de la communauté";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scannez le QR code ";
"vc_enter_chat_url_text_field_hint" = "Entrez l'URL de la communauté";
"vc_settings_title" = "Paramètres";
"vc_group_settings_title" = "Paramètres de Groupe";
"vc_group_settings_title" = "Paramètres de groupe";
"vc_settings_display_name_missing_error" = "Veuillez choisir un nom d'utilisateur";
"vc_settings_display_name_too_long_error" = "Veuillez choisir un nom d'utilisateur plus court";
"vc_settings_privacy_button_title" = "Confidentialité ";
"vc_settings_privacy_button_title" = "Confidentialité";
"vc_settings_notifications_button_title" = "Notifications";
"vc_settings_recovery_phrase_button_title" = "Phrase de récupération";
"vc_settings_clear_all_data_button_title" = "Effacer les données";
"vc_qr_code_title" = "Code QR";
"vc_qr_code_view_my_qr_code_tab_title" = "Afficher mon code QR";
"vc_qr_code_title" = "QR Code ";
"vc_qr_code_view_my_qr_code_tab_title" = "Afficher mon QR code ";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scanner le QR Code";
"vc_qr_code_view_scan_qr_code_explanation" = "Scannez le code QR d'un autre utilisateur pour démarrer une session";
"vc_view_my_qr_code_explanation" = "Ceci est votre code QR. Les autres utilisateurs peuvent le scanner pour démarrer une session avec vous.";
"vc_qr_code_view_scan_qr_code_explanation" = "Scannez le QR code d'un autre utilisateur pour démarrer une session";
"vc_view_my_qr_code_explanation" = "Ceci est votre QR code. Les autres utilisateurs peuvent le scanner pour démarrer une conversation avec vous.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Vous serez notifiés de nouveaux messages de manière certaine et immédiate en utilisant les serveurs de notification dApple.";
"fast_mode" = "Mode rapide";
"slow_mode_explanation" = "Session vérifiera occasionnellement la présence de nouveaux messages en tâche de fond.";
"slow_mode_explanation" = "Session vérifiera occasionnellement la présence de nouveaux message en tâche de fond.";
"slow_mode" = "Mode lent";
"vc_pn_mode_title" = "Notifications de message";
"vc_link_device_recovery_phrase_tab_title" = "Phrase de récupération";
"vc_link_device_scan_qr_code_explanation" = "Allez dans paramètre → Phrase de récupération sur votre autre appareil pour afficher votre QR Code.";
"vc_enter_recovery_phrase_title" = "Phrase de récupération";
"vc_enter_recovery_phrase_explanation" = "Pour lier votre appareil, entrez la phrase de récupération qui vous a été donnée lors de la création du compte.";
"vc_enter_recovery_phrase_explanation" = "Pour lier votre appareil, entrez la phrase de récupération qui vous a été donné lors de la création du compte.";
"vc_enter_public_key_text_field_hint" = "Entrez un ID Session ou un nom ONS";
"admin_group_leave_warning" = "Puisque vous êtes le créateur de ce groupe, il sera supprimé pour tout le monde. Ceci ne peut pas être annulé.";
"vc_join_open_group_suggestions_title" = "Ou rejoignez un de ceux-ci...";
@ -360,13 +356,12 @@
"modal_send_seed_explanation" = "Voici votre phrase de récupération. Si vous l'envoyez à quelqu'un, cette personne aura un accès complet à votre compte.";
"modal_send_seed_send_button_title" = "Envoyer";
"vc_conversation_settings_notify_for_mentions_only_title" = "Activer les notifications que sur mention";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Quand activé, vous recevrez uniquement les notifications des messages vous mentionnant.";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Quand activer, vous recevrez les notifications duniquement les messages vous notifiant.";
"view_conversation_title_notify_for_mentions_only" = "Me notifier que si je suis mentionné(e)";
"message_deleted" = "Ce message a été supprimé";
"delete_message_for_me" = "Supprimer pour moi uniquement";
"delete_message_for_everyone" = "Supprimer pour tout le monde";
"delete_message_for_me_and_recipient" = "Supprimer pour moi et %@";
"context_menu_info" = "Info";
"context_menu_reply" = "Répondre";
"context_menu_save" = "Enregistrer";
"context_menu_ban_user" = "Bannir l'utilisateur";
@ -391,7 +386,7 @@
"UNPIN_BUTTON_TEXT" = "Désépingler";
"modal_call_missed_tips_title" = "Appel manqué";
"modal_call_missed_tips_explanation" = "Appel manqué de '%@' car vous devez activer la permission 'Appels vocaux et vidéo' dans les paramètres de confidentialité.";
"media_saved" = "%@ a enregistré le média.";
"media_saved" = "Média enregistré par %@.";
"screenshot_taken" = "%@ a pris une capture d'écran.";
"SEARCH_SECTION_CONTACTS" = "Contacts et Groupes";
"SEARCH_SECTION_MESSAGES" = "Messages";
@ -402,56 +397,51 @@
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Effacer";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Êtes-vous sûr de vouloir supprimer cette demande de message ?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Êtes-vous sûr de vouloir bloquer ce contact ?";
"MESSAGE_REQUESTS_INFO" = "Envoyer un message à cet utilisateur acceptera automatiquement sa demande de message.";
"MESSAGE_REQUESTS_INFO" = "Envoyer un message à cet utilisateur acceptera automatiquement sa demande de message et révélera votre ID de session.";
"MESSAGE_REQUESTS_ACCEPTED" = "Votre demande de message a été réceptionnée.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Vous avez une nouvelle demande de message";
"TXT_HIDE_TITLE" = "Masquer";
"TXT_DELETE_ACCEPT" = "Accepter";
"TXT_BLOCK_USER_TITLE" = "Bloquer Utilisateur";
"TXT_BLOCK_USER_TITLE" = "Bloquer l'utilisateur";
"ALERT_ERROR_TITLE" = "Erreur";
"modal_call_permission_request_title" = "Autorisation d'appel requise";
"modal_call_permission_request_title" = "Autorisations d'appel requises";
"modal_call_permission_request_explanation" = "Vous pouvez activer la permission \"Appels vocaux et vidéo\" dans les paramètres de confidentialité.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oups, une erreur est survenue";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Une erreur s'est produite !";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Veuillez réessayer plus tard";
"LOADING_CONVERSATIONS" = "Chargement des conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "Une erreur est survenue pendant l'optimisation de la base de données\n\nVous pouvez exporter votre journal d'application pour le partager et aider à régler le problème ou vous pouvez restaurer votre appareil\n\nAttention : restaurer votre appareil résultera en une perte des données des deux dernières semaines";
"RECOVERY_PHASE_ERROR_GENERIC" = "Quelque chose s'est mal passé. Vérifiez votre phrase de récupération et réessayez s'il vous plaît.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Il semble que vous n'avez pas saisi tous les mots. Vérifiez votre phrase de récupération et réessayez s'il vous plaît.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Il semble qu'il vous manque le dernier mot de votre phrase de récupération. Vérifiez votre saisie et réessayez s'il vous plaît.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Il semble qu'il y a un mot invalide dans votre phrase de récupération. Vérifiez votre saisie et réessayez s'il vous plaît.";
"RECOVERY_PHASE_ERROR_FAILED" = "Votre phrase de récupération n'a pas pu être validée. Vérifiez votre saisie et réessayez s'il vous plaît.";
"DATABASE_MIGRATION_FAILED" = "Une erreur s'est produite lors de l'optimisation de la base de données\n\nVous pouvez exporter vos journaux d'application pour être en mesure de partager pour dépannage ou vous pouvez restaurer votre appareil\n\nAttention : la restauration de votre appareil entraînera la perte de toutes les données de plus de deux semaines";
"RECOVERY_PHASE_ERROR_GENERIC" = "Quelque chose s'est mal passé. Veuillez vérifier votre phrase de récupération et réessayer.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Il semble que vous n'ayez pas saisi suffisamment de mots. Veuillez vérifier votre phrase de récupération et réessayer.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Le dernier mot de votre phrase de récupération semble manquant. Veuillez vérifier ce que vous avez entré et réessayer.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Il semble y avoir un mot invalide dans votre phrase de récupération. Veuillez vérifier ce que vous avez entré et réessayez.";
"RECOVERY_PHASE_ERROR_FAILED" = "Votre phrase de récupération n'a pas pu être vérifiée. Veuillez vérifier ce que vous avez saisi et réessayer.";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "L'authentification a échoué.";
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Impossible daccéder à lauthentification.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Échec dauthentification";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Échec dauthentification.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Trop dessais infructueux dauthentification. Veuillez réessayer plus tard.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Trop déchecs de tentatives dauthentification. Veuillez ressayer ultérieurement.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou décran.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrouillage de lécran.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou décran.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrouillage de lécran.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrou décran.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Vous devez activer un code dans vos réglages iOS pour utiliser le verrouillage de lécran.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Envoyer";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Réessayer";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Montrer Discussion";
"SHOW_THREAD_BUTTON_TITLE" = "Afficher le chat";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Échec d'envoi de votre message.";
"INVALID_SESSION_ID_MESSAGE" = "Veuillez vérifier l'ID Session et réessayez.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Veuillez vérifier la phrase de récupération et réessayez.";
"QUOTED_MESSAGE_NOT_FOUND" = "Message original non trouvé.";
"MEDIA_TAB_TITLE" = "Média";
"SEND_FAILED_NOTIFICATION_BODY" = "Lenvoi de votre message a échoué.";
"INVALID_SESSION_ID_MESSAGE" = "Veuillez vérifier le Session ID et réessayer.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Veuillez vérifier la phrase de récupération et réessayer.";
"MEDIA_TAB_TITLE" = "Médias";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "Vous n'avez aucun document dans cette conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Chargement des documents les plus récents…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Chargement des documents les plus anciens…";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Chargement du document plus récent…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Chargement du document plus ancien…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activités";
/* The name for the emoji category 'Animals & Nature' */
@ -463,188 +453,363 @@
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objets";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Récents";
"EMOJI_CATEGORY_RECENTS_NAME" = "Fréquemment Utilisés";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & Personnes";
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Émoticônes & Personnes";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symboles";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Voyages et Lieux";
"EMOJI_REACTS_NOTIFICATION" = "%@ a réagi au message de %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "et 1 autre personne a réagi %@ à ce message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "et %@ autres personnes ont réagi %@ à ce message.";
"EMOJI_REACTS_SHOW_LESS" = "Moins";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Ralentissez ! Vous avez envoyé trop de réactions Emojis. Réessayez un peu plus tard.";
"EMOJI_CATEGORY_TRAVEL_NAME" = "Voyages & Lieux";
"EMOJI_REACTS_NOTIFICATION" = "%@ réagit à un message avec %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Et 1 autre a réagi %@ à ce message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "Et %@ autres ont réagi %@ à ce message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Ralentissez ! Vous avez envoyé trop d'émoticônes. Réessayez bientôt.";
/* New conversation screen*/
"vc_new_conversation_title" = "Nouvelle Conversation";
"vc_new_conversation_title" = "Nouvelle conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Créer";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Rejoindre";
"PRIVACY_TITLE" = "Confidentialité";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Sécurité de lécran";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Sécurité d'écran";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Verrouiller Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Requiert Touch ID, Face ID ou votre code pour déverrouiller Session.";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Exiger Touch ID, Face ID ou votre code d'accès pour déverrouiller Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Accusés de lecture";
"PRIVACY_READ_RECEIPTS_TITLE" = "Accusés de lecture";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Envoyer un accusé réception dans les conversations 1 à 1.";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Envoyer des accusés de lecture dans les conversations individuelles.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indicateurs de saisie";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indicateurs de saisie";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Voir et partager l'indicateur de saisie dans les conversions 1 à 1.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Aperçus des liens";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Envoyer des aperçus de liens.";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Générer un lien d'aperçu pour les URL supportées.";
"PRIVACY_SECTION_CALLS" = "Appels (Béta)";
"PRIVACY_CALLS_TITLE" = "Appels audio et vidéo";
"PRIVACY_CALLS_DESCRIPTION" = "Active les appels voix et vidéos de et vers d'autres utilisateurs.";
"PRIVACY_CALLS_WARNING_TITLE" = "Appels voix et vidéo (Béta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Votre adresse IP est visible de votre partenaire d'appel et d'un serveur de Oxen Foundation pendant l'utilisation d'un appel. Êtes-vous certain de vouloir activer les appels voix et vidéo ?";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "Voir et envoyer les indicateurs de saisie dans les conversations un à un.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Aperçus de liens";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Envoyer les aperçus des liens";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Générer des aperçus de liens pour les URL supportées.";
"PRIVACY_SECTION_CALLS" = "Appels (Beta)";
"PRIVACY_CALLS_TITLE" = "Appels vocaux et vidéos";
"PRIVACY_CALLS_DESCRIPTION" = "Active les appels vocaux et vidéo vers et depuis d'autres utilisateurs.";
"PRIVACY_CALLS_WARNING_TITLE" = "Appels vocaux et vidéo (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Votre adresse IP est visible par votre interlocuteur et un serveur d'Oxen Foundation lorsque que vous utilisez les appels beta. Voulez-vous vraiment activer les appels vocaux et vidéo ?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Stratégie de notification";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Utiliser le mode rapide";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Vous serez notifiés des nouveaux messages de manière fiable et rapide en utilisant les serveurs de notifications d'Apple.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Aller aux paramètres de notification";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Utiliser le Mode Rapide";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Vous serez averti de nouveaux messages de manière fiable et immédiate en utilisant les serveurs de notification d'Apple.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Accédez aux paramètres de notifications de l'appareil";
"NOTIFICATIONS_SECTION_STYLE" = "Style de notification";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Son";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Son quand l'application est ouverte";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Contenu des notifications";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "L'information qui apparaît dans les notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Nom et contenu";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Nom seulement";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Ni nom ni contenu";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Son à l'ouverture de l'application";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Contenu de la notification";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Informations affichées dans les notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Nom & Contenu";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Nom uniquement";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Épuration des messages";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Épuration des communautés";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Supprimer les messages datant de plus de 6 mois dans les communautés ayant plus de 2000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Messages audio";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Jouer automatiquement les messages audio";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Jouer automatiquement les messages audio de manière consécutive.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Contacts bloqués";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Vous n'avez aucun contact bloqué.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Débloquer";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Êtes-vous sûr de vouloir débloquer %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "Ce contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Êtes-vous sûr de vouloir débloquer %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "et %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "et %d autres?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Débloquer";
"APPEARANCE_TITLE" = "Apparence";
"APPEARANCE_THEMES_TITLE" = "Thèmes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Couleur primaire";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Comment allez-vous ?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Je vais bien, et vous ?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Je vais très bien. Merci.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Mode nuit automatique";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Se conformer aux paramètres système";
"HELP_TITLE" = "Aide";
"HELP_REPORT_BUG_TITLE" = "Rapporter un bogue";
"HELP_REPORT_BUG_DESCRIPTION" = "Exporter votre journal d'application et téléverser le fichier via le support Session.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Exporter Journal";
"HELP_TRANSLATE_TITLE" = "Traduire Session";
"HELP_FEEDBACK_TITLE" = "Nous aimerions votre retour d'expérience";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"modal_clear_all_data_title" = "Effacer toutes les données";
"modal_clear_all_data_explanation" = "Ceci supprimera de manière permanente vos messages et contacts. Voulez-vous effacer vos données sur cet appareil seulement ou sur le réseau aussi ?";
"modal_clear_all_data_explanation_2" = "Êtes-vous sûr de vouloir effacer les données sur le réseau ? Si vous continuez, vous ne pourrez restaurer ni vos messages ni vos contacts.";
"modal_clear_all_data_device_only_button_title" = "Effacer sur l'appareil seulement";
"modal_clear_all_data_entire_account_button_title" = "Effacer sur l'appareil et le réseau";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"dialog_clear_all_data_deletion_failed_1" = "Les données nont pas été supprimées sur un nœud de service. ID du nœud de service : %@.";
"dialog_clear_all_data_deletion_failed_2" = "Les données nont pas été supprimées sur %@ nœuds de service. ID des nœuds de service : %@.";
"modal_clear_all_data_confirm" = "Effacer";
"modal_clear_all_data_confirm" = "Clear";
"modal_seed_title" = "Votre phrase de récupération";
"modal_seed_explanation" = "Vous pouvez utiliser votre phrase de récupération pour restaurer votre compte ou pour lier un autre appareil.";
"modal_permission_explanation" = "Session a besoin de l'accès %@ pour pouvoir continuer. Vous pouvez donner cet accès depuis les paramètres iOS.";
"modal_permission_settings_title" = "Paramètres";
"modal_permission_camera" = "caméra";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "disque";
"DISAPPEARING_MESSAGES_OFF" = "Éteint";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Éteint";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disparaît après : %@";
"COPY_GROUP_URL" = "Copier l'URL de Groupe";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Veuillez choisir au moins 1 membre de groupe";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Veuillez patienter pendant la création du groupe...";
"GROUP_CREATION_ERROR_TITLE" = "Impossible de créer le groupe";
"GROUP_CREATION_ERROR_MESSAGE" = "Veuillez vérifier votre connexion internet et réessayez.";
"GROUP_CREATION_ERROR_MESSAGE" = "Veuillez vérifier votre connexion internet et réessayer.";
"GROUP_UPDATE_ERROR_TITLE" = "Impossible de mettre à jour le groupe";
"GROUP_UPDATE_ERROR_MESSAGE" = "Impossible de quitter pendant l'ajout ou la suppression d'un autre membre.";
"GROUP_ACTION_REMOVE" = "Retirer";
"GROUP_UPDATE_ERROR_MESSAGE" = "Impossible de quitter lors de l'ajout ou la suppression d'autres membres.";
"GROUP_ACTION_REMOVE" = "Supprimer";
"GROUP_TITLE_MEMBERS" = "Membres";
"GROUP_TITLE_FALLBACK" = "Groupe";
"DM_ERROR_DIRECT_BLINDED_ID" = "Vous pouvez seulement envoyer des messages à des IDs anonymes depuis une communauté";
"DM_ERROR_INVALID" = "Veuillez vérifier l'ID Session ou l'ONS et réessayez";
"COMMUNITY_ERROR_INVALID_URL" = "Veuillez vérifier l'URL et réessayez";
"DM_ERROR_DIRECT_BLINDED_ID" = "Vous pouvez seulement envoyer des messages aux identifiants aveugles depuis une communauté";
"DM_ERROR_INVALID" = "Veuillez vérifier l'ID de Session ou le nom ONS et réessayer";
"COMMUNITY_ERROR_INVALID_URL" = "Veuillez vérifier l'URL que vous avez saisie et réessayer.";
"COMMUNITY_ERROR_GENERIC" = "Impossible de rejoindre";
"DISAPPERING_MESSAGES_TITLE" = "Messages éphémères";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Type de suppression";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disparaît après lecture";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Les messages disparaissent une fois lus.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disparaît après envoi";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Les messages disparaissent une fois envoyés.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Compteur";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Sauver";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Ce paramètre s'applique à toutes les personnes de cette conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Ce paramètre s'applique à toutes les personnes de cette conversation. Seuls les administrateurs du groupe peuvent changer ce paramètre.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disparaît après %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ a paramétré les messages pour qu'ils disparaissent %@ après avoir été %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ a paramétré les messages pour qu'ils disparaissent %@ après avoir été %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ a désactivé les messages éphémères.";
"MESSAGE_STATE_READ" = "Lu";
"MESSAGE_STATE_SENT" = "Envoyé";
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "Vous pourrez envoyer des messages et des pièces jointes une fois que le destinataire aura approuvé votre demande.";
"MESSAGE_DELIVERY_STATUS_SENDING" = "Envoi";
"MESSAGE_DELIVERY_STATUS_SENT" = "Envoyé";
"MESSAGE_DELIVERY_STATUS_READ" = "Lu";
"MESSAGE_DELIVERY_STATUS_FAILED" = "Échec de l'envoi";
"MESSAGE_INFO_SENT" = "Envoyé";
"MESSAGE_INFO_RECEIVED" = "Reçu";
"MESSAGE_INFO_FROM" = "De";
"ATTACHMENT_INFO_FILE_ID" = "ID Fichier";
"ATTACHMENT_INFO_FILE_TYPE" = "Type Fichier";
"ATTACHMENT_INFO_FILE_SIZE" = "Taille Fichier";
"ATTACHMENT_INFO_RESOLUTION" = "Résolution";
"ATTACHMENT_INFO_DURATION" = "Durée";
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Échec de synchronisation";
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Synchronisation";
"MESSAGE_DELIVERY_FAILED_TITLE" = "Échec d'envoi du message";
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Échec de synchronisation vers vos autres appareils";
"delete_message_for_me_and_my_devices" = "Effacer sur mes autres appareils";
"context_menu_resend" = "Réenvoyer";
"context_menu_resync" = "Resynchroniser";
"GIPHY_PERMISSION_TITLE" = "Rechercher GIFs?";
"GIPHY_PERMISSION_MESSAGE" = "Session va se connecter à Giphy. Envoyer des GIFs empêchera la protection de vos métadonnées.";
"message_info_title" = "Info Message";
"mute_button_text" = "Silence";
"unmute_button_text" = "Actif";
"mark_read_button_text" = "Marquer comme lu";
"mark_unread_button_text" = "Marquer comme non lu";
"leave_group_confirmation_alert_title" = "Quitter le groupe";
"leave_community_confirmation_alert_title" = "Quitter la communauté";
"leave_community_confirmation_alert_message" = "Êtes-vous sûr de vouloir quitter %@?";
"group_you_leaving" = "Quitter...";
"group_leave_error" = "Impossible de quitter le groupe!";
"group_unable_to_leave" = "Impossible de quitter le groupe, veuillez réessayer";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Les messages sont supprimés après avoir été lus.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disparaît après l'envoi";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Les messages sont supprimés après avoir été envoyés.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Minuteur";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Appliquer";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Ce paramètre s'applique à tout le monde dans cette conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
"delete_conversation_confirmation_alert_title" = "Supprimer conversation";
"delete_conversation_confirmation_alert_message" = "Êtes-vous sûr de vouloir supprimer votre conversation avec %@ ?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -15,7 +15,7 @@
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "अनुलग्नक भेजने में त्रुटि";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Unable to convert image.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "छवि प्रच्छन्न करने मे असफल";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Unable to process video.";
/* Attachment error message for image attachments which cannot be parsed */
@ -113,7 +113,7 @@
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = " %@ समूह से हटा दिए गये हैं ";
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Title is now '%@'. ";
/* No comment provided by engineer. */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "ग्रुप को छोड़ें";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "सभी मीडिया";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "फोटो लाइब्रेरी";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "संदेश %d हटाएं";
/* Confirmation button text to delete selected media message from the gallery */
@ -165,7 +163,7 @@
/* Lock screen notification text presented after user powers on their device without unlocking. Embeds {{device model}} (either 'iPad' or 'iPhone') */
"NOTIFICATION_BODY_PHONE_LOCKED_FORMAT" = "हो सकता है कि आपका %@ पुनरारंभ होने के दौरान आपको संदेश प्राप्त हुए हों।";
/* No comment provided by engineer. */
"BUTTON_OK" = "ठीक है";
"BUTTON_OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@ ने गायब संदेश अक्षम कर दिए हैं।";
/* Info Message when {{other user}} updates message expiration to {{time amount}}, see the *_TIME_AMOUNT strings for context. */
@ -291,18 +289,16 @@
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_scan_qr_code_grant_camera_access_button_title" = "Grant Camera Access";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Enter a group name";
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
"vc_create_closed_group_empty_state_button_title" = "Start a Session";
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Open Group URL";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_enter_chat_url_text_field_hint" = "Enter an open group URL";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Settings";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Please pick a display name";
@ -366,7 +362,6 @@
"delete_message_for_me" = "Delete just for me";
"delete_message_for_everyone" = "Delete for everyone";
"delete_message_for_me_and_recipient" = "Delete for me and %@";
"context_menu_info" = "Info";
"context_menu_reply" = "Reply";
"context_menu_save" = "Save";
"context_menu_ban_user" = "Ban User";
@ -394,7 +389,7 @@
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ took a screenshot.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "संदेश";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
@ -414,10 +409,6 @@
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
@ -427,15 +418,15 @@
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "प्रमाणीकरण असफल";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "बहुत सारी असफल प्रमाणीकरण की कोशिशें हुई हैं। कृपया थोङी देर बाद कोशिश करें।";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "सक्रीन लॉक इस्तेमाल करने के लिये अपने iOS सेटिंग्स से पासकोड की अनुमति दें।";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
@ -446,7 +437,6 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
@ -473,7 +463,6 @@
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
@ -508,8 +497,8 @@
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "केवल नाम";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "कोई नाम या सामग्री नहीं";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
@ -584,67 +573,243 @@
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

View File

@ -15,23 +15,23 @@
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Pogreška kod slanja privitka";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Neuspješna pretvorba slike";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Nije moguće pretvoriti sliku.";
/* Attachment error message for video attachments which could not be converted to MP4 */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Neuspješna obrada videozapisa.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_MP4" = "Nije moguće obraditi videozapis.";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Neuspješna analiza slike.";
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Nije moguće raščlaniti sliku.";
/* Attachment error message for image attachments in which metadata could not be removed */
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Neuspješno uklanjanje metapodataka iz slike.";
"ATTACHMENT_ERROR_COULD_NOT_REMOVE_METADATA" = "Nije moguće izbrisati metapodatke sa slike.";
/* Attachment error message for image attachments which could not be resized */
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Neuspješna promjena veličine slike.";
"ATTACHMENT_ERROR_COULD_NOT_RESIZE_IMAGE" = "Unable to resize image.";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Privitak je prevelik.";
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Attachment is too large.";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Privitak sadrži nevažeći sadržaj.";
"ATTACHMENT_ERROR_INVALID_DATA" = "Attachment includes invalid content.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Privitak ima nevažeći format datoteke.";
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Attachment has an invalid file format.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Privitak je prazan.";
"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty.";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Odabir dokumenta neuspješan.";
/* Alert body when picking a document fails because user picked a directory/bundle */
@ -44,8 +44,8 @@
"BLOCK_LIST_BLOCK_BUTTON" = "Blokiraj";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Blokiraj %@?";
/* A format for the 'unblock conversation' action sheet title. Embeds the {{conversation title}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Deblokiraj %@?";
/* A format for the 'unblock user' action sheet title. Embeds {{the unblocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Deblokiraj";
/* The message format of the 'conversation blocked' alert. Embeds the {{conversation title}}. */
@ -53,7 +53,7 @@
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "Korisnik blokiran";
/* Alert title after unblocking a group or 1:1 chat. Embeds the {{conversation title}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ je deblokiran.";
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE_FORMAT" = "%@ has been unblocked.";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokirani korisnici neće vas moći nazvati niti poslati poruke.";
/* Label for generic done button. */
@ -107,13 +107,13 @@
/* No comment provided by engineer. */
"GROUP_CREATED" = "Kreirana Grupa";
/* No comment provided by engineer. */
"GROUP_MEMBER_JOINED" = "%@ se pridružio grupi. ";
"GROUP_MEMBER_JOINED" = "%@ joined the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ je napustio grupu. ";
"GROUP_MEMBER_LEFT" = "%@ left the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = "%@ je uklonjen iz grupe. ";
"GROUP_MEMBER_REMOVED" = "%@ was removed from the group. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = "%@ su uklonjeni iz grupe. ";
"GROUP_MEMBERS_REMOVED" = "%@ were removed from the group. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Naslov je sada %@. ";
/* No comment provided by engineer. */
@ -134,8 +134,6 @@
"LEAVE_GROUP_ACTION" = "Napusti grupu";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "Sva multimedija";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "Galerija slika";
/* Confirmation button text to delete selected media from the gallery, embeds {{number of messages}} */
"MEDIA_GALLERY_DELETE_MULTIPLE_MESSAGES_FORMAT" = "Izbriši broj poruka %d";
/* Confirmation button text to delete selected media message from the gallery */
@ -286,23 +284,21 @@
"vc_path_service_node_row_title" = "Čvor usluge";
"vc_path_destination_row_title" = "Odredište";
"vc_path_learn_more_button_title" = "Saznaj više";
"vc_create_private_chat_title" = "Nova sesija";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Unesite Session ID";
"vc_create_private_chat_scan_qr_code_tab_title" = "Skeniraj QR kôd";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session treba pristup kameri za skeniranje QR kôdova";
"vc_scan_qr_code_grant_camera_access_button_title" = "Odobri pristup kameri";
"vc_create_closed_group_title" = "Nova zatvorena grupa";
"vc_create_closed_group_title" = "Create Group";
"vc_create_closed_group_text_field_hint" = "Unesite naziv grupe";
"vc_create_closed_group_empty_state_message" = "Još nemate kontakata";
"vc_create_closed_group_empty_state_button_title" = "Pokreni Session razgovor";
"vc_create_closed_group_group_name_missing_error" = "Unesite naziv grupe";
"vc_create_closed_group_group_name_too_long_error" = "Unesite kraći naziv grupe";
"vc_create_closed_group_too_many_group_members_error" = "Zatvorena grupa ne može imati više od 100 članova";
"vc_join_public_chat_title" = "Pridruži se otvorenoj grupi";
"vc_join_public_chat_enter_group_url_tab_title" = "Otvori poveznicu grupe";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Skeniraj QR kôd";
"vc_enter_chat_url_text_field_hint" = "Unesite poveznicu otvorene grupe";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_settings_title" = "Postavke";
"vc_group_settings_title" = "Group Settings";
"vc_settings_display_name_missing_error" = "Molimo odaberite svoje ime za prikaz";
@ -366,7 +362,6 @@
"delete_message_for_me" = "Izbriši samo za mene";
"delete_message_for_everyone" = "Izbriši za sve";
"delete_message_for_me_and_recipient" = "Izbriši za mene i %@";
"context_menu_info" = "Info";
"context_menu_reply" = "Odgovori";
"context_menu_save" = "Spremi";
"context_menu_ban_user" = "Zabrani korisnik";
@ -391,10 +386,10 @@
"UNPIN_BUTTON_TEXT" = "Otkvači";
"modal_call_missed_tips_title" = "Propušten poziv";
"modal_call_missed_tips_explanation" = "Propušten poziv od '%@' jer 'Audio i video pozivi' nemaju dopuštenje u Postavkama privatnosti.";
"media_saved" = "%@ je spremio/la medij.";
"media_saved" = "Media saved by %@.";
"screenshot_taken" = "%@ je napravio/la snimku zaslona.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_MESSAGES" = "Poruke";
"SEARCH_SECTION_MESSAGES" = "Messages";
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
@ -408,16 +403,12 @@
"TXT_HIDE_TITLE" = "Hide";
"TXT_DELETE_ACCEPT" = "Accept";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Greška";
"ALERT_ERROR_TITLE" = "Error";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "You can enable the 'Voice and video calls' permission in the Privacy Settings.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_EXIT" = "Exit";
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
@ -427,15 +418,15 @@
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Provjera autentičnosti nije uspjela.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Previše neuspjelih pokušaja provjere autentičnosti. Pokušajte ponovo kasnije.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Kako biste koristili Zaključavanje zaslona, morate omogućiti lozinku u postavkama iOS-a.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
/* Generic text for button that retries whatever the last action was. */
@ -446,7 +437,6 @@
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
@ -473,43 +463,42 @@
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privatnost";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Sigurnost zaslona";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Potvrda o čitanju";
"PRIVACY_READ_RECEIPTS_TITLE" = "Potvrda o čitanju";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indikatori tipkanja";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indikatori tipkanja";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Pošaljite preglede poveznica";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Audio i video pozivi";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Obavijesti";
"NOTIFICATIONS_SECTION_STRATEGY" = "Strategija obavijesti";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Koristi brzi način";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Sadržaj obavijesti";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Samo ime";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Bez imena ili sadržaja";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
@ -584,67 +573,243 @@
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation. Only group admins can change this setting.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
"MESSAGE_STATE_READ" = "Read";
"MESSAGE_STATE_SENT" = "Sent";
/* context_menu_info */
"context_menu_info" = "Info";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"mark_read_button_text" = "Mark read";
"mark_unread_button_text" = "Mark unread";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"MARK_AS_READ" = "Mark Read";
"MARK_AS_UNREAD" = "Mark Unread";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
/* Warning to indicate one of the users devices is running an old version of Session */
"USER_CONFIG_OUTDATED_WARNING" = "Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.";
/* Ann error displayed if the device is unable to retrieve the users recovery password */
"LOAD_RECOVERY_PASSWORD_ERROR" = "An error occurred when trying to load your recovery password.\n\nPlease export your logs, then upload the file though Session's Help Desk to help resolve this issue.";
/* An error displayed when trying to send a message if the device is unable to save it to the database */
"FAILED_TO_STORE_OUTGOING_MESSAGE" = "An error occurred when trying to store the outgoing message for sending, you may need to restart the app before you can send messages.";
/* An error indicating that the device was unable to access the database for some reason */
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
/* A warning shown at the top of a conversation to indicate a participant is using an old version of Session which may not support the updated disappearing messages functionality */
"DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER" = "%@ is using an outdated client. Disappearing messages may not work as expected.";
/* An error which can occur when a user tries to update from a version that Session no longer supports updating from */
"DATABASE_UNSUPPORTED_MIGRATION" = "You are trying to updated from a version which no longer supports upgrading\n\nIn order to continue to use session you need to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";

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