Merge branch 'dev' into cleanup

This commit is contained in:
Niels Andriesse 2021-05-07 13:06:48 +10:00
commit e3671291c5
44 changed files with 1423 additions and 894 deletions

View File

@ -23,14 +23,12 @@
3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */; };
34480B361FD0929200BC14EF /* ShareAppExtensionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */; };
344825C6211390C800DB4BD8 /* OWSOrphanDataCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 344825C5211390C800DB4BD8 /* OWSOrphanDataCleaner.m */; };
3461284B1FD0B94000532771 /* SAELoadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3461284A1FD0B93F00532771 /* SAELoadViewController.swift */; };
346129991FD1E4DA00532771 /* SignalApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129971FD1E4D900532771 /* SignalApp.m */; };
34641E1F2088DA6D00E2EDE5 /* SAEScreenLockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34641E1E2088DA6D00E2EDE5 /* SAEScreenLockViewController.m */; };
34661FB820C1C0D60056EDD6 /* message_sent.aiff in Resources */ = {isa = PBXBuildFile; fileRef = 34661FB720C1C0D60056EDD6 /* message_sent.aiff */; };
346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; };
3478504C1FD7496D007B8332 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; };
347850551FD749C0007B8332 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; };
347850571FD86544007B8332 /* SAEFailedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850561FD86544007B8332 /* SAEFailedViewController.swift */; };
3488F9362191CC4000E524CC /* MediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3488F9352191CC4000E524CC /* MediaView.swift */; };
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496744E2076ACCE00080B5F /* LongTextViewController.swift */; };
3496955C219B605E00DCFE74 /* ImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34969559219B605E00DCFE74 /* ImagePickerController.swift */; };
@ -75,7 +73,6 @@
4520D8D51D417D8E00123472 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4520D8D41D417D8E00123472 /* Photos.framework */; };
4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */; };
452EC6DF205E9E30000E787C /* MediaGalleryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452EC6DE205E9E30000E787C /* MediaGalleryViewController.swift */; };
4535186B1FC635DD00210559 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4535186A1FC635DD00210559 /* ShareViewController.swift */; };
4535186E1FC635DD00210559 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4535186C1FC635DD00210559 /* MainInterface.storyboard */; };
453518721FC635DD00210559 /* SessionShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 453518681FC635DD00210559 /* SessionShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
@ -159,6 +156,8 @@
B8041A9525C8FA1D003C2166 /* MediaLoaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8041A9425C8FA1D003C2166 /* MediaLoaderView.swift */; };
B8041AA725C90927003C2166 /* TypingIndicatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8041AA625C90927003C2166 /* TypingIndicatorCell.swift */; };
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80A579E23DFF1F300876683 /* NewClosedGroupVC.swift */; };
B817AD9A26436593009DF825 /* SimplifiedConversationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B817AD9926436593009DF825 /* SimplifiedConversationCell.swift */; };
B817AD9C26436F73009DF825 /* ThreadPickerVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B817AD9B26436F73009DF825 /* ThreadPickerVC.swift */; };
B81D25C426157F40004D1FE1 /* storage-seed-3.crt in Resources */ = {isa = PBXBuildFile; fileRef = B81D25B926157F20004D1FE1 /* storage-seed-3.crt */; };
B81D25C526157F40004D1FE1 /* storage-seed-1.crt in Resources */ = {isa = PBXBuildFile; fileRef = B81D25B726157F20004D1FE1 /* storage-seed-1.crt */; };
B81D25C626157F40004D1FE1 /* public-loki-foundation.crt in Resources */ = {isa = PBXBuildFile; fileRef = B81D25B826157F20004D1FE1 /* public-loki-foundation.crt */; };
@ -671,6 +670,7 @@
C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Description.swift */; };
C3AAFFE825AE975D0089E6DD /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */; };
C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFF125AE99710089E6DD /* AppDelegate.swift */; };
C3ADC66126426688005F1414 /* ShareVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3ADC66026426688005F1414 /* ShareVC.swift */; };
C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; };
C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE07F2554CDD70050F1E3 /* Storage.swift */; };
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */; };
@ -953,14 +953,12 @@
34480B381FD092E300BC14EF /* SessionShareExtension-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SessionShareExtension-Prefix.pch"; sourceTree = "<group>"; };
344825C4211390C700DB4BD8 /* OWSOrphanDataCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSOrphanDataCleaner.h; sourceTree = "<group>"; };
344825C5211390C800DB4BD8 /* OWSOrphanDataCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOrphanDataCleaner.m; sourceTree = "<group>"; };
3461284A1FD0B93F00532771 /* SAELoadViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAELoadViewController.swift; sourceTree = "<group>"; };
346129971FD1E4D900532771 /* SignalApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalApp.m; sourceTree = "<group>"; };
346129981FD1E4DA00532771 /* SignalApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalApp.h; sourceTree = "<group>"; };
34641E1D2088DA6C00E2EDE5 /* SAEScreenLockViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SAEScreenLockViewController.h; sourceTree = "<group>"; };
34641E1E2088DA6D00E2EDE5 /* SAEScreenLockViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SAEScreenLockViewController.m; sourceTree = "<group>"; };
34661FB720C1C0D60056EDD6 /* message_sent.aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = message_sent.aiff; path = Session/Meta/AudioFiles/message_sent.aiff; sourceTree = SOURCE_ROOT; };
346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = "<group>"; };
347850561FD86544007B8332 /* SAEFailedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAEFailedViewController.swift; sourceTree = "<group>"; };
3488F9352191CC4000E524CC /* MediaView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaView.swift; sourceTree = "<group>"; };
3496744E2076ACCE00080B5F /* LongTextViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LongTextViewController.swift; sourceTree = "<group>"; };
34969559219B605E00DCFE74 /* ImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePickerController.swift; sourceTree = "<group>"; };
@ -1021,7 +1019,6 @@
4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldHelper.swift; sourceTree = "<group>"; };
452EC6DE205E9E30000E787C /* MediaGalleryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryViewController.swift; sourceTree = "<group>"; };
453518681FC635DD00210559 /* SessionShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4535186A1FC635DD00210559 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
4535186D1FC635DD00210559 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
4535186F1FC635DD00210559 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4539B5851F79348F007141FF /* PushRegistrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushRegistrationManager.swift; sourceTree = "<group>"; };
@ -1135,6 +1132,8 @@
B8041A9425C8FA1D003C2166 /* MediaLoaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaLoaderView.swift; sourceTree = "<group>"; };
B8041AA625C90927003C2166 /* TypingIndicatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingIndicatorCell.swift; sourceTree = "<group>"; };
B80A579E23DFF1F300876683 /* NewClosedGroupVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewClosedGroupVC.swift; sourceTree = "<group>"; };
B817AD9926436593009DF825 /* SimplifiedConversationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplifiedConversationCell.swift; sourceTree = "<group>"; };
B817AD9B26436F73009DF825 /* ThreadPickerVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadPickerVC.swift; sourceTree = "<group>"; };
B81D25B726157F20004D1FE1 /* storage-seed-1.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "storage-seed-1.crt"; sourceTree = "<group>"; };
B81D25B826157F20004D1FE1 /* public-loki-foundation.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "public-loki-foundation.crt"; sourceTree = "<group>"; };
B81D25B926157F20004D1FE1 /* storage-seed-3.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "storage-seed-3.crt"; sourceTree = "<group>"; };
@ -1173,6 +1172,7 @@
B8569AE225CBB19A00DBA3DB /* DocumentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentView.swift; sourceTree = "<group>"; };
B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; };
B87588582644CA9D000E60D0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
B8783E9D23EB948D00404FB8 /* UILabel+Interaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Interaction.swift"; sourceTree = "<group>"; };
B879D448247E1BE300DB3608 /* PathVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathVC.swift; sourceTree = "<group>"; };
B879D44A247E1D9200DB3608 /* PathStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathStatusView.swift; sourceTree = "<group>"; };
@ -1657,6 +1657,7 @@
C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = "Migrating Translations from Android.md"; path = "Meta/Translations/Migrating Translations from Android.md"; sourceTree = "<group>"; };
C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; };
C3AAFFF125AE99710089E6DD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C3ADC66026426688005F1414 /* ShareVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareVC.swift; sourceTree = "<group>"; };
C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = "<group>"; };
C3B7845C25649DA600ADB2E7 /* TSIncomingMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSIncomingMessage+Conversion.swift"; sourceTree = "<group>"; };
C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
@ -1946,13 +1947,13 @@
children = (
C31C21A4255BCA4800EC2D66 /* Meta */,
4535186C1FC635DD00210559 /* MainInterface.storyboard */,
347850561FD86544007B8332 /* SAEFailedViewController.swift */,
3461284A1FD0B93F00532771 /* SAELoadViewController.swift */,
34641E1D2088DA6C00E2EDE5 /* SAEScreenLockViewController.h */,
34641E1E2088DA6D00E2EDE5 /* SAEScreenLockViewController.m */,
4535186A1FC635DD00210559 /* ShareViewController.swift */,
34480B341FD0929200BC14EF /* ShareAppExtensionContext.h */,
34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */,
C3ADC66026426688005F1414 /* ShareVC.swift */,
B817AD9B26436F73009DF825 /* ThreadPickerVC.swift */,
B817AD9926436593009DF825 /* SimplifiedConversationCell.swift */,
);
path = SessionShareExtension;
sourceTree = "<group>";
@ -3959,6 +3960,7 @@
"vi-VN",
"id-ID",
sk,
nl,
);
mainGroup = D221A07E169C9E5E00537ABF;
productRefGroup = D221A08A169C9E5E00537ABF /* Products */;
@ -4327,11 +4329,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4535186B1FC635DD00210559 /* ShareViewController.swift in Sources */,
B817AD9A26436593009DF825 /* SimplifiedConversationCell.swift in Sources */,
34480B361FD0929200BC14EF /* ShareAppExtensionContext.m in Sources */,
C3ADC66126426688005F1414 /* ShareVC.swift in Sources */,
34641E1F2088DA6D00E2EDE5 /* SAEScreenLockViewController.m in Sources */,
3461284B1FD0B94000532771 /* SAELoadViewController.swift in Sources */,
347850571FD86544007B8332 /* SAEFailedViewController.swift in Sources */,
B817AD9C26436F73009DF825 /* ThreadPickerVC.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5001,6 +5003,7 @@
C396469F2509D41100B0B9F5 /* id-ID */,
C3F0A5B2255C915C007BE2A3 /* en */,
B8EB20E6263F7E4B00773E52 /* sk */,
B87588582644CA9D000E60D0 /* nl */,
);
name = Localizable.strings;
path = Meta/Translations;
@ -5030,7 +5033,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -5051,7 +5054,7 @@
INFOPLIST_FILE = SessionShareExtension/Meta/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -5099,7 +5102,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -5125,7 +5128,7 @@
INFOPLIST_FILE = SessionShareExtension/Meta/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -5160,7 +5163,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -5179,7 +5182,7 @@
INFOPLIST_FILE = SessionNotificationServiceExtension/Meta/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -5230,7 +5233,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -5254,7 +5257,7 @@
INFOPLIST_FILE = SessionNotificationServiceExtension/Meta/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -6115,7 +6118,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -6151,7 +6154,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
@ -6183,7 +6186,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 235;
CURRENT_PROJECT_VERSION = 238;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -6219,7 +6222,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 1.10.1;
MARKETING_VERSION = 1.11.0;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
PRODUCT_NAME = Session;

View File

@ -296,18 +296,18 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
let lastCharacterIndex = newText.index(before: newText.endIndex)
let lastCharacter = newText[lastCharacterIndex]
// Check if there is a whitespace before the '@' or the '@' is the first character
let isCharacterBeforeLastAtSignOrStartOfLine: Bool
let isCharacterBeforeLastWhiteSpaceOrStartOfLine: Bool
if newText.count == 1 {
isCharacterBeforeLastAtSignOrStartOfLine = true // Start of line
isCharacterBeforeLastWhiteSpaceOrStartOfLine = true // Start of line
} else {
let characterBeforeLast = newText[newText.index(before: lastCharacterIndex)]
isCharacterBeforeLastAtSignOrStartOfLine = (characterBeforeLast == "@")
isCharacterBeforeLastWhiteSpaceOrStartOfLine = characterBeforeLast.isWhitespace
}
if lastCharacter == "@" && isCharacterBeforeLastAtSignOrStartOfLine {
if lastCharacter == "@" && isCharacterBeforeLastWhiteSpaceOrStartOfLine {
let candidates = MentionsManager.getMentionCandidates(for: "", in: thread.uniqueId!)
currentMentionStartIndex = lastCharacterIndex
snInputView.showMentionsUI(for: candidates, in: thread)
} else if lastCharacter.isWhitespace {
} else if lastCharacter.isWhitespace || lastCharacter == "@" { // the lastCharacter == "@" is to check for @@
currentMentionStartIndex = nil
snInputView.hideMentionsUI()
} else {

View File

@ -9,7 +9,7 @@ public final class InputTextView : UITextView, UITextViewDelegate {
// MARK: UI Components
private lazy var placeholderLabel: UILabel = {
let result = UILabel()
result.text = "Message"
result.text = NSLocalizedString("vc_conversation_input_prompt", comment: "")
result.font = .systemFont(ofSize: Values.mediumFontSize)
result.textColor = Colors.text.withAlphaComponent(Values.mediumOpacity)
return result
@ -74,7 +74,7 @@ public final class InputTextView : UITextView, UITextViewDelegate {
}
// MARK: Delegate
protocol InputTextViewDelegate : class {
protocol InputTextViewDelegate : AnyObject {
func inputTextViewDidChangeSize(_ inputTextView: InputTextView)
func inputTextViewDidChangeContent(_ inputTextView: InputTextView)

View File

@ -338,7 +338,7 @@ final class InputView : UIView, InputViewButtonDelegate, InputTextViewDelegate,
}
// MARK: Delegate
protocol InputViewDelegate : class, ExpandingAttachmentsButtonDelegate, VoiceMessageRecordingViewDelegate {
protocol InputViewDelegate : AnyObject, ExpandingAttachmentsButtonDelegate, VoiceMessageRecordingViewDelegate {
func showLinkPreviewSuggestionModal()
func handleSendButtonTapped()

View File

@ -61,7 +61,7 @@ final class VoiceMessageRecordingView : UIView {
private lazy var slideToCancelLabel: UILabel = {
let result = UILabel()
result.text = "Slide to cancel"
result.text = NSLocalizedString("vc_conversation_voice_message_cancel_message", comment: "")
result.font = .systemFont(ofSize: Values.smallFontSize)
result.textColor = Colors.text.withAlphaComponent(Values.mediumOpacity)
return result

View File

@ -291,7 +291,7 @@ CGFloat kIconViewLength = 24;
[mainSection addItem:[OWSTableItem
itemWithCustomCellBlock:^{
return [weakSelf
disclosureCellWithName:@"Copy Session ID"
disclosureCellWithName:NSLocalizedString(@"vc_conversation_settings_copy_session_id_button_title", "")
iconName:@"ic_copy"
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(
OWSConversationSettingsViewController, @"copy_session_id")];

View File

@ -23,13 +23,13 @@ final class BlockedModal : Modal {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize)
titleLabel.text = "Unblock \(name)?"
titleLabel.text = String(format: NSLocalizedString("modal_blocked_title", comment: ""), name)
titleLabel.textAlignment = .center
// Message
let messageLabel = UILabel()
messageLabel.textColor = Colors.text
messageLabel.font = .systemFont(ofSize: Values.smallFontSize)
let message = "Are you sure you want to unblock \(name)?"
let message = String(format: NSLocalizedString("modal_blocked_explanation", comment: ""), name)
let attributedMessage = NSMutableAttributedString(string: message)
attributedMessage.addAttributes([ .font : UIFont.boldSystemFont(ofSize: Values.smallFontSize) ], range: (message as NSString).range(of: name))
messageLabel.attributedText = attributedMessage
@ -43,7 +43,7 @@ final class BlockedModal : Modal {
unblockButton.backgroundColor = Colors.buttonBackground
unblockButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
unblockButton.setTitleColor(Colors.text, for: UIControl.State.normal)
unblockButton.setTitle("Unblock", for: UIControl.State.normal)
unblockButton.setTitle(NSLocalizedString("modal_blocked_button_title", comment: ""), for: UIControl.State.normal)
unblockButton.addTarget(self, action: #selector(unblock), for: UIControl.Event.touchUpInside)
// Button stack view
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, unblockButton ])

View File

@ -24,13 +24,13 @@ final class DownloadAttachmentModal : Modal {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize)
titleLabel.text = "Trust \(name)?"
titleLabel.text = String(format: NSLocalizedString("modal_download_attachment_title", comment: ""), name)
titleLabel.textAlignment = .center
// Message
let messageLabel = UILabel()
messageLabel.textColor = Colors.text
messageLabel.font = .systemFont(ofSize: Values.smallFontSize)
let message = "Are you sure you want to download media sent by \(name)?"
let message = String(format: NSLocalizedString("modal_download_attachment_explanation", comment: ""), name)
let attributedMessage = NSMutableAttributedString(string: message)
attributedMessage.addAttributes([ .font : UIFont.boldSystemFont(ofSize: Values.smallFontSize) ], range: (message as NSString).range(of: name))
messageLabel.attributedText = attributedMessage
@ -44,7 +44,7 @@ final class DownloadAttachmentModal : Modal {
downloadButton.backgroundColor = Colors.buttonBackground
downloadButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
downloadButton.setTitleColor(Colors.text, for: UIControl.State.normal)
downloadButton.setTitle("Download", for: UIControl.State.normal)
downloadButton.setTitle(NSLocalizedString("modal_download_button_title", comment: ""), for: UIControl.State.normal)
downloadButton.addTarget(self, action: #selector(trust), for: UIControl.Event.touchUpInside)
// Button stack view
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, downloadButton ])

View File

@ -21,13 +21,13 @@ final class LinkPreviewModal : Modal {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize)
titleLabel.text = "Enable Link Previews?"
titleLabel.text = NSLocalizedString("modal_link_previews_title", comment: "")
titleLabel.textAlignment = .center
// Message
let messageLabel = UILabel()
messageLabel.textColor = Colors.text
messageLabel.font = .systemFont(ofSize: Values.smallFontSize)
let message = "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."
let message = NSLocalizedString("modal_link_previews_explanation", comment: "")
messageLabel.text = message
messageLabel.numberOfLines = 0
messageLabel.lineBreakMode = .byWordWrapping
@ -39,7 +39,7 @@ final class LinkPreviewModal : Modal {
enableButton.backgroundColor = Colors.buttonBackground
enableButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
enableButton.setTitleColor(Colors.text, for: UIControl.State.normal)
enableButton.setTitle("Enable", for: UIControl.State.normal)
enableButton.setTitle(NSLocalizedString("modal_link_previews_button_title", comment: ""), for: UIControl.State.normal)
enableButton.addTarget(self, action: #selector(enable), for: UIControl.Event.touchUpInside)
// Button stack view
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, enableButton ])

View File

@ -21,13 +21,13 @@ final class URLModal : Modal {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize)
titleLabel.text = "Open URL?"
titleLabel.text = NSLocalizedString("modal_open_url_title", comment: "")
titleLabel.textAlignment = .center
// Message
let messageLabel = UILabel()
messageLabel.textColor = Colors.text
messageLabel.font = .systemFont(ofSize: Values.smallFontSize)
let message = "Are you sure you want to open \(url.absoluteString)?"
let message = String(format: NSLocalizedString("modal_open_url_explanation", comment: ""), url.absoluteString)
let attributedMessage = NSMutableAttributedString(string: message)
attributedMessage.addAttributes([ .font : UIFont.boldSystemFont(ofSize: Values.smallFontSize) ], range: (message as NSString).range(of: url.absoluteString))
messageLabel.attributedText = attributedMessage
@ -41,7 +41,7 @@ final class URLModal : Modal {
openButton.backgroundColor = Colors.buttonBackground
openButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
openButton.setTitleColor(Colors.text, for: UIControl.State.normal)
openButton.setTitle("Open", for: UIControl.State.normal)
openButton.setTitle(NSLocalizedString("modal_open_url_button_title", comment: ""), for: UIControl.State.normal)
openButton.addTarget(self, action: #selector(openURL), for: UIControl.Event.touchUpInside)
// Button stack view
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, openButton ])

View File

@ -167,7 +167,7 @@ private final class EnterPublicKeyVC : UIViewController {
// MARK: Components
private lazy var publicKeyTextView: TextView = {
let result = TextView(placeholder: "Enter Session ID or ONS name")
let result = TextView(placeholder: NSLocalizedString("vc_enter_public_key_text_field_hint", comment: ""))
result.autocapitalizationType = .none
return result
}()
@ -308,7 +308,7 @@ private final class EnterPublicKeyVC : UIViewController {
UIPasteboard.general.string = getUserHexEncodedPublicKey()
copyButton.isUserInteractionEnabled = false
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
self.copyButton.setTitle(NSLocalizedString("copied", comment: ""), for: UIControl.State.normal)
}, completion: nil)
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
}

View File

@ -89,7 +89,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
setUpNavBarStyle()
}
updateNavBarButtons()
setNavBarTitle("Messages")
setNavBarTitle(NSLocalizedString("vc_home_title", comment: ""))
// Recovery phrase reminder
let hasViewedSeed = UserDefaults.standard[.hasViewedSeed]
if !hasViewedSeed {
@ -324,7 +324,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
let delete = UITableViewRowAction(style: .destructive, title: NSLocalizedString("TXT_DELETE_TITLE", comment: "")) { [weak self] _, _ in
var message = NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: "")
if let thread = thread as? TSGroupThread, thread.isClosedGroup, thread.groupModel.groupAdminIds.contains(getUserHexEncodedPublicKey()) {
message = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone."
message = NSLocalizedString("admin_group_leave_warning", comment: "")
}
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { [weak self] _ in

View File

@ -1,18 +0,0 @@
TODO: Make a script that does this
* Replace <string name=
* Replace “> → “ = “
* Replace </string> → “;
* Replace activity_ → vc_
* Replace fragment_ → vc_
* Replace dialog_ → modal_
* Replace Firebase Cloud Messaging → Apple Push Notification Service
* Replace fcm_ → apns_
* Replace FCM → APNs
* Replace &gt; → >
* Remove any \
* Check for any unescaped “
* Replace %1$s → %@
* Replace %s → %@
* Replace edit_text → text_field
* Replace Google → Apple

View File

@ -7,7 +7,7 @@
/* Label for the 'update' button in the 'new app version available' alert. */
"APP_UPDATE_NAG_ALERT_UPDATE_BUTTON" = "Aktualisieren";
/* No comment provided by engineer. */
"ATTACHMENT" = "Anhang";
"ATTACHMENT" = "Anhang";
/* One-line label indicating the user can add no more text to the attachment caption. */
"ATTACHMENT_APPROVAL_CAPTION_LENGTH_LIMIT_REACHED" = "Beschriftungslimit erreicht.";
/* placeholder text for an empty captioning field */
@ -181,9 +181,9 @@
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ hat die Gruppe verlassen.";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = " %@ was removed from the group. ";
"GROUP_MEMBER_REMOVED" = " %@ wurde aus der Gruppe entfernt. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = " %@ were removed from the group. ";
"GROUP_MEMBERS_REMOVED" = " %@ wurden aus der Gruppe entfernt. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Titel lautet jetzt »%@«.";
/* No comment provided by engineer. */
@ -191,7 +191,7 @@
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Du hast die Gruppe verlassen.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from the group. ";
"YOU_WERE_REMOVED" = " Du wurdest aus der Gruppe entfernt. ";
/* 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 kannst nicht mehr als %@ Elemente teilen.";
/* alert title */
@ -313,7 +313,7 @@
/* Indicates that the last backup restore succeeded. */
"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED" = "Wiederherstellen der Sicherung erfolgreich";
/* Label for phase row in the in the backup settings view. */
"SETTINGS_BACKUP_PHASE" = "Phase";
"SETTINGS_BACKUP_PHASE" = "Schritt";
/* Label for phase row in the in the backup settings view. */
"SETTINGS_BACKUP_PROGRESS" = "Fortschritt";
/* Label for backup status row in the in the backup settings view. */
@ -337,7 +337,7 @@
/* Setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS" = "Link-Vorschauen senden";
/* Footer for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Previews are supported for Imgur, Instagram, Pinterest, Reddit, and YouTube links.";
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Linkvorschau ist verfügbar für Imgur, Instagram, Pinterest, Reddit, und YouTube Links.";
/* Header for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_HEADER" = "Link-Vorschauen";
/* table section header */
@ -359,7 +359,7 @@
/* Label for the 'typing indicators' setting. */
"SETTINGS_TYPING_INDICATORS" = "Tipp-Indikatoren";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
"SOUNDS_NONE" = "Stumm";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ Tage";
/* 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 */
@ -489,3 +489,37 @@
"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_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.";
"slow_mode_explanation" = "Session sucht gelegentlich im Hintergrund nach neuen Nachrichten.";
"vc_pn_mode_title" = "Nachrichtenmitteilungen";
"vc_notification_settings_notification_mode_title" = "Schnellen Modus benutzen";
"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" = "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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -491,7 +491,9 @@
"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_notification_settings_notification_mode_title" = "Use Fast Mode";
"vc_link_device_recovery_phrase_tab_title" = "Recovery Phrase";
@ -520,3 +522,6 @@
"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...";

View File

@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Escanear código QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Escanea el código QR de una persona para comenzar una conversación con ella";
"vc_view_my_qr_code_explanation" = "Este es tu código QR. Otros usuarios pueden escanearlo para empezar una Session contigo.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -89,11 +89,11 @@
/* The label for the 'restore backup' button. */
"CHECK_FOR_BACKUP_RESTORE" = "بازیابی";
/* Error indicating that the app could not determine that user's iCloud account status */
"CLOUDKIT_STATUS_COULD_NOT_DETERMINE" = "Session could not determine your iCloud account status. Sign in to your iCloud Account in the iOS settings app to backup your Session data.";
"CLOUDKIT_STATUS_COULD_NOT_DETERMINE" = "سشن نتوانست وضعیت اکانت iCloud شما را تشخیص دهد. وارد اکانت iCloud خود از بخش تنظیمات iOS شوید تا بتوانید اطلاعات برنامه ی سشن را بکاپ بگیرید.";
/* Error indicating that user does not have an iCloud account. */
"CLOUDKIT_STATUS_NO_ACCOUNT" = "No iCloud Account. Sign in to your iCloud Account in the iOS settings app to backup your Session data.";
"CLOUDKIT_STATUS_NO_ACCOUNT" = "اکانت iCloud وجود ندارد. وارد اکانت iCloud خود از بخش تنظیمات iOS شوید تا بتوانید اطلاعات برنامه ی سشن را بکاپ بگیرید.";
/* Error indicating that the app was prevented from accessing the user's iCloud account. */
"CLOUDKIT_STATUS_RESTRICTED" = "Session was denied access your iCloud account for backups. Grant Session access to your iCloud Account in the iOS settings app to backup your Session data.";
"CLOUDKIT_STATUS_RESTRICTED" = "دسترسی سشن به اکانت iCloud شما رد شد. به سشن دسترسی لازم به اکانت iCloud خود از بخش تنظیمات iOS بدهید تا بتوانید اطلاعات برنامه ی سشن را بکاپ بگیرید.";
/* Alert body */
"CONFIRM_LEAVE_GROUP_DESCRIPTION" = "شما دیگر قادر به ارسال یا دریافت پیام از این گروه نخواهید بود";
/* Alert title */
@ -103,11 +103,11 @@
/* Title for the 'conversation delete confirmation' alert. */
"CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE" = "گفتگو حذف شود؟";
/* keyboard toolbar label when no messages match the search string */
"CONVERSATION_SEARCH_NO_RESULTS" = "No matches";
"CONVERSATION_SEARCH_NO_RESULTS" = "مشابهی یافت نشد";
/* keyboard toolbar label when exactly 1 message matches the search string */
"CONVERSATION_SEARCH_ONE_RESULT" = "1 match";
"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 of %d matches";
"CONVERSATION_SEARCH_RESULTS_FORMAT" = "%d از %d مورد یافت شد";
/* title for conversation settings screen */
"CONVERSATION_SETTINGS" = "تنظیمات گفت و گو";
/* table cell label in conversation settings */
@ -131,7 +131,7 @@
/* Indicates that this thread is muted until a given date or time. Embeds {{The date or time which the thread is muted until}}. */
"CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT" = "تا %@";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Search Conversation";
"CONVERSATION_SETTINGS_SEARCH" = "جستجو در مکالمه";
/* Label for button to unmute a thread. */
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "خارج کردن از حالت سکوت";
/* Title for the 'crop/scale image' dialog. */
@ -181,9 +181,9 @@
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ از گروه خارج شد.";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = " %@ was removed from the group. ";
"GROUP_MEMBER_REMOVED" = " %@ از گروه حذف شد. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = " %@ were removed from the group. ";
"GROUP_MEMBERS_REMOVED" = " %@ از گروه حذف شدند. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "عنوان ، هم‌اکنون '%@' است.";
/* No comment provided by engineer. */
@ -191,11 +191,11 @@
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "شما از این گروه خارج شده‌اید.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from the group. ";
"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" = "You can't share more than %@ items.";
"IMAGE_PICKER_CAN_SELECT_NO_MORE_TOAST_FORMAT" = "شما نمی توانید بیش از %@ آیتم را به اشتراک بگذارید.";
/* alert title */
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "Failed to select attachment.";
"IMAGE_PICKER_FAILED_TO_PROCESS_ATTACHMENTS" = "انتخاب پیوست ناموفق بود.";
/* Message for the alert indicating that an audio file is invalid. */
"INVALID_AUDIO_FILE_ALERT_ERROR_MESSAGE" = "فایل صوتی نامعتبر.";
/* Slider label when disappearing messages is off */
@ -245,9 +245,9 @@
/* An explanation of the consequences of muting a thread. */
"MUTE_BEHAVIOR_EXPLANATION" = "شما هیچ اعلانی از گفتگوهای ساکت‌شده دریافت نخواهید کرد.";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ to %@";
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ در %@";
/* Label for 1:1 conversation with yourself. */
"NOTE_TO_SELF" = "Note to Self";
"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. */
@ -261,21 +261,21 @@
/* No comment provided by engineer. */
"NOTIFICATIONS_SENDER_ONLY" = "فقط نام";
/* No comment provided by engineer. */
"NOTIFICATIONS_SHOW" = "نمایش";
/* No comment provided by engineer. */
"NOTIFICATIONS_NONE" = "هیچ نام و یا محتوایی وجود ندارد";
/* No comment provided by engineer. */
"NOTIFICATIONS_SHOW" = "نمایش";
/* No comment provided by engineer. */
"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" = "Unable to capture image.";
"PHOTO_CAPTURE_GENERIC_ERROR" = "مشکل در گرفتن تصویر.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Unable to capture image.";
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "مشکل در گرفتن تصویر.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Failed to configure camera.";
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "مشکل در نتظیمات دوربین.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "آلبوم بی نام";
/* alert body during registration */
@ -289,7 +289,7 @@
/* 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";
/* alert action when the user decides not to cancel the media flow after all. */
"SEND_MEDIA_RETURN_TO_CAMERA" = "Return to Camera";
"SEND_MEDIA_RETURN_TO_CAMERA" = "بازگشت به دوربین";
/* alert action when the user decides not to cancel the media flow after all. */
"SEND_MEDIA_RETURN_TO_MEDIA_LIBRARY" = "Return to Media Library";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
@ -305,13 +305,13 @@
/* Label for iCloud status row in the in the backup settings view. */
"SETTINGS_BACKUP_ICLOUD_STATUS" = "وضعیت iCloud";
/* Indicates that the last backup restore failed. */
"SETTINGS_BACKUP_IMPORT_STATUS_FAILED" = "Backup Restore Failed";
"SETTINGS_BACKUP_IMPORT_STATUS_FAILED" = "ناتوانی در بازگرداندن بکاپ";
/* Indicates that app is not restoring up. */
"SETTINGS_BACKUP_IMPORT_STATUS_IDLE" = "Backup Restore Idle";
/* Indicates that app is restoring up. */
"SETTINGS_BACKUP_IMPORT_STATUS_IN_PROGRESS" = "Backup Restore In Progress";
"SETTINGS_BACKUP_IMPORT_STATUS_IN_PROGRESS" = "در حال بازگرداندن بکاپ";
/* Indicates that the last backup restore succeeded. */
"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED" = "Backup Restore Succeeded";
"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED" = "بازگرداندن بکاپ موفقیت‌آمیز بود";
/* Label for phase row in the in the backup settings view. */
"SETTINGS_BACKUP_PHASE" = "فاز";
/* Label for phase row in the in the backup settings view. */
@ -335,11 +335,11 @@
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "صدای پیام";
/* Setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS" = "Send Link Previews";
"SETTINGS_LINK_PREVIEWS" = "ارسال پیش نمایش لینک";
/* Footer for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Previews are supported for Imgur, Instagram, Pinterest, Reddit, and YouTube links.";
"SETTINGS_LINK_PREVIEWS_FOOTER" = "پیش نمایش ها برای Imgur، Instagram، Pinterest، Reddit، و لینک های Youtube پشتیبانی می شود.";
/* Header for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_HEADER" = "Link Previews";
"SETTINGS_LINK_PREVIEWS_HEADER" = "پیش نمایش های لینک";
/* table section header */
"SETTINGS_NOTIFICATION_CONTENT_TITLE" = "محتوای نوتیفیکیشن";
/* Label for the 'read receipts' setting. */
@ -359,7 +359,7 @@
/* Label for the 'typing indicators' setting. */
"SETTINGS_TYPING_INDICATORS" = "نشانگر های نوشته";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
"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 */
@ -489,3 +489,37 @@
"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 شماست. سایر کاربران می‌توانند برای شروع Session با شما آن را اسکن کنند.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "استفاده از حالت سریع";
"vc_link_device_recovery_phrase_tab_title" = "عبارت بازیابی";
"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" = "عبارت بازیابی";
"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";
"vc_home_title" = "پیام ها";
"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" = "یا به یکی از اینها بپیوندید...";
"vc_settings_invite_a_friend_button_title" = "دعوت از یک دوست";
"vc_settings_help_us_translate_button_title" = "به ما کمک کنید که سشن را ترجمه کنیم";
"copied" = "کپی شد";
"vc_conversation_settings_copy_session_id_button_title" = "کپی کردن شناسه‌ی Session شما";
"vc_conversation_input_prompt" = "پیام";
"vc_conversation_voice_message_cancel_message" = "برای کنسل کردن به کناره بکشید";
"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" = "URL باز شود؟";
"modal_open_url_explanation" = "آیا مطمئن هستید که میخواهید %@ را باز کنید؟";
"modal_open_url_button_title" = "باز کن";
"modal_blocked_title" = "Unblock %@?";
"modal_blocked_explanation" = "Are you sure you want to unblock %@?";
"modal_blocked_button_title" = "رفع مسدودی";
"modal_link_previews_title" = "فعال‌سازی پیش‌نمایش لینک؟";
"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" = "اشتراک گذاری با Session";
"vc_share_loading_message" = "آماده سازی پیوست‌ها...";
"vc_share_sending_message" = "در حال ارسال...";

View File

@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Scanner le code QR";
"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.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -257,14 +257,14 @@
/* Label for settings UI that allows user to change the notification sound. */
"NOTIFICATIONS_SECTION_SOUNDS" = "Suara";
/* No comment provided by engineer. */
"NOTIFICATIONS_SHOW" = "Tampilkan";
/* No comment provided by engineer. */
"NOTIFICATIONS_SENDER_AND_MESSAGE" = "Nama dan Isi";
/* No comment provided by engineer. */
"NOTIFICATIONS_SENDER_ONLY" = "Nama Saja";
/* No comment provided by engineer. */
"NOTIFICATIONS_NONE" = "Tanpa Nama atau Isi";
/* No comment provided by engineer. */
"NOTIFICATIONS_SHOW" = "Tampilkan";
/* No comment provided by engineer. */
"OK" = "OK";
/* Info Message when {{other user}} disables or doesn't support disappearing messages */
"OTHER_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "%@menonaktifkan pesan tersembunyi";
@ -463,7 +463,6 @@
"vc_create_closed_group_empty_state_button_title" = "Mulai sebuah Session";
"vc_create_closed_group_group_name_missing_error" = "Masukkan nama grup";
"vc_create_closed_group_group_name_too_long_error" = "Masukkan nama grup yang lebih pendek";
"vc_create_closed_group_not_enough_group_members_error" = "Pilih setidaknya 2 anggota grup";
"vc_create_closed_group_too_many_group_members_error" = "Grup tertutup maksimal berisi 100 anggota";
"vc_join_public_chat_title" = "Gabung ke grup terbuka";
"vc_join_public_chat_enter_group_url_tab_title" = "Buka URL grup";
@ -490,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Pindai kode QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Pindai kode QR pengguna lain untuk memulai percakapan";
"vc_view_my_qr_code_explanation" = "Ini adalah kode QR anda. Pengguna lain bisa memindainya untuk memulai percakapan dengan anda";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Scansiona il codice QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Scansiona il codice QR di un utente per iniziare una conversazione con questa persona";
"vc_view_my_qr_code_explanation" = "Questo è il tuo codice QR. Altri utenti possono scansionarlo per iniziare una sessione con te.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -463,7 +463,6 @@
"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_not_enough_group_members_error" = "グループメンバーを少なくとも 2 人選択してください";
"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 を開く";
@ -490,3 +489,37 @@
"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 コードです。他のユーザーはそれをスキャンして、あなたとの Session を開始できます。";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -0,0 +1,527 @@
/* Label for the 'dismiss' button in the 'new app version available' alert. */
"APP_UPDATE_NAG_ALERT_DISMISS_BUTTON" = "Niet nu";
/* Message format for the 'new app version available' alert. Embeds: {{The latest app version number}} */
"APP_UPDATE_NAG_ALERT_MESSAGE_FORMAT" = "Versie %@ is nu beschikbaar in de App Store.";
/* Title for the 'new app version available' alert. */
"APP_UPDATE_NAG_ALERT_TITLE" = "Een nieuwe versie van Session is beschikbaar";
/* Label for the 'update' button in the 'new app version available' alert. */
"APP_UPDATE_NAG_ALERT_UPDATE_BUTTON" = "Update";
/* No comment provided by engineer. */
"ATTACHMENT" = "Bijlage";
/* One-line label indicating the user can add no more text to the attachment caption. */
"ATTACHMENT_APPROVAL_CAPTION_LENGTH_LIMIT_REACHED" = "Maximale bijschriftlengte bereikt.";
/* placeholder text for an empty captioning field */
"ATTACHMENT_APPROVAL_CAPTION_PLACEHOLDER" = "Bijschrift toevoegen…";
/* Title for 'caption' mode of the attachment approval view. */
"ATTACHMENT_APPROVAL_CAPTION_TITLE" = "Bijschrift";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "Bestand 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" = "Grootte: %@";
/* One-line label indicating the user can add no more text to the media message field. */
"ATTACHMENT_APPROVAL_MESSAGE_LENGTH_LIMIT_REACHED" = "Maximale berichtlengte bereikt";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Versturen";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Bijlage";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Versturen bijlage mislukt";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Document kiezen mislukt.";
/* 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" = "Niet-ondersteund bestand";
/* Short text label for a voice message attachment, used for thread preview and on the lock screen */
"ATTACHMENT_TYPE_VOICE_MESSAGE" = "Spraakbericht";
/* Error indicating the backup export could not export the user's data. */
"BACKUP_EXPORT_ERROR_COULD_NOT_EXPORT" = "Kan back-upbestand niet exporteren.";
/* Error indicating that the app received an invalid response from CloudKit. */
"BACKUP_EXPORT_ERROR_INVALID_CLOUDKIT_RESPONSE" = "Ongeldige Service Reactie";
/* Indicates that the cloud is being cleaned up. */
"BACKUP_EXPORT_PHASE_CLEAN_UP" = "Backup opschonen";
/* Indicates that the backup export is being configured. */
"BACKUP_EXPORT_PHASE_CONFIGURATION" = "Backup initialiseren";
/* Indicates that the database data is being exported. */
"BACKUP_EXPORT_PHASE_DATABASE_EXPORT" = "Gegevens exporteren";
/* Indicates that the backup export data is being exported. */
"BACKUP_EXPORT_PHASE_EXPORT" = "Backup exporteren";
/* Indicates that the backup export data is being uploaded. */
"BACKUP_EXPORT_PHASE_UPLOAD" = "Uploaden van backup";
/* Error indicating the backup import could not import the user's data. */
"BACKUP_IMPORT_ERROR_COULD_NOT_IMPORT" = "Kan backup niet importeren.";
/* Indicates that the backup import is being configured. */
"BACKUP_IMPORT_PHASE_CONFIGURATION" = "Backup configuratie";
/* Indicates that the backup import data is being downloaded. */
"BACKUP_IMPORT_PHASE_DOWNLOAD" = "Download van backup...";
/* Indicates that the backup import data is being finalized. */
"BACKUP_IMPORT_PHASE_FINALIZING" = "Backup afronden";
/* Indicates that the backup import data is being imported. */
"BACKUP_IMPORT_PHASE_IMPORT" = "Importeren van backup.";
/* Indicates that the backup database is being restored. */
"BACKUP_IMPORT_PHASE_RESTORING_DATABASE" = "Database Herstellen";
/* Indicates that the backup import data is being restored. */
"BACKUP_IMPORT_PHASE_RESTORING_FILES" = "Bestanden herstellen…";
/* Label for the backup restore decision section. */
"BACKUP_RESTORE_DECISION_TITLE" = "Backup beschikbaar";
/* Label for the backup restore description. */
"BACKUP_RESTORE_DESCRIPTION" = "Backup herstellen";
/* Label for the backup restore progress. */
"BACKUP_RESTORE_PROGRESS" = "Vooruitgang";
/* Label for the backup restore status. */
"BACKUP_RESTORE_STATUS" = "Status";
/* Error shown when backup fails due to an unexpected error. */
"BACKUP_UNEXPECTED_ERROR" = "Onverwachte backup fout";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Blokkeren";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "%@ blokkeren?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Deblokkeren";
/* An explanation of the consequences of blocking another user. */
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Geblokkeerde gebruikers zijn niet in staat om u te bellen of berichten te sturen.";
/* Label for generic done button. */
"BUTTON_DONE" = "Ok";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Selecteer";
/* The label for the 'do not restore backup' button. */
"CHECK_FOR_BACKUP_DO_NOT_RESTORE" = "Niet herstellen";
/* The label for the 'restore backup' button. */
"CHECK_FOR_BACKUP_RESTORE" = "Herstellen";
/* Error indicating that the app could not determine that user's iCloud account status */
"CLOUDKIT_STATUS_COULD_NOT_DETERMINE" = "Session kon de status van je iCloud-account niet bepalen. log in met je iCloud-account in de iOS-instellingen app om een backup te maken van je Session gegevens.";
/* Error indicating that user does not have an iCloud account. */
"CLOUDKIT_STATUS_NO_ACCOUNT" = "Geen iCloud-account niet bepalen. log in met je iCloud-account in de iOS-instellingen app om een backup te maken van je Session gegevens.";
/* Error indicating that the app was prevented from accessing the user's iCloud account. */
"CLOUDKIT_STATUS_RESTRICTED" = "Session was denied access your iCloud account for backups. Grant Session access to your iCloud Account in the iOS settings app to backup your Session data.";
/* Alert body */
"CONFIRM_LEAVE_GROUP_DESCRIPTION" = "You will no longer be able to send or receive messages in this group.";
/* Alert title */
"CONFIRM_LEAVE_GROUP_TITLE" = "Do you really want to leave?";
/* Message for the 'conversation delete confirmation' alert. */
"CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE" = "This cannot be undone.";
/* Title for the 'conversation delete confirmation' alert. */
"CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE" = "Delete Conversation?";
/* 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 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 of %d matches";
/* title for conversation settings screen */
"CONVERSATION_SETTINGS" = "Conversation Settings";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block This User";
/* Title of the 'mute this thread' action sheet. */
"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE" = "Mute";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Mute";
/* Indicates that the current thread is not muted. */
"CONVERSATION_SETTINGS_MUTE_NOT_MUTED" = "Not muted";
/* Label for button to mute a thread for a day. */
"CONVERSATION_SETTINGS_MUTE_ONE_DAY_ACTION" = "Mute for one day";
/* Label for button to mute a thread for a hour. */
"CONVERSATION_SETTINGS_MUTE_ONE_HOUR_ACTION" = "Mute for one hour";
/* Label for button to mute a thread for a minute. */
"CONVERSATION_SETTINGS_MUTE_ONE_MINUTE_ACTION" = "Mute for one minute";
/* Label for button to mute a thread for a week. */
"CONVERSATION_SETTINGS_MUTE_ONE_WEEK_ACTION" = "Mute for one week";
/* Label for button to mute a thread for a year. */
"CONVERSATION_SETTINGS_MUTE_ONE_YEAR_ACTION" = "Mute for one year";
/* Indicates that this thread is muted until a given date or time. Embeds {{The date or time which the thread is muted until}}. */
"CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT" = "until %@";
/* Table cell label in conversation settings which returns the user to the conversation with 'search mode' activated */
"CONVERSATION_SETTINGS_SEARCH" = "Search Conversation";
/* Label for button to unmute a thread. */
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "Unmute";
/* 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";
/* Format string for a relative time, expressed as a certain number of hours in the past. Embeds {{The number of hours}}. */
"DATE_HOURS_AGO_FORMAT" = "%@ Hr Ago";
/* Format string for a relative time, expressed as a certain number of minutes in the past. Embeds {{The number of minutes}}. */
"DATE_MINUTES_AGO_FORMAT" = "%@ Min Ago";
/* The present; the current time. */
"DATE_NOW" = "Now";
/* The current day. */
"DATE_TODAY" = "Today";
/* The day before today. */
"DATE_YESTERDAY" = "Yesterday";
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Disappearing Messages";
/* Info Message when added to a group which has enabled disappearing messages. Embeds {{time amount}} before messages disappear, see the *_TIME_AMOUNT strings for context. */
"DISAPPEARING_MESSAGES_CONFIGURATION_GROUP_EXISTING_FORMAT" = "Messages in this conversation will disappear after %@.";
/* table cell label in conversation settings */
"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 */
"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" = "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.";
/* Slider label when disappearing messages is off */
"KEEP_MESSAGES_FOREVER" = "Messages do not disappear.";
/* Confirmation button within contextual alert */
"LEAVE_BUTTON_TITLE" = "Leave";
/* table cell label in conversation settings */
"LEAVE_GROUP_ACTION" = "Leave Group";
/* Title for the 'long text message' view. */
"LONG_TEXT_VIEW_TITLE" = "Message";
/* 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 */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Delete Message";
/* 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" = "You";
/* Section header in media gallery collection view */
"MEDIA_GALLERY_THIS_MONTH_HEADER" = "This Month";
/* message status for message delivered to their recipient. */
"MESSAGE_STATUS_DELIVERED" = "Delivered";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED" = "Sending failed.";
/* status message for failed messages */
"MESSAGE_STATUS_FAILED_SHORT" = "Failed";
/* status message for read messages */
"MESSAGE_STATUS_READ" = "Read";
/* message status if message delivery to a recipient is skipped. We skip delivering group messages to users who have left the group or unregistered their Session account. */
"MESSAGE_STATUS_RECIPIENT_SKIPPED" = "Skipped";
/* message status while message is sending. */
"MESSAGE_STATUS_SENDING" = "Sending…";
/* status message for sent messages */
"MESSAGE_STATUS_SENT" = "Sent";
/* status message while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Uploading…";
/* Alert body when user has previously denied media library access */
"MISSING_MEDIA_LIBRARY_PERMISSION_MESSAGE" = "You can enable this permission in the iOS Settings app.";
/* Alert title when user has previously denied media library access */
"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE" = "Session requires access to your photos for this feature.";
/* An explanation of the consequences of muting a thread. */
"MUTE_BEHAVIOR_EXPLANATION" = "You will not receive notifications for muted conversations.";
/* 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";
/* 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. */
"NOTIFICATIONS_FOOTER_WARNING" = "Due to known bugs in Apple's push framework, message previews will only be shown if the message is retrieved within 30 seconds after being sent. The application badge might be inaccurate as a result.";
/* Table cell switch label. When disabled, Session will not play notification sounds while the app is in the foreground. */
"NOTIFICATIONS_SECTION_INAPP" = "Play While App is Open";
/* Label for settings UI that allows user to change the notification sound. */
"NOTIFICATIONS_SECTION_SOUNDS" = "Sounds";
/* No comment provided by engineer. */
"NOTIFICATIONS_SENDER_AND_MESSAGE" = "Name and Content";
/* No comment provided by engineer. */
"NOTIFICATIONS_SENDER_ONLY" = "Name Only";
/* No comment provided by engineer. */
"NOTIFICATIONS_NONE" = "No Name or Content";
/* No comment provided by engineer. */
"NOTIFICATIONS_SHOW" = "Show";
/* No comment provided by engineer. */
"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";
/* alert body during registration */
"REGISTRATION_ERROR_BLANK_VERIFICATION_CODE" = "We can't activate your account until you verify the code we sent you.";
/* Indicates a delay of zero seconds, and that 'screen lock activity' will timeout immediately. */
"SCREEN_LOCK_ACTIVITY_TIMEOUT_NONE" = "Instant";
/* 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";
/* alert action when the user decides not to cancel the media flow after all. */
"SEND_MEDIA_RETURN_TO_CAMERA" = "Return to Camera";
/* alert action when the user decides not to cancel the media flow after all. */
"SEND_MEDIA_RETURN_TO_MEDIA_LIBRARY" = "Return to Media Library";
/* Format string for the default 'Note' sound. Embeds the system {{sound name}}. */
"SETTINGS_AUDIO_DEFAULT_TONE_LABEL_FORMAT" = "%@ (default)";
/* Label for the backup view in app settings. */
"SETTINGS_BACKUP" = "Backup";
/* Label for 'backup now' button in the backup settings view. */
"SETTINGS_BACKUP_BACKUP_NOW" = "Backup Now";
/* Label for 'cancel backup' button in the backup settings view. */
"SETTINGS_BACKUP_CANCEL_BACKUP" = "Cancel Backup";
/* Label for switch in settings that controls whether or not backup is enabled. */
"SETTINGS_BACKUP_ENABLING_SWITCH" = "Backup Enabled";
/* Label for iCloud status row in the in the backup settings view. */
"SETTINGS_BACKUP_ICLOUD_STATUS" = "iCloud Status";
/* Indicates that the last backup restore failed. */
"SETTINGS_BACKUP_IMPORT_STATUS_FAILED" = "Backup Restore Failed";
/* Indicates that app is not restoring up. */
"SETTINGS_BACKUP_IMPORT_STATUS_IDLE" = "Backup Restore Idle";
/* Indicates that app is restoring up. */
"SETTINGS_BACKUP_IMPORT_STATUS_IN_PROGRESS" = "Backup Restore In Progress";
/* Indicates that the last backup restore succeeded. */
"SETTINGS_BACKUP_IMPORT_STATUS_SUCCEEDED" = "Backup Restore Succeeded";
/* Label for phase row in the in the backup settings view. */
"SETTINGS_BACKUP_PHASE" = "Phase";
/* Label for phase row in the in the backup settings view. */
"SETTINGS_BACKUP_PROGRESS" = "Progress";
/* Label for backup status row in the in the backup settings view. */
"SETTINGS_BACKUP_STATUS" = "Status";
/* Indicates that the last backup failed. */
"SETTINGS_BACKUP_STATUS_FAILED" = "Backup Failed";
/* Indicates that app is not backing up. */
"SETTINGS_BACKUP_STATUS_IDLE" = "Waiting";
/* Indicates that app is backing up. */
"SETTINGS_BACKUP_STATUS_IN_PROGRESS" = "Backing Up";
/* Indicates that the last backup succeeded. */
"SETTINGS_BACKUP_STATUS_SUCCEEDED" = "Backup Successful";
/* No comment provided by engineer. */
"SETTINGS_CLEAR_HISTORY" = "Clear Conversation History";
/* Confirmation text for button which deletes all message, calling, attachments, etc. */
"SETTINGS_DELETE_HISTORYLOG_CONFIRMATION_BUTTON" = "Delete Everything";
/* Section header */
"SETTINGS_HISTORYLOG_TITLE" = "Clear Conversation History";
/* Label for settings view that allows user to change the notification sound. */
"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Message Sound";
/* Setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS" = "Send Link Previews";
/* Footer for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Previews are supported for Imgur, Instagram, Pinterest, Reddit, and YouTube links.";
/* Header for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_HEADER" = "Link Previews";
/* table section header */
"SETTINGS_NOTIFICATION_CONTENT_TITLE" = "Notification Content";
/* Label for the 'read receipts' setting. */
"SETTINGS_READ_RECEIPT" = "Read Receipts";
/* An explanation of the 'read receipts' setting. */
"SETTINGS_READ_RECEIPTS_SECTION_FOOTER" = "See and share when messages have been read. This setting is optional and applies to all conversations.";
/* Label for the 'screen lock activity timeout' setting of the privacy settings. */
"SETTINGS_SCREEN_LOCK_ACTIVITY_TIMEOUT" = "Screen Lock Timeout";
/* Title for the 'screen lock' section of the privacy settings. */
"SETTINGS_SCREEN_LOCK_SECTION_TITLE" = "Screen Lock";
/* Label for the 'enable screen lock' switch of the privacy settings. */
"SETTINGS_SCREEN_LOCK_SWITCH_LABEL" = "Screen Lock";
/* Header Label for the sounds section of settings views. */
"SETTINGS_SECTION_SOUNDS" = "Sounds";
/* Section header */
"SETTINGS_SECURITY_TITLE" = "Screen Security";
/* Label for the 'typing indicators' setting. */
"SETTINGS_TYPING_INDICATORS" = "Typing Indicators";
/* 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 Session";
"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_create_private_chat_scan_qr_code_explanation" = "Scan a users QR code to start a session. QR codes can be found by tapping the QR code icon in account settings.";
"vc_enter_public_key_explanation" = "Users can share their Session ID by going into their account settings and tapping \"Share Session ID\", or by sharing their QR code.";
"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" = "New Closed 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 Open Group";
"vc_join_public_chat_enter_group_url_tab_title" = "Open Group URL";
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
"vc_join_public_chat_scan_qr_code_explanation" = "Scan the QR code of the open group you'd like to join";
"vc_enter_chat_url_text_field_hint" = "Enter an open group URL";
"vc_settings_title" = "Settings";
"vc_settings_display_name_text_field_hint" = "Enter a display name";
"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_notification_settings_title" = "Notifications";
"vc_privacy_settings_title" = "Privacy";
"preferences_notifications_strategy_category_title" = "Notification Strategy";
"modal_seed_title" = "Your Recovery Phrase";
"modal_seed_explanation" = "This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.";
"modal_clear_all_data_title" = "Clear All Data";
"modal_clear_all_data_explanation" = "This will permanently delete your messages, sessions, and contacts.";
"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_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Skanowania QR code";
"vc_qr_code_view_scan_qr_code_explanation" = "Zeskanuj czyjś kod QR, aby rozpocząć z nim rozmowę";
"vc_view_my_qr_code_explanation" = "To jest twój kod QR. Inni użytkownicy mogą go zeskanować, aby rozpocząć z tobą sesję.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -181,9 +181,9 @@
/* No comment provided by engineer. */
"GROUP_MEMBER_LEFT" = "%@ saiu do grupo.";
/* No comment provided by engineer. */
"GROUP_MEMBER_REMOVED" = " %@ was removed from the group. ";
"GROUP_MEMBER_REMOVED" = " %@ foi removido do grupo. ";
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = " %@ were removed from the group. ";
"GROUP_MEMBERS_REMOVED" = " %@ foram removidos do grupo. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "O título agora é '%@'.";
/* No comment provided by engineer. */
@ -191,7 +191,7 @@
/* No comment provided by engineer. */
"GROUP_YOU_LEFT" = "Você saiu do grupo.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from the group. ";
"YOU_WERE_REMOVED" = " Você foi removido do 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" = "Você não pode compartilhar mais de %@ itens.";
/* alert title */
@ -299,9 +299,9 @@
/* Label for 'backup now' button in the backup settings view. */
"SETTINGS_BACKUP_BACKUP_NOW" = "Criar cópia de segurança";
/* Label for 'cancel backup' button in the backup settings view. */
"SETTINGS_BACKUP_CANCEL_BACKUP" = "Cancelar cópia de segurança";
"SETTINGS_BACKUP_CANCEL_BACKUP" = "Cancelar backup";
/* Label for switch in settings that controls whether or not backup is enabled. */
"SETTINGS_BACKUP_ENABLING_SWITCH" = "Cópia de segurança ativada";
"SETTINGS_BACKUP_ENABLING_SWITCH" = "Backup Ativado";
/* Label for iCloud status row in the in the backup settings view. */
"SETTINGS_BACKUP_ICLOUD_STATUS" = "Status da iCloud";
/* Indicates that the last backup restore failed. */
@ -337,7 +337,7 @@
/* Setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS" = "Enviar pré-visualizações de links";
/* Footer for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Previews are supported for Imgur, Instagram, Pinterest, Reddit, and YouTube links.";
"SETTINGS_LINK_PREVIEWS_FOOTER" = "Pré-visualizações de links suportadas para Imgur, Instagram, Pinterest, Reddit e YouTube.";
/* Header for setting for enabling & disabling link previews. */
"SETTINGS_LINK_PREVIEWS_HEADER" = "Pré-visualizações de links";
/* table section header */
@ -359,23 +359,23 @@
/* Label for the 'typing indicators' setting. */
"SETTINGS_TYPING_INDICATORS" = "Indicadores de digitação";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
"SOUNDS_NONE" = "Silencioso";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_DAYS" = "%@ dias";
/* 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" = "%@dias";
/* {{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" = "%@horas";
/* {{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" = "%@minutos";
/* {{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" = "%@segundos";
/* {{1 day}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 day}}'. See other *_TIME_AMOUNT strings */
"TIME_AMOUNT_SINGLE_DAY" = "%@ dia";
/* {{1 hour}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{1 hour}}'. See other *_TIME_AMOUNT strings */
@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Escanear código QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Escaneie o código QR de alguém para iniciar uma conversa com essa pessoa";
"vc_view_my_qr_code_explanation" = "Este é o seu código QR. Outros usuários podem escaneá-lo para iniciar uma sessão com você.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Você será notificado de forma confiável e imediata sobre novas mensagens usando os servidores de notificação da Apple.";
"slow_mode_explanation" = "O session verificará ocasionalmente por novas mensagens em segundo plano.";
"vc_pn_mode_title" = "Notificação de Mensangens";
"vc_notification_settings_notification_mode_title" = "Usar Modo Rápido";
"vc_link_device_recovery_phrase_tab_title" = "Frase de Recuperação";
"vc_link_device_scan_qr_code_explanation" = "Navegue até Configurações -> Frase de Recuperação no outro dispositivo para visualizar seu QR code.";
"vc_enter_recovery_phrase_title" = "Frase de Recuperação";
"vc_enter_recovery_phrase_explanation" = "Para vincular o seu dispositivo, insira a frase de recuperação que foi gerada quando você criou sua conta.";
"vc_enter_public_key_text_field_hint" = "Insira seu ID Session ou ONS";
"vc_home_title" = "Mensagens";
"admin_group_leave_warning" = "Porque você é o criador deste grupo ele será excluído para todos. Isso não pode ser desfeito.";
"vc_join_open_group_suggestions_title" = "Ou junte-se a um desses...";
"vc_settings_invite_a_friend_button_title" = "Convide um amigo";
"vc_settings_help_us_translate_button_title" = "Ajude a traduzir o Session";
"copied" = "Copiado";
"vc_conversation_settings_copy_session_id_button_title" = "Copiar ID Session";
"vc_conversation_input_prompt" = "Mensagem";
"vc_conversation_voice_message_cancel_message" = "Deslize para cancelar";
"modal_download_attachment_title" = "Confiar %@?";
"modal_download_attachment_explanation" = "Você tem certeza que deseja baixar a mídia enviada por %@?";
"modal_download_button_title" = "Download";
"modal_open_url_title" = "Abrir URL?";
"modal_open_url_explanation" = "Você tem certeza que deseja abrir %@/?";
"modal_open_url_button_title" = "Abrir";
"modal_blocked_title" = "Desbloquear %@?";
"modal_blocked_explanation" = "Você tem certeza que deseja desbloquear %@?";
"modal_blocked_button_title" = "Desbloquear";
"modal_link_previews_title" = "Ativar pré-visualizações de link?";
"modal_link_previews_explanation" = "Ativar a pré-visualização de links irá mostrar as URLs que você receber e enviar. Isto pode ser útil, o Session precisa se conectar aos sites vinculados gerar as prévias. Você poderá desabiliatar esta opção nas configurações do Session.";
"modal_link_previews_button_title" = "Ativar";
"vc_share_title" = "Compartilhar no Session";
"vc_share_loading_message" = "Preparando anexos...";
"vc_share_sending_message" = "Enviando...";

View File

@ -520,3 +520,6 @@
"modal_link_previews_title" = "Включить предварительный просмотр ссылок?";
"modal_link_previews_explanation" = "Включение предпросмотра ссылок покажет превью для отправляемых и получаемых ссылок. Это может быть полезно, но Session нужно будет соединиться с сайтами, связанными с ссылками, чтобы сгенерировать предпросмотр. Вы всегда можете отключить предпросмотр ссылок в настройках Session.";
"modal_link_previews_button_title" = "Включить";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sending...";

View File

@ -33,7 +33,7 @@
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Nepodporovaný súbor";
/* 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" = "Hlasová správa";
/* Error indicating the backup export could not export the user's data. */
"BACKUP_EXPORT_ERROR_COULD_NOT_EXPORT" = "Backup data could not be exported.";
/* Error indicating that the app received an invalid response from CloudKit. */
@ -75,13 +75,13 @@
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Blokovať";
/* 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 %@?";
"BLOCK_LIST_BLOCK_USER_TITLE_FORMAT" = "Blokovať %@?";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Odblokovať";
/* 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.";
"BLOCK_USER_BEHAVIOR_EXPLANATION" = "Blokovaný používateľ vám nebude mocť volať ani posielať správy.";
/* Label for generic done button. */
"BUTTON_DONE" = "Done";
"BUTTON_DONE" = "Hotovo";
/* Button text to enable batch selection mode */
"BUTTON_SELECT" = "Vyberte";
/* The label for the 'do not restore backup' button. */
@ -95,7 +95,7 @@
/* Error indicating that the app was prevented from accessing the user's iCloud account. */
"CLOUDKIT_STATUS_RESTRICTED" = "Session was denied access your iCloud account for backups. Grant Session access to your iCloud Account in the iOS settings app to backup your Session data.";
/* Alert body */
"CONFIRM_LEAVE_GROUP_DESCRIPTION" = "You will no longer be able to send or receive messages in this group.";
"CONFIRM_LEAVE_GROUP_DESCRIPTION" = "Už nebudete môcť posielať a prijímať správy v tejto skupine.";
/* Alert title */
"CONFIRM_LEAVE_GROUP_TITLE" = "Ste si istý/á, že chcete odísť?";
/* Message for the 'conversation delete confirmation' alert. */
@ -153,7 +153,7 @@
/* table cell label in conversation settings */
"DISAPPEARING_MESSAGES" = "Miznúce správy";
/* Info Message when added to a group which has enabled disappearing messages. Embeds {{time amount}} before messages disappear, see the *_TIME_AMOUNT strings for context. */
"DISAPPEARING_MESSAGES_CONFIGURATION_GROUP_EXISTING_FORMAT" = "Messages in this conversation will disappear after %@.";
"DISAPPEARING_MESSAGES_CONFIGURATION_GROUP_EXISTING_FORMAT" = "Správy v tejto konverzácii zmiznú po %@.";
/* table cell label in conversation settings */
"EDIT_GROUP_ACTION" = "Upraviť skupinu";
/* Label indicating media gallery is empty */
@ -163,7 +163,7 @@
/* Label indicating loading is in progress */
"GALLERY_TILES_LOADING_OLDER_LABEL" = "Načítavajú sa staršie médiá…";
/* 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.";
"GIF_PICKER_ERROR_FETCH_FAILURE" = "Nepodarilo sa stiahnuť požadovaný GIF. Uistite sa prosím, že ste online.";
/* Generic error displayed when picking a GIF */
"GIF_PICKER_ERROR_GENERIC" = "Vyskytla sa neznáma chyba.";
/* Shown when selected GIF couldn't be fetched */
@ -185,7 +185,7 @@
/* No comment provided by engineer. */
"GROUP_MEMBERS_REMOVED" = " %@ boli odstránení zo skupiny. ";
/* No comment provided by engineer. */
"GROUP_TITLE_CHANGED" = "Title is now '%@'. ";
"GROUP_TITLE_CHANGED" = "Názov je teraz '%@'. ";
/* No comment provided by engineer. */
"GROUP_UPDATED" = "Skupina bola aktualizovaná.";
/* No comment provided by engineer. */
@ -215,7 +215,7 @@
/* Confirmation button text to delete selected media message from the gallery */
"MEDIA_GALLERY_DELETE_SINGLE_MESSAGE" = "Odstrániť správu";
/* embeds {{sender name}} and {{sent datetime}}, e.g. 'Sarah on 10/30/18, 3:29' */
"MEDIA_GALLERY_LANDSCAPE_TITLE_FORMAT" = "%@ on %@";
"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 */
@ -241,9 +241,9 @@
/* Alert body when user has previously denied media library access */
"MISSING_MEDIA_LIBRARY_PERMISSION_MESSAGE" = "You can enable this permission in the iOS Settings app.";
/* Alert title when user has previously denied media library access */
"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE" = "Session requires access to your photos for this feature.";
"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE" = "Session potrebuje prístup k vašim fotkám pre túto funkciu.";
/* An explanation of the consequences of muting a thread. */
"MUTE_BEHAVIOR_EXPLANATION" = "You will not receive notifications for muted conversations.";
"MUTE_BEHAVIOR_EXPLANATION" = "Na stíšené konverzácie nebudete dostávať upozornenia.";
/* notification title. Embeds {{author name}} and {{group name}} */
"NEW_GROUP_MESSAGE_NOTIFICATION_TITLE" = "%@ do %@";
/* Label for 1:1 conversation with yourself. */
@ -271,9 +271,9 @@
/* 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.";
"PHOTO_CAPTURE_GENERIC_ERROR" = "Nepodarilo sa zachytiť obrázok.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Unable to capture image.";
"PHOTO_CAPTURE_UNABLE_TO_CAPTURE_IMAGE" = "Nepodarilo sa zachytiť obrázok.";
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Failed to configure camera.";
/* label for system photo collections which have no name. */
@ -281,13 +281,13 @@
/* alert body during registration */
"REGISTRATION_ERROR_BLANK_VERIFICATION_CODE" = "Nemôžeme aktivovať váš účet kým neoveríte kód, ktorý sme vám poslali.";
/* Indicates a delay of zero seconds, and that 'screen lock activity' will timeout immediately. */
"SCREEN_LOCK_ACTIVITY_TIMEOUT_NONE" = "Instant";
"SCREEN_LOCK_ACTIVITY_TIMEOUT_NONE" = "Okamžite";
/* Title for alert indicating that screen lock could not be unlocked. */
"SCREEN_LOCK_UNLOCK_FAILED" = "Overenie zlyhalo";
/* alert title when user attempts to leave the send media flow when they have an in-progress album */
"SEND_MEDIA_ABANDON_TITLE" = "Discard Media?";
"SEND_MEDIA_ABANDON_TITLE" = "Zahodiť médiá?";
/* 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";
"SEND_MEDIA_CONFIRM_ABANDON_ALBUM" = "Zahodiť médiá";
/* alert action when the user decides not to cancel the media flow after all. */
"SEND_MEDIA_RETURN_TO_CAMERA" = "Vrátiť sa ku kamere";
/* alert action when the user decides not to cancel the media flow after all. */
@ -303,7 +303,7 @@
/* Label for switch in settings that controls whether or not backup is enabled. */
"SETTINGS_BACKUP_ENABLING_SWITCH" = "Zálohovanie povolené";
/* Label for iCloud status row in the in the backup settings view. */
"SETTINGS_BACKUP_ICLOUD_STATUS" = "iCloud Status";
"SETTINGS_BACKUP_ICLOUD_STATUS" = "Stav iCloud";
/* Indicates that the last backup restore failed. */
"SETTINGS_BACKUP_IMPORT_STATUS_FAILED" = "Backup Restore Failed";
/* Indicates that app is not restoring up. */
@ -359,33 +359,33 @@
/* Label for the 'typing indicators' setting. */
"SETTINGS_TYPING_INDICATORS" = "Indikátory písania";
/* Label for the 'no sound' option that allows users to disable sounds for notifications, etc. */
"SOUNDS_NONE" = "None";
"SOUNDS_NONE" = "Žiaden";
/* {{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";
"TIME_AMOUNT_DAYS" = "%@ d";
/* 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";
"TIME_AMOUNT_HOURS" = "%@ hodín";
/* 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";
"TIME_AMOUNT_MINUTES" = "%@ minút";
/* 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";
"TIME_AMOUNT_SECONDS" = "%@ sekúnd";
/* 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";
"TIME_AMOUNT_SINGLE_DAY" = "%@ d";
/* {{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";
"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" = "%@ minute";
"TIME_AMOUNT_SINGLE_MINUTE" = "%@ minúta";
/* {{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";
"TIME_AMOUNT_SINGLE_WEEK" = "%@ týždeň";
/* {{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";
"TIME_AMOUNT_WEEKS" = "%@ týždňov";
/* 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. */
@ -399,9 +399,9 @@
/* 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á správa";
/* Info Message when you disable disappearing messages */
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You disabled disappearing messages.";
"YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Vypli ste miznúce správy.";
/* Info message embedding a {{time amount}}, see the *_TIME_AMOUNT strings for context. */
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You set disappearing message time to %@";
"YOU_UPDATED_DISAPPEARING_MESSAGES_CONFIGURATION" = "Nastavili ste časovač miznúcich správ na %@";
// MARK: - Session
"continue_2" = "Pokračovať";
"copy" = "Kopírovať";
@ -444,7 +444,7 @@
"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" = "Uistite sa, že frázu na obnovenie máte uloženú na bezpečnom mieste";
"vc_path_title" = "Cesta";
"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_explanation" = "Session skrýva vašu IP smerovaním vašich správ cez viacero servisných uzlov v decentralizovanej Session siete. Toto sú krajiny cez ktoré je momentálne smerované vaše spojenie:";
"vc_path_device_row_title" = "Vy";
"vc_path_guard_node_row_title" = "Vstupný uzol";
"vc_path_service_node_row_title" = "Servisný uzol";
@ -479,7 +479,7 @@
"vc_settings_clear_all_data_button_title" = "Odstrániť dáta";
"vc_notification_settings_title" = "Hlásenia";
"vc_privacy_settings_title" = "Súkromie";
"preferences_notifications_strategy_category_title" = "Notification Strategy";
"preferences_notifications_strategy_category_title" = "Stratégia upozornení";
"modal_seed_title" = "Vaša fráza pre obnovenie";
"modal_seed_explanation" = "Toto je vaša fráza pre obnovenie. S jej pomocou môžete obnoviť alebo presunúť svoje Session ID na nové zariadenie.";
"modal_clear_all_data_title" = "Odstrániť všetky dáta";
@ -490,7 +490,7 @@
"vc_qr_code_view_scan_qr_code_explanation" = "Oskenujte niečí QR kód a začnite konverzáciu s danou osobou";
"vc_view_my_qr_code_explanation" = "Toto je váš QR kód. Ostatní používatelia ho môžu oskenovať a začať tak stretnutie s vami.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode_explanation" = "Budete upozornený/á na nové správy spoľahlivo a okamžite použitím serverov Apple.";
"slow_mode_explanation" = "Session občas na pozadí skontroluje nové správy.";
"vc_pn_mode_title" = "Upozornenia na správy";
"vc_notification_settings_notification_mode_title" = "Použiť rýchly režim";
@ -500,7 +500,7 @@
"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";
"vc_home_title" = "Správy";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"admin_group_leave_warning" = "Pretože tvorcom skupiny ste vy, skupina bude vymazaná pre každého. Táto akcia sa nedá vrátiť.";
"vc_join_open_group_suggestions_title" = "Alebo sa pripojte k jednej z týchto...";
"vc_settings_invite_a_friend_button_title" = "Pozvať priateľa";
"vc_settings_help_us_translate_button_title" = "Pomôžte nám preložiť Session";
@ -520,3 +520,6 @@
"modal_link_previews_title" = "Povoliť náhľad odkazov?";
"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" = "Povoliť";
"vc_share_title" = "Share to Session";
"vc_share_loading_message" = "Preparing attachments...";
"vc_share_sending_message" = "Sending...";

View File

@ -192,12 +192,6 @@
"GROUP_YOU_LEFT" = "You have left the group.";
/* No comment provided by engineer. */
"YOU_WERE_REMOVED" = " You were removed from 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. */
"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 */
@ -469,7 +463,6 @@
"vc_create_closed_group_empty_state_button_title" = "Bắt đầu Session";
"vc_create_closed_group_group_name_missing_error" = "Vui lòng nhập tên nhóm";
"vc_create_closed_group_group_name_too_long_error" = "Vui lòng nhập một tên nhóm ngắn hơn ";
"vc_create_closed_group_not_enough_group_members_error" = "Vui lòng chọn ít nhất 2 thành viên trong nhóm ";
"vc_create_closed_group_too_many_group_members_error" = "Một nhóm kín không thể có nhiều hơn 100 thành viên ";
"vc_join_public_chat_title" = "Tham gia nhóm mở";
"vc_join_public_chat_enter_group_url_tab_title" = "URL của nhóm mở";
@ -496,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "Quét mã QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Quét mã QR của ai đó để bắt đầu trò chuyện với họ";
"vc_view_my_qr_code_explanation" = "Đây là mã QR của bạn. Những người dùng khác có thể quét mã này và bắt đầu session với bạn.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -489,3 +489,37 @@
"vc_qr_code_view_scan_qr_code_tab_title" = "扫描二维码";
"vc_qr_code_view_scan_qr_code_explanation" = "扫描对方的二维码以发起对话";
"vc_view_my_qr_code_explanation" = "这是您的二维码。其他用户可以对其进行扫描以发起与您的对话。";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"vc_pn_mode_title" = "Message Notifications";
"vc_notification_settings_notification_mode_title" = "Use Fast Mode";
"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";
"vc_home_title" = "Messages";
"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";
"vc_settings_help_us_translate_button_title" = "Help us Translate Session";
"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_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...";

View File

@ -10,7 +10,7 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
// MARK: Components
private lazy var tabBar: TabBar = {
let tabs = [
TabBar.Tab(title: "Recovery Phrase") { [weak self] in
TabBar.Tab(title: NSLocalizedString("vc_link_device_recovery_phrase_tab_title", comment: "")) { [weak self] in
guard let self = self else { return }
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
},
@ -35,7 +35,7 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
}()
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
let message = "Navigate to Settings → Recovery Phrase on your other device to show your QR code."
let message = NSLocalizedString("vc_link_device_scan_qr_code_explanation", comment: "")
let result = ScanQRCodeWrapperVC(message: message)
result.delegate = self
return result
@ -163,14 +163,14 @@ private final class RecoveryPhraseVC : UIViewController {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
titleLabel.text = "Recovery Phrase"
titleLabel.text = NSLocalizedString("vc_enter_recovery_phrase_title", comment: "")
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Explanation label
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = "To link your device, enter the recovery phrase that was given to you when you signed up."
explanationLabel.text = NSLocalizedString("vc_enter_recovery_phrase_explanation", comment: "")
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Spacers

View File

@ -12,14 +12,14 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
// MARK: Components
private lazy var apnsOptionView: OptionView = {
let explanation = "Youll be notified of new messages reliably and immediately using Apples notification servers."
let explanation = NSLocalizedString("fast_mode_explanation", comment: "")
let result = OptionView(title: "Fast Mode", explanation: explanation, delegate: self, isRecommended: true)
result.accessibilityLabel = "Fast mode option"
return result
}()
private lazy var backgroundPollingOptionView: OptionView = {
let explanation = "Session will occasionally check for new messages in the background."
let explanation = NSLocalizedString("slow_mode_explanation", comment: "")
let result = OptionView(title: "Slow Mode", explanation: explanation, delegate: self)
result.accessibilityLabel = "Slow mode option"
return result
@ -38,7 +38,7 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
titleLabel.text = "Message Notifications"
titleLabel.text = NSLocalizedString("vc_pn_mode_title", comment: "")
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Set up spacers

View File

@ -177,7 +177,7 @@ final class RegisterVC : BaseVC {
UIPasteboard.general.string = x25519KeyPair.hexEncodedPublicKey
copyPublicKeyButton.isUserInteractionEnabled = false
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyPublicKeyButton.setTitle("Copied", for: UIControl.State.normal)
self.copyPublicKeyButton.setTitle(NSLocalizedString("copied", comment: ""), for: UIControl.State.normal)
}, completion: nil)
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
}

View File

@ -177,7 +177,7 @@ final class SeedVC : BaseVC {
UIPasteboard.general.string = mnemonic
copyButton.isUserInteractionEnabled = false
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
self.copyButton.setTitle(NSLocalizedString("copied", comment: ""), for: UIControl.State.normal)
}, completion: nil)
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
}

View File

@ -193,7 +193,7 @@ private final class EnterURLVC : UIViewController, UIGestureRecognizerDelegate,
let suggestionGridTitleLabel = UILabel()
suggestionGridTitleLabel.textColor = Colors.text
suggestionGridTitleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize)
suggestionGridTitleLabel.text = "Or join one of these..."
suggestionGridTitleLabel.text = NSLocalizedString("vc_join_open_group_suggestions_title", comment: "")
suggestionGridTitleLabel.numberOfLines = 0
suggestionGridTitleLabel.lineBreakMode = .byWordWrapping
// Next button

View File

@ -44,7 +44,7 @@
OWSTableSection *strategySection = [OWSTableSection new];
strategySection.headerTitle = NSLocalizedString(@"preferences_notifications_strategy_category_title", @"");
[strategySection addItem:[OWSTableItem switchItemWithText:@"Use Fast Mode"
[strategySection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"vc_notification_settings_notification_mode_title", @"")
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"push_notification_strategy")
isOnBlock:^{
return [NSUserDefaults.standardUserDefaults boolForKey:@"isUsingFullAPNs"];

View File

@ -139,13 +139,13 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
versionLabel.text = "Version \(version) (\(buildNumber))"
// Invite button
let inviteButton = UIButton()
inviteButton.setTitle("Invite a Friend", for: UIControl.State.normal)
inviteButton.setTitle(NSLocalizedString("vc_settings_invite_a_friend_button_title", comment: ""), for: UIControl.State.normal)
inviteButton.setTitleColor(Colors.text, for: UIControl.State.normal)
inviteButton.titleLabel!.font = .boldSystemFont(ofSize: Values.smallFontSize)
inviteButton.addTarget(self, action: #selector(sendInvitation), for: UIControl.Event.touchUpInside)
// Help translate button
let helpTranslateButton = UIButton()
helpTranslateButton.setTitle("Help us Translate Session", for: UIControl.State.normal)
helpTranslateButton.setTitle(NSLocalizedString("vc_settings_help_us_translate_button_title", comment: ""), for: UIControl.State.normal)
helpTranslateButton.setTitleColor(Colors.text, for: UIControl.State.normal)
helpTranslateButton.titleLabel!.font = .boldSystemFont(ofSize: Values.smallFontSize)
helpTranslateButton.addTarget(self, action: #selector(helpTranslate), for: UIControl.Event.touchUpInside)
@ -418,7 +418,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
UIPasteboard.general.string = getUserHexEncodedPublicKey()
copyButton.isUserInteractionEnabled = false
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
self.copyButton.setTitle(NSLocalizedString("copied", comment: ""), for: UIControl.State.normal)
}, completion: nil)
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
}

View File

@ -82,7 +82,7 @@ public final class AttachmentUploadJob : NSObject, Job, NSCoding { // NSObject/N
if encrypt {
var encryptionKey = NSData()
var digest = NSData()
guard let ciphertext = Cryptography.encryptAttachmentData(data, shouldPad: false, outKey: &encryptionKey, outDigest: &digest) else {
guard let ciphertext = Cryptography.encryptAttachmentData(data, shouldPad: true, outKey: &encryptionKey, outDigest: &digest) else {
SNLog("Couldn't encrypt attachment.")
onFailure?(Error.encryptionFailed); return
}

View File

@ -1,28 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Share View Controller-->
<!--ShareVC-->
<scene sceneID="ceB-am-kn3">
<objects>
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModule="SignalShareExtension" customModuleProvider="target" sceneMemberID="viewController">
<viewController id="j1y-V4-xli" customClass="ShareVC" customModule="SessionShareExtension" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SessionGreen64" translatesAutoresizingMaskIntoConstraints="NO" id="Hvu-b1-e3Q">
<rect key="frame" x="155.5" y="301.5" width="64" height="64"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="bwQ-vq-ZId"/>
<constraint firstAttribute="height" constant="64" id="vrS-W4-ZXG"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
<color key="backgroundColor" red="0.086274509803921567" green="0.086274509803921567" blue="0.086274509803921567" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Hvu-b1-e3Q" firstAttribute="centerY" secondItem="wbc-yd-nQP" secondAttribute="centerY" id="0no-Qo-O3k"/>
<constraint firstItem="Hvu-b1-e3Q" firstAttribute="centerX" secondItem="wbc-yd-nQP" secondAttribute="centerX" id="Vsx-JI-9HN"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="126" y="133"/>
</scene>
</scenes>
<resources>
<image name="SessionGreen64" width="57.5" height="64"/>
</resources>
</document>

View File

@ -1,96 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import UIKit
import PureLayout
// All Observer methods will be invoked from the main thread.
protocol SAEFailedViewDelegate: class {
func shareViewWasCancelled()
}
class SAEFailedViewController: UIViewController {
weak var delegate: SAEFailedViewDelegate?
let failureTitle: String
let failureMessage: String
// MARK: Initializers and Factory Methods
init(delegate: SAEFailedViewDelegate, title: String, message: String) {
self.delegate = delegate
self.failureTitle = title
self.failureMessage = message
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable, message:"use other constructor instead.")
required init?(coder aDecoder: NSCoder) {
notImplemented()
}
override func loadView() {
super.loadView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(cancelPressed))
self.navigationItem.title = "Session"
self.view.backgroundColor = UIColor.ows_signalBrandBlue
let logoImage = UIImage(named: "logoSignal")
let logoImageView = UIImageView(image: logoImage)
self.view.addSubview(logoImageView)
logoImageView.autoCenterInSuperview()
let logoSize = CGFloat(120)
logoImageView.autoSetDimension(.width, toSize: logoSize)
logoImageView.autoSetDimension(.height, toSize: logoSize)
let titleLabel = UILabel()
titleLabel.textColor = UIColor.white
titleLabel.font = UIFont.ows_mediumFont(withSize: 18)
titleLabel.text = failureTitle
titleLabel.textAlignment = .center
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
self.view.addSubview(titleLabel)
titleLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: 20)
titleLabel.autoPinEdge(toSuperviewEdge: .trailing, withInset: 20)
titleLabel.autoPinEdge(.top, to: .bottom, of: logoImageView, withOffset: 25)
let messageLabel = UILabel()
messageLabel.textColor = UIColor.white
messageLabel.font = UIFont.ows_regularFont(withSize: 14)
messageLabel.text = failureMessage
messageLabel.textAlignment = .center
messageLabel.numberOfLines = 0
messageLabel.lineBreakMode = .byWordWrapping
self.view.addSubview(messageLabel)
messageLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: 20)
messageLabel.autoPinEdge(toSuperviewEdge: .trailing, withInset: 20)
messageLabel.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: 10)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
// MARK: - Event Handlers
@objc func cancelPressed(sender: UIButton) {
guard let delegate = delegate else {
owsFailDebug("missing delegate")
return
}
delegate.shareViewWasCancelled()
}
}

View File

@ -1,110 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
import PureLayout
class SAELoadViewController: UIViewController {
weak var delegate: ShareViewDelegate?
var activityIndicator: UIActivityIndicatorView!
var progressView: UIProgressView!
var progress: Progress? {
didSet {
guard progressView != nil else {
return
}
updateProgressViewVisability()
progressView.observedProgress = progress
}
}
func updateProgressViewVisability() {
guard progressView != nil, activityIndicator != nil else {
return
}
// Prefer to show progress view when progress is present
if self.progress == nil {
activityIndicator.startAnimating()
self.progressView.isHidden = true
self.activityIndicator.isHidden = false
} else {
activityIndicator.stopAnimating()
self.progressView.isHidden = false
self.activityIndicator.isHidden = true
}
}
// MARK: Initializers and Factory Methods
init(delegate: ShareViewDelegate) {
self.delegate = delegate
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable, message:"use other constructor instead.")
required init?(coder aDecoder: NSCoder) {
notImplemented()
}
override func loadView() {
super.loadView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(cancelPressed))
self.navigationItem.title = "Session"
self.view.backgroundColor = UIColor.ows_signalBrandBlue
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
self.activityIndicator = activityIndicator
self.view.addSubview(activityIndicator)
activityIndicator.autoCenterInSuperview()
progressView = UIProgressView(progressViewStyle: .default)
progressView.observedProgress = progress
self.view.addSubview(progressView)
progressView.autoVCenterInSuperview()
progressView.autoPinWidthToSuperview(withMargin: ScaleFromIPhone5(30))
progressView.progressTintColor = UIColor.white
updateProgressViewVisability()
let label = UILabel()
label.textColor = UIColor.white
label.font = UIFont.ows_mediumFont(withSize: 18)
label.text = NSLocalizedString("SHARE_EXTENSION_LOADING",
comment: "Indicates that the share extension is still loading.")
self.view.addSubview(label)
label.autoHCenterInSuperview()
label.autoPinEdge(.top, to: .bottom, of: activityIndicator, withOffset: 25)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
// MARK: - Event Handlers
@objc func cancelPressed(sender: UIButton) {
guard let delegate = delegate else {
owsFailDebug("missing delegate")
return
}
delegate.shareViewWasCancelled()
}
}

View File

@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
UIView.appearance.tintColor = LKColors.text;
// Loki: Set gradient background
// Gradient background
self.view.backgroundColor = UIColor.clearColor;
CAGradientLayer *layer = [CAGradientLayer new];
layer.frame = UIScreen.mainScreen.bounds;
@ -52,20 +52,21 @@ NS_ASSUME_NONNULL_BEGIN
layer.colors = @[ (id)gradientStartColor.CGColor, (id)gradientEndColor.CGColor ];
[self.view.layer insertSublayer:layer atIndex:0];
// Loki: Set navigation bar background color
// Navigation bar background color
UINavigationBar *navigationBar = self.navigationController.navigationBar;
[navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
navigationBar.shadowImage = [UIImage new];
[navigationBar setTranslucent:NO];
navigationBar.barTintColor = LKColors.navigationBarBackground;
// Loki: Customize title
// Title
UILabel *titleLabel = [UILabel new];
titleLabel.text = NSLocalizedString(@"Share to Session", @"");
titleLabel.text = NSLocalizedString(@"vc_share_title", @"");
titleLabel.textColor = LKColors.text;
titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
self.navigationItem.titleView = titleLabel;
// Close button
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"X"] style:UIBarButtonItemStylePlain target:self action:@selector(dismissPressed:)];
closeButton.tintColor = LKColors.text;
self.navigationItem.leftBarButtonItem = closeButton;

View File

@ -1,42 +1,21 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
import PureLayout
import CoreServices
import PromiseKit
import SessionUIKit
import CoreServices
@objc
public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailedViewDelegate, AppModeManagerDelegate {
// MARK: - Dependencies
private var tsAccountManager: TSAccountManager {
return TSAccountManager.sharedInstance()
}
// MARK: -
final class ShareVC : UINavigationController, ShareViewDelegate, AppModeManagerDelegate {
private var areVersionMigrationsComplete = false
public static var attachmentPrepPromise: Promise<[SignalAttachment]>?
// MARK: Error
enum ShareViewControllerError: Error {
case assertionError(description: String)
case unsupportedMedia
case notRegistered
case obsoleteShare
}
private var hasInitialRootViewController = false
private var isReadyForAppExtensions = false
private var areVersionMigrationsComplete = false
private var progressPoller: ProgressPoller?
var loadViewController: SAELoadViewController?
private var shareViewNavigationController: OWSNavigationController?
override open func loadView() {
// MARK: Lifecycle
override func loadView() {
super.loadView()
// This should be the first thing we do.
@ -56,8 +35,6 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
_ = AppVersion.sharedInstance()
startupLogging()
Cryptography.seedRandom()
// We don't need to use DeviceSleepManager in the SAE.
@ -69,18 +46,6 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
return
}
// If we haven't migrated the database file to the shared data
// directory we can't load it, and therefore can't init TSSPrimaryStorage,
// and therefore don't want to setup most of our machinery (Environment,
// most of the singletons, etc.). We just want to show an error view and
// abort.
isReadyForAppExtensions = OWSPreferences.isReadyForAppExtensions()
guard isReadyForAppExtensions else {
showNotReadyView()
return
}
// We shouldn't set up our environment until after we've consulted isReadyForAppExtensions.
AppSetup.setupEnvironment(appSpecificSingletonBlock: {
SSKEnvironment.shared.notificationsManager = NoopNotificationsManager()
}, migrationCompletion: { [weak self] in
@ -93,120 +58,16 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
strongSelf.versionMigrationsDidComplete()
})
let shareViewNavigationController = OWSNavigationController()
self.shareViewNavigationController = shareViewNavigationController
let loadViewController = SAELoadViewController(delegate: self)
self.loadViewController = loadViewController
// Don't display load screen immediately, in hopes that we can avoid it altogether.
after(seconds: 0.5).done { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
guard strongSelf.presentedViewController == nil else {
Logger.debug("setup completed quickly, no need to present load view controller.")
return
}
Logger.debug("setup is slow - showing loading screen")
strongSelf.showPrimaryViewController(loadViewController)
}.retainUntilComplete()
// We don't need to use "screen protection" in the SAE.
NotificationCenter.default.addObserver(self,
selector: #selector(storageIsReady),
name: .StorageIsReady,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(registrationStateDidChange),
name: .RegistrationStateDidChange,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(owsApplicationWillEnterForeground),
name: .OWSApplicationWillEnterForeground,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(applicationDidEnterBackground),
name: .OWSApplicationDidEnterBackground,
object: nil)
Logger.info("completed.")
}
deinit {
Logger.info("deinit")
NotificationCenter.default.removeObserver(self)
// Share extensions reside in a process that may be reused between usages.
// That isn't safe; the codebase is full of statics (e.g. singletons) which
// we can't easily clean up.
ExitShareExtension()
}
@objc
public func applicationDidEnterBackground() {
AssertIsOnMainThread()
Logger.info("")
if OWSScreenLock.shared.isScreenLockEnabled() {
Logger.info("dismissing.")
self.dismiss(animated: false) { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
}
private func activate() {
AssertIsOnMainThread()
Logger.debug("")
// We don't need to use "screen protection" in the SAE.
ensureRootViewController()
// We don't need to use RTCInitializeSSL() in the SAE.
if tsAccountManager.isRegistered() {
// At this point, potentially lengthy DB locking migrations could be running.
// Avoid blocking app launch by putting all further possible DB access in async block
DispatchQueue.global().async { [weak self] in
guard let _ = self else { return }
Logger.info("running post launch block for registered user: \(TSAccountManager.localNumber()!)")
// We don't need to use OWSDisappearingMessagesJob in the SAE.
// We don't need to use OWSFailedMessagesJob in the SAE.
// We don't need to use OWSFailedAttachmentDownloadsJob in the SAE.
}
} else {
Logger.info("running post launch block for unregistered user.")
// We don't need to update the app icon badge number in the SAE.
// We don't need to prod the TSSocketManager in the SAE.
}
if tsAccountManager.isRegistered() {
DispatchQueue.main.async { [weak self] in
guard let _ = self else { return }
Logger.info("running post launch block for registered user: \(TSAccountManager.localNumber()!)")
// We don't need to use the TSSocketManager in the SAE.
// We don't need to fetch messages in the SAE.
// We don't need to use OWSSyncPushTokensJob in the SAE.
}
}
}
@objc
@ -256,19 +117,15 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
// it will also run all deferred blocks.
AppReadiness.setAppIsReady()
if tsAccountManager.isRegistered() {
Logger.info("localNumber: \(TSAccountManager.localNumber()!)")
// We don't need to use messageFetcherJob in the SAE.
// We don't need to use messageFetcherJob in the SAE.
// We don't need to use SyncPushTokensJob in the SAE.
}
// We don't need to use SyncPushTokensJob in the SAE.
// We don't need to use DeviceSleepManager in the SAE.
AppVersion.sharedInstance().saeLaunchDidComplete()
ensureRootViewController()
showLockScreenOrMainContent()
// We don't need to use OWSMessageReceiver in the SAE.
// We don't need to use OWSBatchMessageProcessor in the SAE.
@ -281,164 +138,34 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
OWSReadReceiptManager.shared().prepareCachedValues()
}
override func viewDidLoad() {
super.viewDidLoad()
AppReadiness.runNowOrWhenAppDidBecomeReady { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.showLockScreenOrMainContent()
}
}
@objc
func registrationStateDidChange() {
public func applicationDidEnterBackground() {
AssertIsOnMainThread()
Logger.debug("")
if tsAccountManager.isRegistered() {
Logger.info("localNumber: \(TSAccountManager.localNumber()!)")
// We don't need to use ExperienceUpgradeFinder in the SAE.
// We don't need to use OWSDisappearingMessagesJob in the SAE.
OWSProfileManager.shared().ensureLocalProfileCached()
}
}
private func ensureRootViewController() {
AssertIsOnMainThread()
Logger.debug("")
guard AppReadiness.isAppReady() else {
return
}
guard !hasInitialRootViewController else {
return
}
hasInitialRootViewController = true
Logger.info("Presenting initial root view controller")
Logger.info("")
if OWSScreenLock.shared.isScreenLockEnabled() {
presentScreenLock()
} else {
presentContentView()
}
}
private func presentContentView() {
AssertIsOnMainThread()
Logger.debug("")
Logger.info("Presenting content view")
if !tsAccountManager.isRegistered() {
showNotRegisteredView()
} else if !OWSProfileManager.shared().localProfileExists() {
// This is a rare edge case, but we want to ensure that the user
// is has already saved their local profile key in the main app.
showNotReadyView()
} else {
DispatchQueue.main.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.buildAttachmentsAndPresentConversationPicker()
}
}
// We don't use the AppUpdateNag in the SAE.
}
func startupLogging() {
Logger.info("iOS Version: \(UIDevice.current.systemVersion)}")
let locale = NSLocale.current as NSLocale
if let localeIdentifier = locale.object(forKey: NSLocale.Key.identifier) as? String,
localeIdentifier.count > 0 {
Logger.info("Locale Identifier: \(localeIdentifier)")
} else {
owsFailDebug("Locale Identifier: Unknown")
}
if let countryCode = locale.object(forKey: NSLocale.Key.countryCode) as? String,
countryCode.count > 0 {
Logger.info("Country Code: \(countryCode)")
} else {
owsFailDebug("Country Code: Unknown")
}
if let languageCode = locale.object(forKey: NSLocale.Key.languageCode) as? String,
languageCode.count > 0 {
Logger.info("Language Code: \(languageCode)")
} else {
owsFailDebug("Language Code: Unknown")
}
}
// MARK: Error Views
private func showNotReadyView() {
AssertIsOnMainThread()
let failureTitle = NSLocalizedString("SHARE_EXTENSION_NOT_YET_MIGRATED_TITLE",
comment: "Title indicating that the share extension cannot be used until the main app has been launched at least once.")
let failureMessage = NSLocalizedString("SHARE_EXTENSION_NOT_YET_MIGRATED_MESSAGE",
comment: "Message indicating that the share extension cannot be used until the main app has been launched at least once.")
showErrorView(title: failureTitle, message: failureMessage)
}
private func showNotRegisteredView() {
AssertIsOnMainThread()
let failureTitle = NSLocalizedString("SHARE_EXTENSION_NOT_REGISTERED_TITLE",
comment: "Title indicating that the share extension cannot be used until the user has registered in the main app.")
let failureMessage = NSLocalizedString("SHARE_EXTENSION_NOT_REGISTERED_MESSAGE",
comment: "Message indicating that the share extension cannot be used until the user has registered in the main app.")
showErrorView(title: failureTitle, message: failureMessage)
}
private func showErrorView(title: String, message: String) {
AssertIsOnMainThread()
let viewController = SAEFailedViewController(delegate: self, title: title, message: message)
self.showPrimaryViewController(viewController)
}
// MARK: View Lifecycle
override open func viewDidLoad() {
super.viewDidLoad()
Logger.debug("")
if isReadyForAppExtensions {
AppReadiness.runNowOrWhenAppDidBecomeReady { [weak self] in
self.dismiss(animated: false) { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.activate()
strongSelf.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
}
override open func viewWillAppear(_ animated: Bool) {
Logger.debug("")
super.viewWillAppear(animated)
}
override open func viewDidAppear(_ animated: Bool) {
Logger.debug("")
super.viewDidAppear(animated)
}
override open func viewWillDisappear(_ animated: Bool) {
Logger.debug("")
super.viewWillDisappear(animated)
Logger.flush()
}
override open func viewDidDisappear(_ animated: Bool) {
Logger.debug("")
super.viewDidDisappear(animated)
Logger.flush()
deinit {
NotificationCenter.default.removeObserver(self)
// Share extensions reside in a process that may be reused between usages.
// That isn't safe; the codebase is full of statics (e.g. singletons) which
@ -446,136 +173,68 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
ExitShareExtension()
}
@objc
func owsApplicationWillEnterForeground() throws {
AssertIsOnMainThread()
Logger.debug("")
// If a user unregisters in the main app, the SAE should shut down
// immediately.
guard !tsAccountManager.isRegistered() else {
// If user is registered, do nothing.
return
}
guard let shareViewNavigationController = shareViewNavigationController else {
owsFailDebug("Missing shareViewNavigationController")
return
}
guard let firstViewController = shareViewNavigationController.viewControllers.first else {
// If no view has been presented yet, do nothing.
return
}
if let _ = firstViewController as? SAEFailedViewController {
// If root view is an error view, do nothing.
return
}
throw ShareViewControllerError.notRegistered
// MARK: App Mode
public func getCurrentAppMode() -> AppMode {
guard let window = self.view.window else { return .light }
let userInterfaceStyle = window.traitCollection.userInterfaceStyle
let isLightMode = (userInterfaceStyle == .light || userInterfaceStyle == .unspecified)
return isLightMode ? .light : .dark
}
// MARK: ShareViewDelegate, SAEFailedViewDelegate
public func shareViewWasUnlocked() {
Logger.info("")
presentContentView()
public func setCurrentAppMode(to appMode: AppMode) {
return // Not applicable to share extensions
}
public func shareViewWasCompleted() {
Logger.info("")
self.dismiss(animated: true) { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
public func shareViewWasCancelled() {
Logger.info("")
self.dismiss(animated: true) { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
public func shareViewFailed(error: Error) {
Logger.info("")
self.dismiss(animated: true) { [weak self] in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.extensionContext!.cancelRequest(withError: error)
}
}
// MARK: Helpers
// This view controller is not visible to the user. It exists to intercept touches, set up the
// extensions dependencies, and eventually present a visible view to the user.
// For speed of presentation, we only present a single modal, and if it's already been presented
// we swap out the contents.
// e.g. if loading is taking a while, the user will see the load screen presented with a modal
// animation. Next, when loading completes, the load view will be switched out for the contact
// picker view.
private func showPrimaryViewController(_ viewController: UIViewController) {
AssertIsOnMainThread()
guard let shareViewNavigationController = shareViewNavigationController else {
owsFailDebug("Missing shareViewNavigationController")
return
}
shareViewNavigationController.setViewControllers([viewController], animated: false)
if self.presentedViewController == nil {
Logger.debug("presenting modally: \(viewController)")
self.present(shareViewNavigationController, animated: true)
// MARK: Updating
private func showLockScreenOrMainContent() {
if OWSScreenLock.shared.isScreenLockEnabled() {
showLockScreen()
} else {
Logger.debug("modal already presented. swapping modal content for: \(viewController)")
assert(self.presentedViewController == shareViewNavigationController)
showMainContent()
}
}
private func buildAttachmentsAndPresentConversationPicker() {
AssertIsOnMainThread()
self.buildAttachments().map { [weak self] attachments in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
strongSelf.progressPoller = nil
strongSelf.loadViewController = nil
let conversationPicker = SharingThreadPickerViewController(shareViewDelegate: strongSelf)
Logger.debug("presentConversationPicker: \(conversationPicker)")
conversationPicker.attachments = attachments
strongSelf.showPrimaryViewController(conversationPicker)
Logger.info("showing picker with attachments: \(attachments)")
}.catch { [weak self] error in
AssertIsOnMainThread()
guard let strongSelf = self else { return }
let alertTitle = NSLocalizedString("SHARE_EXTENSION_UNABLE_TO_BUILD_ATTACHMENT_ALERT_TITLE",
comment: "Shown when trying to share content to a Signal user for the share extension. Followed by failure details.")
OWSAlerts.showAlert(title: alertTitle,
message: error.localizedDescription,
buttonTitle: CommonStrings.cancelButton) { _ in
strongSelf.shareViewWasCancelled()
private func showLockScreen() {
let screenLockVC = SAEScreenLockViewController(shareViewDelegate: self)
setViewControllers([ screenLockVC ], animated: false)
}
private func showMainContent() {
let threadPickerVC = ThreadPickerVC()
threadPickerVC.shareVC = self
setViewControllers([ threadPickerVC ], animated: false)
let promise = buildAttachments()
ModalActivityIndicatorViewController.present(fromViewController: self, canCancel: false, message: NSLocalizedString("vc_share_loading_message", comment: "")) { activityIndicator in
promise.done { _ in
activityIndicator.dismiss { }
}.catch { _ in
activityIndicator.dismiss { }
}
owsFailDebug("building attachment failed with error: \(error)")
}.retainUntilComplete()
}
ShareVC.attachmentPrepPromise = promise
}
private func presentScreenLock() {
AssertIsOnMainThread()
let screenLockUI = SAEScreenLockViewController(shareViewDelegate: self)
Logger.debug("presentScreenLock: \(screenLockUI)")
showPrimaryViewController(screenLockUI)
Logger.info("showing screen lock")
func shareViewWasUnlocked() {
showMainContent()
}
func shareViewWasCompleted() {
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
func shareViewWasCancelled() {
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
func shareViewFailed(error: Error) {
let alert = UIAlertController(title: "Session", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: { _ in
self.extensionContext!.cancelRequest(withError: error)
}))
present(alert, animated: true, completion: nil)
}
// MARK: Attachment Prep
private class func itemMatchesSpecificUtiType(itemProvider: NSItemProvider, utiType: String) -> Bool {
// URLs, contacts and other special items have to be detected separately.
// Many shares (e.g. pdfs) will register many UTI types and/or conform to kUTTypeData.
@ -708,7 +367,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
Logger.error("invalid inputItem \(inputItemRaw)")
continue
}
if let itemProviders = ShareViewController.preferredItemProviders(inputItem: inputItem) {
if let itemProviders = ShareVC.preferredItemProviders(inputItem: inputItem) {
return Promise.value(itemProviders)
}
}
@ -740,7 +399,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
self.isConvertibleToContactShare = isConvertibleToContactShare
}
}
private func loadItemProvider(itemProvider: NSItemProvider) -> Promise<LoadedItem> {
Logger.info("attachment: \(itemProvider)")
@ -753,7 +412,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
// * UTIs aren't very descriptive (there are far more MIME types than UTI types)
// so in the case of file attachments we try to refine the attachment type
// using the file extension.
guard let srcUtiType = ShareViewController.utiType(itemProvider: itemProvider) else {
guard let srcUtiType = ShareVC.utiType(itemProvider: itemProvider) else {
let error = ShareViewControllerError.unsupportedMedia
return Promise(error: error)
}
@ -862,7 +521,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
return promise
}
private func buildAttachment(forLoadedItem loadedItem: LoadedItem) -> Promise<SignalAttachment> {
let itemProvider = loadedItem.itemProvider
let itemUrl = loadedItem.itemUrl
@ -880,7 +539,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
Logger.debug("building DataSource with url: \(url), utiType: \(utiType)")
guard let dataSource = ShareViewController.createDataSource(utiType: utiType, url: url, customFileName: loadedItem.customFileName) else {
guard let dataSource = ShareVC.createDataSource(utiType: utiType, url: url, customFileName: loadedItem.customFileName) else {
let error = ShareViewControllerError.assertionError(description: "Unable to read attachment data")
return Promise(error: error)
}
@ -901,27 +560,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
guard !SignalAttachment.isInvalidVideo(dataSource: dataSource, dataUTI: specificUTIType) else {
// This can happen, e.g. when sharing a quicktime-video from iCloud drive.
let (promise, exportSession) = SignalAttachment.compressVideoAsMp4(dataSource: dataSource, dataUTI: specificUTIType)
// TODO: How can we move waiting for this export to the end of the share flow rather than having to do it up front?
// Ideally we'd be able to start it here, and not block the UI on conversion unless there's still work to be done
// when the user hits "send".
if let exportSession = exportSession {
let progressPoller = ProgressPoller(timeInterval: 0.1, ratioCompleteBlock: { return exportSession.progress })
self.progressPoller = progressPoller
progressPoller.startPolling()
guard let loadViewController = self.loadViewController else {
owsFailDebug("load view controller was unexpectedly nil")
return promise
}
DispatchQueue.main.async {
loadViewController.progress = progressPoller.progress
}
}
let (promise, _) = SignalAttachment.compressVideoAsMp4(dataSource: dataSource, dataUTI: specificUTIType)
return promise
}
@ -1004,60 +643,4 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed
// apply any conversion, so no need to relocate the app.
return !itemProvider.registeredTypeIdentifiers.contains(kUTTypeMPEG4 as String)
}
// MARK: App Mode
public func getCurrentAppMode() -> AppMode {
guard let window = self.view.window else { return .light }
let userInterfaceStyle = window.traitCollection.userInterfaceStyle
let isLightMode = (userInterfaceStyle == .light || userInterfaceStyle == .unspecified)
return isLightMode ? .light : .dark
}
public func setCurrentAppMode(to appMode: AppMode) {
return // Not applicable to share extensions
}
}
// Exposes a Progress object, whose progress is updated by polling the return of a given block
private class ProgressPoller: NSObject {
let progress: Progress
private(set) var timer: Timer?
// Higher number offers higher ganularity
let progressTotalUnitCount: Int64 = 10000
private let timeInterval: Double
private let ratioCompleteBlock: () -> Float
init(timeInterval: TimeInterval, ratioCompleteBlock: @escaping () -> Float) {
self.timeInterval = timeInterval
self.ratioCompleteBlock = ratioCompleteBlock
self.progress = Progress()
progress.totalUnitCount = progressTotalUnitCount
progress.completedUnitCount = Int64(ratioCompleteBlock() * Float(progressTotalUnitCount))
}
func startPolling() {
guard self.timer == nil else {
owsFailDebug("already started timer")
return
}
self.timer = WeakTimer.scheduledTimer(timeInterval: timeInterval, target: self, userInfo: nil, repeats: true) { [weak self] (timer) in
guard let strongSelf = self else {
return
}
let completedUnitCount = Int64(strongSelf.ratioCompleteBlock() * Float(strongSelf.progressTotalUnitCount))
strongSelf.progress.completedUnitCount = completedUnitCount
if completedUnitCount == strongSelf.progressTotalUnitCount {
Logger.debug("progress complete")
timer.invalidate()
}
}
}
}

View File

@ -0,0 +1,92 @@
import UIKit
import SessionUIKit
final class SimplifiedConversationCell : UITableViewCell {
var threadViewModel: ThreadViewModel! { didSet { update() } }
static let reuseIdentifier = "SimplifiedConversationCell"
// MARK: UI Components
private lazy var accentLineView: UIView = {
let result = UIView()
result.backgroundColor = Colors.destructive
return result
}()
private lazy var profilePictureView = ProfilePictureView()
private lazy var displayNameLabel: UILabel = {
let result = UILabel()
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.textColor = Colors.text
result.lineBreakMode = .byTruncatingTail
return result
}()
// MARK: Initialization
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpViewHierarchy()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpViewHierarchy()
}
private func setUpViewHierarchy() {
// Background color
backgroundColor = Colors.cellBackground
// Highlight color
let selectedBackgroundView = UIView()
selectedBackgroundView.backgroundColor = Colors.cellSelected
self.selectedBackgroundView = selectedBackgroundView
// Accent line view
accentLineView.set(.width, to: Values.accentLineThickness)
accentLineView.set(.height, to: 68)
// Profile picture view
let profilePictureViewSize = Values.mediumProfilePictureSize
profilePictureView.set(.width, to: profilePictureViewSize)
profilePictureView.set(.height, to: profilePictureViewSize)
profilePictureView.size = profilePictureViewSize
// Main stack view
let stackView = UIStackView(arrangedSubviews: [ accentLineView, profilePictureView, displayNameLabel, UIView.hSpacer(0) ])
stackView.axis = .horizontal
stackView.alignment = .center
stackView.spacing = Values.mediumSpacing
addSubview(stackView)
stackView.pin(to: self)
}
// MARK: Updating
private func update() {
AssertIsOnMainThread()
guard let thread = threadViewModel?.threadRecord else { return }
let isBlocked: Bool
if let thread = thread as? TSContactThread {
isBlocked = SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(thread.contactSessionID())
} else {
isBlocked = false
}
accentLineView.alpha = isBlocked ? 1 : 0
profilePictureView.update(for: thread)
displayNameLabel.text = getDisplayName()
}
private func getDisplayName() -> String {
if threadViewModel.isGroupThread {
if threadViewModel.name.isEmpty {
return "Unknown Group"
} else {
return threadViewModel.name
}
} else {
if threadViewModel.threadRecord.isNoteToSelf() {
return NSLocalizedString("NOTE_TO_SELF", comment: "")
} else {
let hexEncodedPublicKey = threadViewModel.contactSessionID!
return Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey
}
}
}
}

View File

@ -0,0 +1,157 @@
import SessionUIKit
final class ThreadPickerVC : UIViewController, UITableViewDataSource, UITableViewDelegate, AttachmentApprovalViewControllerDelegate {
private var threads: YapDatabaseViewMappings!
private var threadViewModelCache: [String:ThreadViewModel] = [:] // Thread ID to ThreadViewModel
private var selectedThread: TSThread?
var shareVC: ShareVC?
private var threadCount: UInt {
threads.numberOfItems(inGroup: TSInboxGroup)
}
private lazy var dbConnection: YapDatabaseConnection = {
let result = OWSPrimaryStorage.shared().newDatabaseConnection()
result.objectCacheLimit = 500
return result
}()
private lazy var tableView: UITableView = {
let result = UITableView()
result.backgroundColor = .clear
result.separatorStyle = .none
result.register(SimplifiedConversationCell.self, forCellReuseIdentifier: SimplifiedConversationCell.reuseIdentifier)
result.showsVerticalScrollIndicator = false
return result
}()
private lazy var fadeView: UIView = {
let result = UIView()
let gradient = Gradients.homeVCFade
result.setGradient(gradient)
result.isUserInteractionEnabled = false
return result
}()
// MARK: Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// Gradient
view.backgroundColor = .clear
let gradient = Gradients.defaultBackground
view.setGradient(gradient)
// Threads
dbConnection.beginLongLivedReadTransaction() // Freeze the connection for use on the main thread (this gives us a stable data source that doesn't change until we tell it to)
threads = YapDatabaseViewMappings(groups: [ TSInboxGroup ], view: TSThreadDatabaseViewExtensionName) // The extension should be registered at this point
threads.setIsReversed(true, forGroup: TSInboxGroup)
dbConnection.read { transaction in
self.threads.update(with: transaction) // Perform the initial update
}
// Title
let titleLabel = UILabel()
titleLabel.text = NSLocalizedString("vc_share_title", comment: "")
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
navigationItem.titleView = titleLabel
// Table view
tableView.dataSource = self
tableView.delegate = self
view.addSubview(tableView)
tableView.pin(to: view)
view.addSubview(fadeView)
fadeView.pin(.leading, to: .leading, of: view)
let topInset = 0.15 * view.height()
fadeView.pin(.top, to: .top, of: view, withInset: topInset)
fadeView.pin(.trailing, to: .trailing, of: view)
fadeView.pin(.bottom, to: .bottom, of: view)
// Reload
reload()
}
// MARK: Table View Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Int(threadCount)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: SimplifiedConversationCell.reuseIdentifier) as! SimplifiedConversationCell
cell.threadViewModel = threadViewModel(at: indexPath.row)
return cell
}
// MARK: Updating
private func reload() {
AssertIsOnMainThread()
dbConnection.beginLongLivedReadTransaction() // Jump to the latest commit
dbConnection.read { transaction in
self.threads.update(with: transaction)
}
threadViewModelCache.removeAll()
tableView.reloadData()
}
// MARK: Interaction
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let thread = self.thread(at: indexPath.row), let attachments = ShareVC.attachmentPrepPromise?.value else { return }
self.selectedThread = thread
tableView.deselectRow(at: indexPath, animated: true)
let approvalVC = AttachmentApprovalViewController.wrappedInNavController(attachments: attachments, approvalDelegate: self)
navigationController!.present(approvalVC, animated: true, completion: nil)
}
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didApproveAttachments attachments: [SignalAttachment], messageText: String?) {
let message = VisibleMessage()
message.sentTimestamp = NSDate.millisecondTimestamp()
message.text = messageText
let tsMessage = TSOutgoingMessage.from(message, associatedWith: selectedThread!)
Storage.write { transaction in
tsMessage.save(with: transaction)
}
shareVC!.dismiss(animated: true, completion: nil)
ModalActivityIndicatorViewController.present(fromViewController: shareVC!, canCancel: false, message: NSLocalizedString("vc_share_sending_message", comment: "")) { activityIndicator in
Storage.write { transaction in
MessageSender.sendNonDurably(message, with: attachments, in: self.selectedThread!, using: transaction).done { [weak self] _ in
guard let self = self else { return }
activityIndicator.dismiss { }
self.shareVC!.shareViewWasCompleted()
}.catch { [weak self] error in
guard let self = self else { return }
activityIndicator.dismiss { }
self.shareVC!.shareViewFailed(error: error)
}
}
}
}
func attachmentApprovalDidCancel(_ attachmentApproval: AttachmentApprovalViewController) {
// Do nothing
}
func attachmentApproval(_ attachmentApproval: AttachmentApprovalViewController, didChangeMessageText newMessageText: String?) {
// Do nothing
}
// MARK: Convenience
private func thread(at index: Int) -> TSThread? {
var thread: TSThread? = nil
dbConnection.read { transaction in
let ext = transaction.ext(TSThreadDatabaseViewExtensionName) as! YapDatabaseViewTransaction
thread = ext.object(atRow: UInt(index), inSection: 0, with: self.threads) as! TSThread?
}
return thread
}
private func threadViewModel(at index: Int) -> ThreadViewModel? {
guard let thread = thread(at: index) else { return nil }
if let cachedThreadViewModel = threadViewModelCache[thread.uniqueId!] {
return cachedThreadViewModel
} else {
var threadViewModel: ThreadViewModel? = nil
dbConnection.read { transaction in
threadViewModel = ThreadViewModel(thread: thread, transaction: transaction)
}
threadViewModelCache[thread.uniqueId!] = threadViewModel
return threadViewModel
}
}
}

View File

@ -54,7 +54,6 @@ public class ModalActivityIndicatorViewController: OWSViewController {
fromViewController.present(view, animated: false) {
DispatchQueue.global().async {
backgroundBlock(view)
}
}
}