Merge remote-tracking branch 'origin/hotfix/2.11.3'

This commit is contained in:
Matthew Chen 2017-05-08 16:47:20 -04:00
commit ad3a1a671a
10 changed files with 210 additions and 179 deletions

View File

@ -107,6 +107,8 @@
453D28BA1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; };
453D28BB1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; };
4542F0941EB9372700C7EE92 /* SystemContactsFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542F0931EB9372700C7EE92 /* SystemContactsFetcher.swift */; };
4542F0961EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */; };
4542F0971EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */; };
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
45666EC61D99483D008FE134 /* OWSAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC51D99483D008FE134 /* OWSAvatarBuilder.m */; };
45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC81D994C0D008FE134 /* OWSGroupAvatarBuilder.m */; };
@ -450,8 +452,8 @@
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = "<group>"; };
34B3F86F1E8DF1700035BE1A /* SignalsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsViewController.h; sourceTree = "<group>"; };
34B3F8701E8DF1700035BE1A /* SignalsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsViewController.m; sourceTree = "<group>"; };
34B3F8981E8DF1B90035BE1A /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapterTest.m; sourceTree = "<group>"; };
34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListViewController.h; sourceTree = "<group>"; };
34B3F8981E8DF1B90035BE1A /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapterTest.m; sourceTree = "<group>"; };
34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListViewController.m; sourceTree = "<group>"; };
34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSTableViewController.h; sourceTree = "<group>"; };
34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = "<group>"; };
@ -508,6 +510,7 @@
453D28B81D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessagesBubblesSizeCalculator.h; sourceTree = "<group>"; };
453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessagesBubblesSizeCalculator.m; sourceTree = "<group>"; };
4542F0931EB9372700C7EE92 /* SystemContactsFetcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemContactsFetcher.swift; sourceTree = "<group>"; };
4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+retainUntilComplete.swift"; sourceTree = "<group>"; };
45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; };
454B35071D08EED80026D658 /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = translations/mk.lproj/Localizable.strings; sourceTree = "<group>"; };
45666EC41D99483D008FE134 /* OWSAvatarBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAvatarBuilder.h; sourceTree = "<group>"; };
@ -1275,6 +1278,7 @@
76EB04FB18170B33006006FC /* Util.h */,
45F170D51E315310003FC1F2 /* Weak.swift */,
45F170CB1E310E22003FC1F2 /* WeakTimer.swift */,
4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */,
);
path = util;
sourceTree = "<group>";
@ -2019,6 +2023,7 @@
34B3F8791E8DF1700035BE1A /* CountryCodeViewController.m in Sources */,
4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */,
4531C9C41DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m in Sources */,
4542F0961EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */,
4516E3FF1DD2193B00DC4206 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */,
4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */,
45387B041E36D650005D00B3 /* OWS102MoveLoggingPreferenceToUserDefaults.m in Sources */,
@ -2202,6 +2207,7 @@
45FBC5D21DF8592E00E9B410 /* SignalCall.swift in Sources */,
451A13B21E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */,
45C681B81D305A580050903A /* OWSCall.m in Sources */,
4542F0971EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */,
45855F381D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */,
45DF5DF31DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */,
456AC8341E3A775E00A3C7FC /* Weak.swift in Sources */,

View File

@ -38,7 +38,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.11.2</string>
<string>2.11.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -55,7 +55,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>2.11.2.1</string>
<string>2.11.3.0</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LOGS_EMAIL</key>

View File

@ -12,8 +12,6 @@ class SyncPushTokensJob: NSObject {
let accountManager: AccountManager
let preferences: PropertyListPreferences
var uploadOnlyIfStale = true
// useful to ensure promise runs to completion
var retainCycle: SyncPushTokensJob?
required init(pushManager: PushManager, accountManager: AccountManager, preferences: PropertyListPreferences) {
self.pushManager = pushManager
@ -32,14 +30,12 @@ class SyncPushTokensJob: NSObject {
func run() -> Promise<Void> {
Logger.debug("\(TAG) Starting.")
// Make sure we don't GC until completion.
self.retainCycle = self
// Required to potentially prompt user for notifications settings
// before `requestPushTokens` will return.
self.pushManager.validateUserNotificationSettings()
return self.requestPushTokens().then { (pushToken: String, voipToken: String) in
let runPromise: Promise<Void> = self.requestPushTokens().then { (pushToken: String, voipToken: String) in
var shouldUploadTokens = !self.uploadOnlyIfStale
if self.preferences.getPushToken() != pushToken || self.preferences.getVoipToken() != voipToken {
Logger.debug("\(self.TAG) push tokens changed.")
@ -56,9 +52,10 @@ class SyncPushTokensJob: NSObject {
Logger.info("\(self.TAG) Recording tokens locally.")
return self.recordNewPushTokens(pushToken:pushToken, voipToken:voipToken)
}
}.always {
self.retainCycle = nil
}
runPromise.retainUntilComplete()
return runPromise
}
private func requestPushTokens() -> Promise<(pushToken: String, voipToken: String)> {

View File

@ -282,13 +282,6 @@ protocol CallServiceObserver: class {
callRecord.save()
call.callRecord = callRecord
guard self.peerConnectionClient == nil else {
let errorDescription = "\(TAG) peerconnection was unexpectedly already set."
Logger.error(errorDescription)
call.state = .localFailure
return Promise(error: CallError.assertionError(description: errorDescription))
}
return getIceServers().then { iceServers -> Promise<HardenedRTCSessionDescription> in
Logger.debug("\(self.TAG) got ice servers:\(iceServers)")
@ -296,11 +289,15 @@ protocol CallServiceObserver: class {
throw CallError.obsoleteCall(description:"obsolete call in \(#function)")
}
guard self.peerConnectionClient == nil else {
let errorDescription = "\(self.TAG) peerconnection was unexpectedly already set."
Logger.error(errorDescription)
throw CallError.assertionError(description: errorDescription)
}
let useTurnOnly = Environment.getCurrent().preferences.doCallsHideIPAddress()
let peerConnectionClient = PeerConnectionClient(iceServers: iceServers, delegate: self, callDirection: .outgoing, useTurnOnly: useTurnOnly)
assert(self.peerConnectionClient == nil, "Unexpected PeerConnectionClient instance")
Logger.debug("\(self.TAG) setting peerConnectionClient in \(#function)")
self.peerConnectionClient = peerConnectionClient
@ -372,9 +369,10 @@ protocol CallServiceObserver: class {
if pendingIceUpdateMessages.count > 0 {
let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessages: pendingIceUpdateMessages)
_ = messageSender.sendCallMessage(callMessage).catch { error in
let sendPromise = messageSender.sendCallMessage(callMessage).catch { error in
Logger.error("\(self.TAG) failed to send ice updates in \(#function) with error: \(error)")
}
sendPromise.retainUntilComplete()
}
guard let peerConnectionClient = self.peerConnectionClient else {
@ -383,7 +381,7 @@ protocol CallServiceObserver: class {
}
let sessionDescription = RTCSessionDescription(type: .answer, sdp: sessionDescription)
_ = peerConnectionClient.setRemoteSessionDescription(sessionDescription).then {
let setDescriptionPromise = peerConnectionClient.setRemoteSessionDescription(sessionDescription).then {
Logger.debug("\(self.TAG) successfully set remote description")
}.catch { error in
if let callError = error as? CallError {
@ -393,6 +391,7 @@ protocol CallServiceObserver: class {
self.handleFailedCall(failedCall: call, error: externalError)
}
}
setDescriptionPromise.retainUntilComplete()
}
/**
@ -428,7 +427,8 @@ protocol CallServiceObserver: class {
let busyMessage = OWSCallBusyMessage(callId: call.signalingId)
let callMessage = OWSOutgoingCallMessage(thread: thread, busyMessage: busyMessage)
_ = messageSender.sendCallMessage(callMessage)
let sendPromise = messageSender.sendCallMessage(callMessage)
sendPromise.retainUntilComplete()
handleMissedCall(call, thread: thread)
}
@ -627,7 +627,8 @@ protocol CallServiceObserver: class {
if self.sendIceUpdatesImmediately {
let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessage: iceUpdateMessage)
_ = self.messageSender.sendCallMessage(callMessage)
let sendPromise = self.messageSender.sendCallMessage(callMessage)
sendPromise.retainUntilComplete()
} else {
// For outgoing messages, we wait to send ice updates until we're sure client received our call message.
// e.g. if the client has blocked our message due to an identity change, we'd otherwise
@ -885,11 +886,12 @@ protocol CallServiceObserver: class {
// If the call hasn't started yet, we don't have a data channel to communicate the hang up. Use Signal Service Message.
let hangupMessage = OWSCallHangupMessage(callId: call.signalingId)
let callMessage = OWSOutgoingCallMessage(thread: thread, hangupMessage: hangupMessage)
_ = self.messageSender.sendCallMessage(callMessage).then {
let sendPromise = self.messageSender.sendCallMessage(callMessage).then {
Logger.debug("\(self.TAG) successfully sent hangup call message to \(thread)")
}.catch { error in
Logger.error("\(self.TAG) failed to send hangup call message to \(thread) with error: \(error)")
}
sendPromise.retainUntilComplete()
terminateCall()
}
@ -916,7 +918,9 @@ protocol CallServiceObserver: class {
return
}
peerConnectionClient.setAudioEnabled(enabled: !isMuted)
if call.state == .connected {
peerConnectionClient.setAudioEnabled(enabled: !isMuted)
}
}
/**
@ -971,7 +975,9 @@ protocol CallServiceObserver: class {
return
}
peerConnectionClient.setLocalVideoEnabled(enabled: shouldHaveLocalVideoTrack())
if call.state == .connected {
peerConnectionClient.setLocalVideoEnabled(enabled: shouldHaveLocalVideoTrack())
}
}
func handleCallKitStartVideo() {

View File

@ -29,8 +29,8 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
self.callService.handleOutgoingCall(call).then {
Logger.debug("\(self.TAG) handleOutgoingCall succeeded")
}.catch { error in
Logger.error("\(self.TAG) handleOutgoingCall failed with error: \(error)")
}.catch { error in
Logger.error("\(self.TAG) handleOutgoingCall failed with error: \(error)")
}
return call

View File

@ -239,7 +239,9 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// We can't wait for long before fulfilling the CXAction, else CallKit will show a "Failed Call". We don't
// actually need to wait for the outcome of the handleOutgoingCall promise, because it handles any errors by
// manually failing the call.
_ = self.callService.handleOutgoingCall(call)
let callPromise = self.callService.handleOutgoingCall(call)
callPromise.retainUntilComplete()
action.fulfill()
self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil)

View File

@ -0,0 +1,20 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
import PromiseKit
public extension Promise {
/**
* Sometimes there isn't a straight forward candidate to retain a promise, in that case we tell the
* promise to self retain, until it completes to avoid the risk it's GC'd before completion.
*/
func retainUntilComplete() {
// Unfortunately, there is (currently) no way to surpress the
// compiler warning: "Variable 'retainCycle' was written to, but never read"
var retainCycle: Promise<T>? = self
self.always {
retainCycle = nil
}
}
}

View File

@ -50,49 +50,49 @@
"ATTACHMENT" = "مرفقة";
/* Title for the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_DIALOG_TITLE" = "Attachment";
"ATTACHMENT_APPROVAL_DIALOG_TITLE" = "ملحق";
/* Format string for file extension label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "File type: %@";
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "نوع الملف: %@";
/* Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}. */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Size: %@";
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "الحجم: %@";
/* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Send";
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "ارسل";
/* Generic filename for an attachment with no known name */
"ATTACHMENT_DEFAULT_FILENAME" = "Attachment";
"ATTACHMENT_DEFAULT_FILENAME" = "ملحق";
/* Status label when an attachment download has failed. */
"ATTACHMENT_DOWNLOADING_STATUS_FAILED" = "Failed. Tap to retry.";
"ATTACHMENT_DOWNLOADING_STATUS_FAILED" = "لم ينجح تنزيل الملحق. انقر لإعادة المحاولة.";
/* Status label when an attachment is currently downloading */
"ATTACHMENT_DOWNLOADING_STATUS_IN_PROGRESS" = "Downloading...";
"ATTACHMENT_DOWNLOADING_STATUS_IN_PROGRESS" = "جاري التنزيل";
/* Status label when an attachment is enqueued, but hasn't yet started downloading */
"ATTACHMENT_DOWNLOADING_STATUS_QUEUED" = "Queued";
"ATTACHMENT_DOWNLOADING_STATUS_QUEUED" = "في قائمة التنزيل";
/* The title of the 'attachment error' alert. */
"ATTACHMENT_ERROR_ALERT_TITLE" = "Error Sending Attachment";
"ATTACHMENT_ERROR_ALERT_TITLE" = "خطأ في ارسال الملحق";
/* Attachment error message for image attachments which could not be converted to JPEG */
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Image attachment could not be resized.";
"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "لا يمكن إعادة تحجيم الصورة الملحقة ";
/* Attachment error message for image attachments which cannot be parsed */
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Image attachment could not be parsed.";
"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "لا يمكن تحليل الصورة الملحقة";
/* Attachment error message for attachments whose data exceed file size limits */
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Attachment is too large.";
"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "حجم الملحق كبير جدا";
/* Attachment error message for attachments with invalid data */
"ATTACHMENT_ERROR_INVALID_DATA" = "Attachment has invalid contents.";
"ATTACHMENT_ERROR_INVALID_DATA" = "الملحق يحتوي على بيانات غير صحيحة.";
/* Attachment error message for attachments with an invalid file format */
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Attachment has invalid file format.";
"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "صيغة ملف الملحق غير صحيحة.";
/* Attachment error message for attachments without any data */
"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty.";
"ATTACHMENT_ERROR_MISSING_DATA" = "الملحق خالي.";
/* Accessibility hint describing what you can do with the attachment button */
"ATTACHMENT_HINT" = "اختر أو إلتقط صورة ثمّ أرسلها";
@ -101,109 +101,109 @@
"ATTACHMENT_LABEL" = "المرفق";
/* Alert title when picking a document fails for an unknown reason */
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "Failed to choose document.";
"ATTACHMENT_PICKER_DOCUMENTS_FAILED_ALERT_TITLE" = "فشل في اختيار الوثيقة ";
/* Alert body when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "Signal can't handle that file as is. Try zipping it before sending.";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_BODY" = "لا يمكن لـ Signal التعامل مع ملف من هذا النوع. حاول ضغط الملف قبل ارساله.";
/* Alert title when picking a document fails because user picked a directory/bundle */
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Unsupported File";
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "ملف غير مدعم";
/* An explanation of the consequences of blocking another user. */
"BLOCK_BEHAVIOR_EXPLANATION" = "Blocked users will not be able to call you or send you messages.";
"BLOCK_BEHAVIOR_EXPLANATION" = "لن يتمكن المستخدم المحظور من الاتصال بك أو بعث الرسائل إليك.";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Block";
"BLOCK_LIST_BLOCK_BUTTON" = "حظر";
/* A format for the 'block user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_BLOCK_TITLE_FORMAT" = "Block %@?";
"BLOCK_LIST_BLOCK_TITLE_FORMAT" = "حظر %@؟";
/* Button label for the 'unblock' button */
"BLOCK_LIST_UNBLOCK_BUTTON" = "Unblock";
"BLOCK_LIST_UNBLOCK_BUTTON" = "رفع الحظر";
/* A format for the 'unblock user' action sheet title. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "Unblock %@?";
"BLOCK_LIST_UNBLOCK_TITLE_FORMAT" = "رفع الحظر %@؟";
/* A format for the message of the alert if user tries to block a user who is already blocked. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_VIEW_ALREADY_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ is already blocked.";
"BLOCK_LIST_VIEW_ALREADY_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ تم الحظر مسبقاً.";
/* A title of the alert if user tries to block a user who is already blocked. */
"BLOCK_LIST_VIEW_ALREADY_BLOCKED_ALERT_TITLE" = "Already Blocked";
"BLOCK_LIST_VIEW_ALREADY_BLOCKED_ALERT_TITLE" = "محظور مسبقاً";
/* A label for the block button in the block list view */
"BLOCK_LIST_VIEW_BLOCK_BUTTON" = "Block";
"BLOCK_LIST_VIEW_BLOCK_BUTTON" = "حظر";
/* The title of the 'block user failed' alert. */
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_MESSAGE" = "Failed to Block User.";
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_MESSAGE" = "لم ينجح حظر المستخدم.";
/* The title of the 'block user failed' alert. */
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_TITLE" = "Error";
"BLOCK_LIST_VIEW_BLOCK_FAILED_ALERT_TITLE" = "خطأ";
/* The message format of the 'user blocked' alert. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been blocked";
"BLOCK_LIST_VIEW_BLOCKED_ALERT_MESSAGE_FORMAT" = "%@ تم الحظر";
/* The title of the 'user blocked' alert. */
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "User Blocked";
"BLOCK_LIST_VIEW_BLOCKED_ALERT_TITLE" = "المستخدم محظور";
/* The message of the 'You can't block yourself' alert. */
"BLOCK_LIST_VIEW_CANT_BLOCK_SELF_ALERT_MESSAGE" = "You can't block yourself.";
"BLOCK_LIST_VIEW_CANT_BLOCK_SELF_ALERT_MESSAGE" = "لا يمكنك حظر نفسك.";
/* The title of the 'You can't block yourself' alert. */
"BLOCK_LIST_VIEW_CANT_BLOCK_SELF_ALERT_TITLE" = "Error";
"BLOCK_LIST_VIEW_CANT_BLOCK_SELF_ALERT_TITLE" = "خطأ";
/* A title for the contacts section of the block list view. */
"BLOCK_LIST_VIEW_CONTACTS_SECTION_TITLE" = "Contacts";
"BLOCK_LIST_VIEW_CONTACTS_SECTION_TITLE" = "جهات الاتصال";
/* The title of the 'unblock user failed' alert. */
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE" = "Failed to Unblock User.";
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_MESSAGE" = "لم ينجح رفع الحظر عن المستخدم.";
/* The title of the 'unblock user failed' alert. */
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_TITLE" = "Error";
"BLOCK_LIST_VIEW_UNBLOCK_FAILED_ALERT_TITLE" = "خطأ";
/* The message format of the 'user unblocked' alert. Embeds {{the blocked user's name or phone number}}. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT" = "%@ has been unblocked.";
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_MESSAGE_FORMAT" = "%@ تم رفع الحظر.";
/* The title of the 'user unblocked' alert. */
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE" = "User Unblocked";
"BLOCK_LIST_VIEW_UNBLOCKED_ALERT_TITLE" = "المستخدم غير محظور";
/* Action sheet that will block an unknown user. */
"BLOCK_OFFER_ACTIONSHEET_BLOCK_ACTION" = "Block";
"BLOCK_OFFER_ACTIONSHEET_BLOCK_ACTION" = "حظر";
/* Title format for action sheet that offers to block an unknown user.Embeds {{the unknown user's name or phone number}}. */
"BLOCK_OFFER_ACTIONSHEET_TITLE_FORMAT" = "Block %@?";
"BLOCK_OFFER_ACTIONSHEET_TITLE_FORMAT" = "حظر %@؟";
/* Alert message when calling and permissions for microphone are missing */
"CALL_AUDIO_PERMISSION_MESSAGE" = "Signal requires access to your microphone to make calls. You can grant this permission in the Settings app.";
"CALL_AUDIO_PERMISSION_MESSAGE" = "تتطلب Signal الإِذن باتاحة الميكرفون التابع لك لإجراء المكالمات. يمكنك منح الإذن من برنامج ضبط الإعدادات. ";
/* Alert title when calling and permissions for microphone are missing */
"CALL_AUDIO_PERMISSION_TITLE" = "Microphone Access Required";
"CALL_AUDIO_PERMISSION_TITLE" = "الإذن لاستخدام الميكرفون مطلوب";
/* Accessibilty label for placing call button */
"CALL_LABEL" = "إتصل";
/* Call setup status label after outgoing call times out */
"CALL_SCREEN_STATUS_NO_ANSWER" = "No Answer.";
"CALL_SCREEN_STATUS_NO_ANSWER" = "لم يتم الرد على المكالمة.";
/* embeds {{Call Status}} in call screen label. For ongoing calls, {{Call Status}} is a seconds timer like 01:23, otherwise {{Call Status}} is a short text like 'Ringing', 'Busy', or 'Failed Call' */
"CALL_STATUS_FORMAT" = "Signal %@";
"CALL_STATUS_FORMAT" = "Signal %@";
/* Reminder to the user of the benefits of enabling CallKit and disabling CallKit privacy. */
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL" = "You can answer calls directly from your lock screen and see the name and phone number for incoming calls if you change your settings.\n\nSee the privacy settings for details.";
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL" = "يمكنك الرد على المكالمات من شاشة جهازك المقفلة مباشرةً، كما يمكن أن ترى أسم المتصل ورقمه ضمن المكالمات الواردة إِذا قمت بتغيير الإعدادات.\n\nللمزيد من التفاصيل اطلع على إعدادات الخصوصية.";
/* Reminder to the user of the benefits of disabling CallKit privacy. */
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_PRIVACY" = "You can see the name and phone number for incoming calls if you change your settings.\n\nSee the privacy settings for details.";
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_PRIVACY" = "يمكنك أن ترى الأسم والرقم المكالمات الواردة إِذا قمت بتغيير الإعدادات.\n\nللمزيد من التفاصيل اطلع على إعدادات الخصوصية.";
/* Label for button that dismiss the call view's settings nag. */
"CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON" = "Not Now";
"CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON" = "ليس الآن";
/* Label for button that shows the privacy settings */
"CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS" = "Show Privacy Settings";
"CALL_VIEW_SETTINGS_NAG_SHOW_CALL_SETTINGS" = "اظهار إِعدادات الخصوصية";
/* notification action */
"CALLBACK_BUTTON_TITLE" = "إعادة الإتصال";
/* The generic name used for calls if CallKit privacy is enabled */
"CALLKIT_ANONYMOUS_CONTACT_NAME" = "Signal User";
"CALLKIT_ANONYMOUS_CONTACT_NAME" = "مستخدم Signal";
/* Activity Sheet label */
"COMPARE_SAFETY_NUMBER_ACTION" = "المقارنة مع الحافظة";
@ -227,10 +227,10 @@
"CONFIRMATION_TITLE" = "تأكيد";
/* An indicator that a contact has been blocked. */
"CONTACT_CELL_IS_BLOCKED" = "Blocked";
"CONTACT_CELL_IS_BLOCKED" = "محظور";
/* An indicator that a contact is a member of the current group. */
"CONTACT_CELL_IS_IN_GROUP" = "Group Member";
"CONTACT_CELL_IS_IN_GROUP" = "عضو في المجموعة";
/* No comment provided by engineer. */
"CONTACT_DETAIL_COMM_TYPE_INSECURE" = "رقم غير مسجّل";
@ -245,37 +245,37 @@
"CONVERSATION_SETTINGS" = "إعدادات المحادثة";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Block this user";
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "حظر هذا المستخدم";
/* Title of the 'mute this thread' action sheet. */
"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE" = "Mute";
"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE" = "كتم";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Mute";
"CONVERSATION_SETTINGS_MUTE_LABEL" = "كتم";
/* Indicates that the current thread is not muted. */
"CONVERSATION_SETTINGS_MUTE_NOT_MUTED" = "Not muted";
"CONVERSATION_SETTINGS_MUTE_NOT_MUTED" = "لم يتم الكتم ";
/* Label for button to mute a thread for a day. */
"CONVERSATION_SETTINGS_MUTE_ONE_DAY_ACTION" = "Mute for one day";
"CONVERSATION_SETTINGS_MUTE_ONE_DAY_ACTION" = "كتم ليوم واحد";
/* Label for button to mute a thread for a hour. */
"CONVERSATION_SETTINGS_MUTE_ONE_HOUR_ACTION" = "Mute for one hour";
"CONVERSATION_SETTINGS_MUTE_ONE_HOUR_ACTION" = "كتم لساعة واحدة";
/* Label for button to mute a thread for a minute. */
"CONVERSATION_SETTINGS_MUTE_ONE_MINUTE_ACTION" = "Mute for one minute";
"CONVERSATION_SETTINGS_MUTE_ONE_MINUTE_ACTION" = "كتم لدقيقة واحدة";
/* Label for button to mute a thread for a week. */
"CONVERSATION_SETTINGS_MUTE_ONE_WEEK_ACTION" = "Mute for one week";
"CONVERSATION_SETTINGS_MUTE_ONE_WEEK_ACTION" = "كتم لأسبوع واحد";
/* Label for button to mute a thread for a year. */
"CONVERSATION_SETTINGS_MUTE_ONE_YEAR_ACTION" = "Mute for one year";
"CONVERSATION_SETTINGS_MUTE_ONE_YEAR_ACTION" = "كتم لسنة واحدة";
/* 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 %@";
"CONVERSATION_SETTINGS_MUTED_UNTIL_FORMAT" = "حتى %@";
/* Label for button to unmute a thread. */
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "Unmute";
"CONVERSATION_SETTINGS_UNMUTE_ACTION" = "رفع الكتم";
/* ActionSheet title */
"CORRUPTED_SESSION_DESCRIPTION" = "إعادة تعيين جلستك سيسمح لك باستقبال الرسائل الحديثة من %@, لكن لن تتمكن من استعادة أي من الرسائل التالفة.";
@ -284,7 +284,7 @@
"COUNTRYCODE_SELECT_TITLE" = "اختر رمز الدولة";
/* Accessibility label for the create group new group button */
"CREATE_NEW_GROUP" = "Create new group";
"CREATE_NEW_GROUP" = "انشاء مجموعة جديدة";
/* {{number of days}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 days}}'. See other *_TIME_AMOUNT strings */
"DAYS_TIME_AMOUNT" = "%u يوم";
@ -317,19 +317,19 @@
"EDIT_GROUP_ACTION" = "تعديل المجموعة";
/* A format for the message of the alert if user tries to add a user to a group who is already in the group. Embeds {{the blocked user's name or phone number}}. */
"EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_MESSAGE_FORMAT" = "%@ is already a member of this group.";
"EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_MESSAGE_FORMAT" = "%@ عضو في هذه المجموعة أصلاً.";
/* A title of the alert if user tries to add a user to a group who is already in the group. */
"EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_TITLE" = "Already a Group Member";
"EDIT_GROUP_VIEW_ALREADY_IN_GROUP_ALERT_TITLE" = "عضو في المجموعة مسبقاً";
/* Short name for edit menu item to copy contents of media message. */
"EDIT_ITEM_COPY_ACTION" = "Copy";
"EDIT_ITEM_COPY_ACTION" = "نسخ";
/* Short name for edit menu item to save contents of media message. */
"EDIT_ITEM_SAVE_ACTION" = "حفظ";
/* Short name for edit menu item to share contents of media message. */
"EDIT_ITEM_SHARE_ACTION" = "Share";
"EDIT_ITEM_SHARE_ACTION" = "تبادل";
/* body of email sent to contacts when inviting to install Signal. Embeds {{link to install Signal}} and {{link to WhisperSystems home page}} */
"EMAIL_INVITE_BODY" = "مرحبّا,\n\nمؤخرًا أصبحت أستخدم Signal لجعل محادثاتي على الـiPhone سرية. أرغب أن تثبّته أنت كذلك حتى نتأكد أنا وأنت أننا فقط من يمكنه قراءة رسائلنا أو سماع مكالماتنا.\n\nSignal متاح للـiPhone واﻷندرويد. احصل عليه من هنا: %@\n\nيعمل Signal كما تطبيق تراسلك الحالي. يستطيع إرسال الصور والفيديو, إجاراء المكالمات, وبدء محادثة جماعية. وأفضل جزء هو, لا أحد آخر قادرعلى رؤية أي شيء من ذلك, ولا حتى صنّاع Signal!\n\nتستطيع قراءة المزيد عن Open Whisper Systems, صنّاع Signal, هنا: %@";
@ -368,25 +368,25 @@
"EMPTY_INBOX_TITLE" = "خالٍ تماماً";
/* Call setup status label */
"END_CALL_RESPONDER_IS_BUSY" = "Busy.";
"END_CALL_RESPONDER_IS_BUSY" = "مشغول.";
/* Call setup status label */
"END_CALL_UNCATEGORIZED_FAILURE" = "Call Failed.";
"END_CALL_UNCATEGORIZED_FAILURE" = "لم ينجح الاتصال الهاتفي.";
/* Generic notice when message failed to send. */
"ERROR_DESCRIPTION_CLIENT_SENDING_FAILURE" = "فشل إرسال الرسالة.";
/* Error mesage indicating that message send is disabled due to prekey update failures */
"ERROR_DESCRIPTION_MESSAGE_SEND_DISABLED_PREKEY_UPDATE_FAILURES" = "Unable to send due to stale privacy data.";
"ERROR_DESCRIPTION_MESSAGE_SEND_DISABLED_PREKEY_UPDATE_FAILURES" = "غير قادر على الارسال بسبب بيانات الخصوصية القديمة.";
/* Error mesage indicating that message send failed due to block list */
"ERROR_DESCRIPTION_MESSAGE_SEND_FAILED_DUE_TO_BLOCK_LIST" = "Failed to message user because you blocked them.";
"ERROR_DESCRIPTION_MESSAGE_SEND_FAILED_DUE_TO_BLOCK_LIST" = "لم ينجح بعث الرسالة لأن المستخدم محظور.";
/* Generic error used whenver Signal can't contact the server */
"ERROR_DESCRIPTION_NO_INTERNET" = "Signal غير قادر على الاتصال بالإنترنت. من فضلك حاول من شبكة WiFi أخرى أو استخدم بيانات الهاتف.";
/* Error indicating that an outgoing message had no valid recipients. */
"ERROR_DESCRIPTION_NO_VALID_RECIPIENTS" = "Message send failed due to a lack of valid recipients.";
"ERROR_DESCRIPTION_NO_VALID_RECIPIENTS" = "لم ينجح بعث الرسالة لعدم صحة معلومات المستلمين. ";
/* Error message when attempting to send message */
"ERROR_DESCRIPTION_SENDING_UNAUTHORIZED" = "جهازك لم يعد مسجّلًا برقم هاتفك. عليك حذف وإعادة تثبيت Signal.";
@ -395,10 +395,10 @@
"ERROR_DESCRIPTION_SERVER_FAILURE" = "خطأ في المخدم، الرجاء تكرار المحاولة لاحقاً.";
/* Worst case generic error message */
"ERROR_DESCRIPTION_UNKNOWN_ERROR" = "An unknown error occured.";
"ERROR_DESCRIPTION_UNKNOWN_ERROR" = "حدث خطأ غير معروف.";
/* Error message when attempting to send message */
"ERROR_DESCRIPTION_UNREGISTERED_RECIPIENT" = "Contact is not a Signal user.";
"ERROR_DESCRIPTION_UNREGISTERED_RECIPIENT" = "جهة الاتصال ليست من مستخدمي Signal.";
/* No comment provided by engineer. */
"ERROR_MESSAGE_DUPLICATE_MESSAGE" = "تم تلقي رسالة مكررة.";
@ -431,19 +431,19 @@
"EXISTING_USER_REGISTRATION_ALERT_TITLE" = "تفعيل %@ سوف يعطّل Signal على أي جهاز آخر مرتبط بهذا الرقم حاليّا.";
/* Message for the alert indicating the 'export with signal' file had an invalid filename. */
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_INVALID_FILENAME" = "Invalid filename.";
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_INVALID_FILENAME" = "أسم الملف غير صحيح.";
/* Message for the alert indicating the 'export with signal' attachment couldn't be loaded. */
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_MISSING_ATTACHMENT" = "Couldn't load file.";
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_MISSING_ATTACHMENT" = "لم ينجح تحميل الملف.";
/* Message for the alert indicating the 'export with signal' data couldn't be loaded. */
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_MISSING_DATA" = "Couldn't load file.";
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_MISSING_DATA" = "لم ينجح تحميل لملف.";
/* Message for the alert indicating the 'export with signal' file had unknown type. */
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_UNKNOWN_TYPE" = "Unknown file type.";
"EXPORT_WITH_SIGNAL_ERROR_MESSAGE_UNKNOWN_TYPE" = "نوع الملف غير معروف.";
/* Title for the alert indicating the 'export with signal' attachment had an error. */
"EXPORT_WITH_SIGNAL_ERROR_TITLE" = "Error";
"EXPORT_WITH_SIGNAL_ERROR_TITLE" = "خطأ";
/* action sheet header when re-sending message which failed because of too many attempts */
"FAILED_SENDING_BECAUSE_RATE_LIMIT" = "الكثير من الأخطاء مع جهة الاتصال هذه. فضلّا حاول مرة أخرى بعد لحظات.";
@ -461,10 +461,10 @@
"FINISH_GROUP_CREATION_LABEL" = "إتمام إنشاء المجموعة";
/* A default label for attachment whose file extension cannot be determined. */
"GENERIC_ATTACHMENT_DEFAULT_TYPE" = "?";
"GENERIC_ATTACHMENT_DEFAULT_TYPE" = "؟";
/* A label for generic attachments. */
"GENERIC_ATTACHMENT_LABEL" = "Attachment";
"GENERIC_ATTACHMENT_LABEL" = "ملحق";
/* No comment provided by engineer. */
"GROUP_AVATAR_CHANGED" = "تغيرت الصورة الرمزية.";
@ -488,16 +488,16 @@
"GROUP_MEMBER_LEFT" = "%@ غادر المجموعة";
/* Button label for the 'call group member' button */
"GROUP_MEMBERS_CALL" = "Call";
"GROUP_MEMBERS_CALL" = "اتصال هاتفي";
/* header for table which lists the members of this group thread */
"GROUP_MEMBERS_HEADER" = "أعضاء المجموعة";
/* Button label for the 'send message to group member' button */
"GROUP_MEMBERS_SEND_MESSAGE" = "Send Message";
"GROUP_MEMBERS_SEND_MESSAGE" = "بعث الرسالة";
/* Button label for the 'show contact info' button */
"GROUP_MEMBERS_VIEW_CONTACT_INFO" = "Contact Info";
"GROUP_MEMBERS_VIEW_CONTACT_INFO" = "معلومات جهات الاتصال";
/* No comment provided by engineer. */
"GROUP_REMOVING" = "مغادرة مجموعة %@";
@ -515,7 +515,7 @@
"GROUP_YOU_LEFT" = "لقد غادرت المجموعة";
/* A label for conversations with blocked users. */
"HOME_VIEW_BLOCKED_CONTACT_CONVERSATION" = "Blocked";
"HOME_VIEW_BLOCKED_CONTACT_CONVERSATION" = "محظور";
/* {{number of hours}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 hours}}'. See other *_TIME_AMOUNT strings */
"HOURS_TIME_AMOUNT" = "%u ساعات";
@ -533,7 +533,7 @@
"IN_CALL_TALKING" = "آمن. فعال.";
/* Call setup status label */
"IN_CALL_TERMINATED" = "Call Ended.";
"IN_CALL_TERMINATED" = "انتهت المكالمة.";
/* notification body */
"INCOMING_CALL" = "مكالمة واردة";
@ -542,13 +542,13 @@
"INCOMING_CALL_FROM" = "مكالمة واردة من %@";
/* No comment provided by engineer. */
"INCOMING_INCOMPLETE_CALL" = "Incomplete incoming call from";
"INCOMING_INCOMPLETE_CALL" = "مكالمة غير كاملة واردة من";
/* Text for button at the top of the contact picker */
"INVITE_FRIENDS_CONTACT_TABLE_BUTTON" = "دعوة اﻷصدقاء لـSignal";
/* Search */
"INVITE_FRIENDS_PICKER_SEARCHBAR_PLACEHOLDER" = "Search";
"INVITE_FRIENDS_PICKER_SEARCHBAR_PLACEHOLDER" = "بحث";
/* Navbar title */
"INVITE_FRIENDS_PICKER_TITLE" = "أدع أصدقائك";
@ -614,7 +614,7 @@
"MEDIA_FROM_CAMERA_BUTTON" = "الكاميرا";
/* action sheet button title when choosing attachment type */
"MEDIA_FROM_DOCUMENT_PICKER_BUTTON" = "Document";
"MEDIA_FROM_DOCUMENT_PICKER_BUTTON" = "وثيقة";
/* media picker option to choose from library */
"MEDIA_FROM_LIBRARY_BUTTON" = "مكتبة الصور";
@ -623,34 +623,34 @@
"MESSAGE_COMPOSEVIEW_TITLE" = "رسالة جديدة";
/* message footer for delivered messages */
"MESSAGE_STATUS_DELIVERED" = "Delivered";
"MESSAGE_STATUS_DELIVERED" = "تم الاستلام";
/* message footer for failed messages */
"MESSAGE_STATUS_FAILED" = "Sending failed. Tap to retry.";
"MESSAGE_STATUS_FAILED" = "لم ينجح الارسال. انقر لإعادة المحاولة.";
/* message footer for sent messages */
"MESSAGE_STATUS_SENT" = "Sent";
"MESSAGE_STATUS_SENT" = "تم الارسال";
/* message footer while attachment is uploading */
"MESSAGE_STATUS_UPLOADING" = "Uploading...";
"MESSAGE_STATUS_UPLOADING" = "جاري التحميل";
/* Indicates that this 1:1 conversation has been blocked. */
"MESSAGES_VIEW_CONTACT_BLOCKED" = "You Blocked this User";
"MESSAGES_VIEW_CONTACT_BLOCKED" = "حظرت هذا المستخدم ";
/* Action sheet title after tapping on failed download. */
"MESSAGES_VIEW_FAILED_DOWNLOAD_ACTIONSHEET_TITLE" = "Download Failed.";
"MESSAGES_VIEW_FAILED_DOWNLOAD_ACTIONSHEET_TITLE" = "لم ينجح التنزيل.";
/* Action sheet button text */
"MESSAGES_VIEW_FAILED_DOWNLOAD_RETRY_ACTION" = "Download Again";
"MESSAGES_VIEW_FAILED_DOWNLOAD_RETRY_ACTION" = "إعادة التنزيل";
/* Indicates that a single member of this group has been blocked. */
"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED" = "You Blocked 1 Member of this Group";
"MESSAGES_VIEW_GROUP_1_MEMBER_BLOCKED" = "قمت بحظر 1 عضو من هذه المجموعة";
/* Indicates that some members of this group has been blocked. Embeds {{the number of blocked users in this group}}. */
"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT" = "You Blocked %d Members of this Group";
"MESSAGES_VIEW_GROUP_N_MEMBERS_BLOCKED_FORMAT" = "حظرت %d أعضاء من هذه المجموعة";
/* The subtitle for the messages view title indicates that the title can be tapped to access settings for this conversation. */
"MESSAGES_VIEW_TITLE_SUBTITLE" = "Tap here for settings";
"MESSAGES_VIEW_TITLE_SUBTITLE" = "انقر هنا لفتح الإعدادات";
/* {{number of minutes}} embedded in strings, e.g. 'Alice updated disappearing messages expiration to {{5 minutes}}'. See other *_TIME_AMOUNT strings */
"MINUTES_TIME_AMOUNT" = "%u دقيقة";
@ -660,29 +660,29 @@
/* Alert body
Alert body when camera is not authorized */
"MISSING_CAMERA_PERMISSION_MESSAGE" = "Signal needs access to your camera for video calls. You can grant this permission in the Settings app >> Privacy >> Camera >> Signal";
"MISSING_CAMERA_PERMISSION_MESSAGE" = "Singal بحاجة إِلى استخدام كاميرتك لإجراء الاتصالات الفيديوية. يمكنك السماح بذلك من برنامج الإعدادات >> الخصوصية >> الكاميرا >> Signal";
/* Alert title
Alert title when camera is not authorized */
"MISSING_CAMERA_PERMISSION_TITLE" = "يحتاج Signal للوصول للكاميرا";
/* notification title. Embeds {{Caller's Name}} */
"MSGVIEW_MISSED_CALL_WITH_NAME" = "Missed call from %@.";
"MSGVIEW_MISSED_CALL_WITH_NAME" = "مكالمة فائتة من %@";
/* notification title. */
"MSGVIEW_MISSED_CALL_WITHOUT_NAME" = "Missed call from Signal User.";
"MSGVIEW_MISSED_CALL_WITHOUT_NAME" = "مكالمة فائتة من مستخدم Signal";
/* No comment provided by engineer. */
"MSGVIEW_RECEIVED_CALL" = "مكالمة واردة من %@";
/* No comment provided by engineer. */
"MSGVIEW_THEY_TRIED_TO_CALL_YOU" = "%@ tried to call you.";
"MSGVIEW_THEY_TRIED_TO_CALL_YOU" = "%@ حاول الاتصال بك.";
/* No comment provided by engineer. */
"MSGVIEW_YOU_CALLED" = "لقد اتصلت ب %@";
/* No comment provided by engineer. */
"MSGVIEW_YOU_TRIED_TO_CALL" = "You tried to call %@.";
"MSGVIEW_YOU_TRIED_TO_CALL" = "حاولت الاتصال %@.";
/* No comment provided by engineer. */
"MULTIDEVICE_PAIRING_MAX_DESC" = "لا يمكنك ربط أي أجهزة أخرى.";
@ -691,7 +691,7 @@
"MULTIDEVICE_PAIRING_MAX_RECOVERY" = "لقد وصلت للحد اﻷقصى من اﻷجهزة المرتبطة بحسابك. من فضلك أزل جهاز أو حاول مرة أخرى لاحقًا.";
/* An explanation of the consequences of muting a thread. */
"MUTE_BEHAVIOR_EXPLANATION" = "You will not receive notifications for muted conversations.";
"MUTE_BEHAVIOR_EXPLANATION" = "لن تستلم تنبيهات من المحادثات التي تم كتمها.";
/* No comment provided by engineer. */
"NETWORK_ERROR_RECOVERY" = "من فضلك تأكد من اتصالك بالانترنت وحاول مرة أخرى.";
@ -712,7 +712,7 @@
"NETWORK_STATUS_TEXT" = "يمكنك التأكد من حالة الشبكة من خلال الشريط الملون أعلى صندوق الوارد";
/* Text for button to start a new conversation with a non-contact */
"NEW_CONVERSATION_FOR_NON_CONTACT_FORMAT" = "New conversation with %@";
"NEW_CONVERSATION_FOR_NON_CONTACT_FORMAT" = "محادثة جديدة مع %@";
/* Action Sheet title prompting the user for a group avatar */
"NEW_GROUP_ADD_PHOTO_ACTION" = "ضع صورة للمجموعة";
@ -727,7 +727,7 @@
"NEW_GROUP_REQUEST_ADDPEOPLE" = "إضافة أشخاص";
/* Label for a button that lets users search for contacts by phone number */
"NO_CONTACTS_SEARCH_BY_PHONE_NUMBER" = "Find Contacts by Phone Number";
"NO_CONTACTS_SEARCH_BY_PHONE_NUMBER" = "العثور على أسماء من يتم الاتصال بهم عن طريق رقم الهاتف";
/* No comment provided by engineer. */
"NOTIFICATION_SEND_FAILED" = "فشل إرسال رسالتك إلى %@.";
@ -773,13 +773,13 @@
"OUTGOING_CALL" = "مكالمة صادرة";
/* No comment provided by engineer. */
"OUTGOING_INCOMPLETE_CALL" = "Incomplete outgoing call";
"OUTGOING_INCOMPLETE_CALL" = "مكالمة صادرة غير كاملة";
/* A display format for oversize text messages. */
"OVERSIZE_TEXT_DISPLAY_FORMAT" = "%@… [Tap For More]";
"OVERSIZE_TEXT_DISPLAY_FORMAT" = "%@… [انقر لرؤية المزيد]";
/* The title of the 'oversize text message' view. */
"OVERSIZE_TEXT_MESSAGE_VIEW_TITLE" = "Message";
"OVERSIZE_TEXT_MESSAGE_VIEW_TITLE" = "رسالة ";
/* Alert body when verifying with {{contact name}} */
"PRIVACY_VERIFICATION_FAILED_I_HAVE_WRONG_KEY_FOR_THEM" = "لا يبدو هذا رقم اﻷمان الخاص بك مع %@. هل تتحقق من جهة الاتصال الصحيحة؟";
@ -854,10 +854,10 @@
"REGISTER_CONTACTS_WELCOME" = "مرحبًا!";
/* No comment provided by engineer. */
"REGISTER_FAILED_TRY_AGAIN" = "Try Again";
"REGISTER_FAILED_TRY_AGAIN" = "حاول مرة أُخرى";
/* No comment provided by engineer. */
"REGISTER_RATE_LIMITING_BODY" = "You have tried too often. Please wait a minute before trying again.";
"REGISTER_RATE_LIMITING_BODY" = "حاولت مراراً وتكراراً . الرجاء الانتظار لدقيقة واحدة قبل إعادة المحاولة.";
/* No comment provided by engineer. */
"REGISTERED_NUMBER_TEXT" = "رقم مسجّل";
@ -932,16 +932,16 @@
"SECURE_SESSION_RESET" = "لقد تم إعادة تعيين دورة الاتصال الآمنة";
/* No comment provided by engineer. */
"SEND_AGAIN_BUTTON" = "Send Again";
"SEND_AGAIN_BUTTON" = "ارسل مرة أُخرى";
/* No comment provided by engineer. */
"SEND_BUTTON_TITLE" = "إرسال";
/* Header title for the 'send external file' view. */
"SEND_EXTERNAL_FILE_HEADER_TITLE" = "Select a Recipient for:";
"SEND_EXTERNAL_FILE_HEADER_TITLE" = "اختر مستلم لـ:";
/* Title for the 'send external file' view. */
"SEND_EXTERNAL_FILE_VIEW_TITLE" = "Send File";
"SEND_EXTERNAL_FILE_VIEW_TITLE" = "ارسل الملف";
/* Alert body after invite failed */
"SEND_INVITE_FAILURE" = "فشل إرسال الدعوة, فضلّا أعد المحاولة لاحقًا.";
@ -950,7 +950,7 @@
"SEND_INVITE_SUCCESS" = "لقد دعوت صديقك لاستخدام Signal!";
/* Text for button to send a Signal invite via SMS. %@ is placeholder for the receipient's phone number. */
"SEND_INVITE_VIA_SMS_BUTTON_FORMAT" = "Send Invite via SMS to: %@";
"SEND_INVITE_VIA_SMS_BUTTON_FORMAT" = "ارسل الدعوة عبر رسالة نصية: %@";
/* No comment provided by engineer. */
"SEND_SMS_CONFIRM_TITLE" = "إرسال دعوة لصديق عن طريق رسالة نصية غير آمنة؟";
@ -962,13 +962,13 @@
"SETTINGS_ABOUT" = "حول";
/* Title for the 'block contact' section of the 'add to block list' view. */
"SETTINGS_ADD_TO_BLOCK_LIST_BLOCK_CONTACT_TITLE" = "Block Contact";
"SETTINGS_ADD_TO_BLOCK_LIST_BLOCK_CONTACT_TITLE" = "حظر المتصل";
/* Title for the 'block phone number' section of the 'add to block list' view. */
"SETTINGS_ADD_TO_BLOCK_LIST_BLOCK_PHONE_NUMBER_TITLE" = "Block Phone Number";
"SETTINGS_ADD_TO_BLOCK_LIST_BLOCK_PHONE_NUMBER_TITLE" = "حظر رقم الهاتف";
/* Title for the 'add to block list' view. */
"SETTINGS_ADD_TO_BLOCK_LIST_TITLE" = "Block";
"SETTINGS_ADD_TO_BLOCK_LIST_TITLE" = "حظر";
/* No comment provided by engineer. */
"SETTINGS_ADVANCED_DEBUGLOG" = "تفعيل سجل التصحيح";
@ -980,13 +980,13 @@
"SETTINGS_ADVANCED_TITLE" = "إعدادات متقدمة";
/* A label for the 'add phone number' button in the block list table. */
"SETTINGS_BLOCK_LIST_ADD_BUTTON" = "Add…";
"SETTINGS_BLOCK_LIST_ADD_BUTTON" = "إضافة";
/* A label that indicates the user has no Signal contacts. */
"SETTINGS_BLOCK_LIST_NO_CONTACTS" = "You have no contacts on Signal.";
"SETTINGS_BLOCK_LIST_NO_CONTACTS" = "جهات الاتصال الخاصة بك غير موجودة على Signal.";
/* Label for the block list section of the settings view */
"SETTINGS_BLOCK_LIST_TITLE" = "Blocked";
"SETTINGS_BLOCK_LIST_TITLE" = "تم الحظر";
/* User settings section footer, a detailed explanation */
"SETTINGS_BLOCK_ON_IDENITY_CHANGE_DETAIL" = "موافقتك مطلوبة قبل التواصل مع شخص لديه رقم أمان جديد, غالبًا بسبب إعادته تثبيت Signal.";
@ -995,13 +995,13 @@
"SETTINGS_BLOCK_ON_IDENTITY_CHANGE_TITLE" = "يتطلّب التأكيد عند التغيير";
/* Accessibility hint for the settings button */
"SETTINGS_BUTTON_ACCESSIBILITY" = "Settings";
"SETTINGS_BUTTON_ACCESSIBILITY" = "الإعدادات";
/* Table cell label */
"SETTINGS_CALLING_HIDES_IP_ADDRESS_PREFERENCE_TITLE" = "Always Relay Calls";
"SETTINGS_CALLING_HIDES_IP_ADDRESS_PREFERENCE_TITLE" = "مناوبة المكالمات الهاتفية دوماً";
/* User settings section footer, a detailed explanation */
"SETTINGS_CALLING_HIDES_IP_ADDRESS_PREFERENCE_TITLE_DETAIL" = "Relay all calls through the Signal server to avoid revealing your IP address to your contact. Enabling will reduce call quality.";
"SETTINGS_CALLING_HIDES_IP_ADDRESS_PREFERENCE_TITLE_DETAIL" = "مناوبة جميع المكالمات عن طريق شبكة خدمة Signal لتجنب ظهور عنوان الـ IP الخاص بك إِلى جهات الاتصال. سيُقلل التمكين من جودة المكالمة.";
/* No comment provided by engineer. */
"SETTINGS_CLEAR_HISTORY" = "امسح سجل التاريخ";
@ -1040,10 +1040,10 @@
"SETTINGS_NOTIFICATIONS" = "الإشعارات";
/* Label for 'CallKit privacy' preference */
"SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE" = "Show Caller's Name & Number";
"SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE" = "اظهار أسم المتصل ورقمه";
/* Short table cell label */
"SETTINGS_PRIVACY_CALLKIT_TITLE" = "iOS Call Integration";
"SETTINGS_PRIVACY_CALLKIT_TITLE" = "نظام التشغيل iOS لدمج المكالمة";
/* No comment provided by engineer. */
"SETTINGS_PRIVACY_TITLE" = "الخصوصية";
@ -1055,13 +1055,13 @@
"SETTINGS_SCREEN_SECURITY" = "تفعيل خاصية تأمين الشاشة";
/* No comment provided by engineer. */
"SETTINGS_SCREEN_SECURITY_DETAIL" = "Prevent Signal previews from appearing in the app switcher.";
"SETTINGS_SCREEN_SECURITY_DETAIL" = "منع ظهور استعراضات Signal في محول البرنامج.";
/* Settings table section footer. */
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "iOS Call Integration shows Signal calls on your lock screen and in the system's call history. You may optionally show your contact's name and number. If iCloud is enabled, this call history will be shared with Apple.";
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "يعرض دمج المكالمة التابع لـ iOS مكالمات Signal الهاتفية على الشاشة المقفلة وفي سجل اتصالات النظام. يمكنك أن تختار اظهار أسم المتصل ورقمه. في حال تمكين iCloud يتم تبادل تاريخ المكالمات مع Apple.";
/* settings topic header for table section */
"SETTINGS_SECTION_TITLE_CALLING" = "Calling";
"SETTINGS_SECTION_TITLE_CALLING" = "جاري الاتصال";
/* Section header */
"SETTINGS_SECURITY_TITLE" = "تأمين الشاشة";
@ -1118,7 +1118,7 @@
"UNKNOWN_ATTACHMENT_LABEL" = "مرفق غير معلوم";
/* No comment provided by engineer. */
"UNKNOWN_CONTACT_BLOCK_OFFER" = "User not in your contacts. Would you like to block this user?";
"UNKNOWN_CONTACT_BLOCK_OFFER" = "المستخدم ليس ضمن أسماء قائمة جهات الاتصال التابعة لك. هل ترغب في حظر هذا المستخدم؟";
/* Displayed if for some reason we can't determine a contacts phone number *or* name */
"UNKNOWN_CONTACT_NAME" = "جهة اتصال مجهولة";
@ -1151,40 +1151,40 @@
"UPDATE_BUTTON_TITLE" = "تحديث";
/* Description of CallKit to upgrading (existing) users */
"UPGRADE_EXPERIENCE_CALLKIT_DESCRIPTION" = "Answering calls from your lock screen is easy with iOS call integration. We anonymize your caller by default, so it's private too.";
"UPGRADE_EXPERIENCE_CALLKIT_DESCRIPTION" = "بدمج المكالمات عبر نظام تشغيل iOS يصبح من السهل الرد على المكالمات الهاتفية والشاشة مقفلة. نقوم باخفاء هوية المتصل أساساً، لذا فهي خاصة أيضاً. ";
/* button label shown once when when user upgrades app, in context of call kit */
"UPGRADE_EXPERIENCE_CALLKIT_PRIVACY_SETTINGS_BUTTON" = "Learn more in your privacy settings.";
"UPGRADE_EXPERIENCE_CALLKIT_PRIVACY_SETTINGS_BUTTON" = "تعلم المزيد عن إعدادات الخصوصية.";
/* Header for upgrade experience */
"UPGRADE_EXPERIENCE_CALLKIT_TITLE" = "Just Swipe to Answer";
"UPGRADE_EXPERIENCE_CALLKIT_TITLE" = "تصفح بسلاسة لتعرف الإجابة ببساطة";
/* Description of video calling to upgrading (existing) users */
"UPGRADE_EXPERIENCE_VIDEO_DESCRIPTION" = "Signal now supports secure video calling. Just start a call like normal, tap the camera button, and wave hello.";
"UPGRADE_EXPERIENCE_VIDEO_DESCRIPTION" = "تدعم Signal حالياً الاتصال الفيديوي الآمن. إِبدأ بمجرد إجراء الاتصال الهاتفي المعتاد، وانقر على زرّ الكاميرا، ثم لوِّح لتلقي التحية. ";
/* Header for upgrade experience */
"UPGRADE_EXPERIENCE_VIDEO_TITLE" = "Hello Secure Video Calls!";
"UPGRADE_EXPERIENCE_VIDEO_TITLE" = "أهلاً بالاتصالات الفيديوية الآمنة! ";
/* No comment provided by engineer. */
"Upgrading Signal ..." = "ترقية Signal ...";
/* button text for back button on verification view */
"VERIFICATION_BACK_BUTTON" = "Back";
"VERIFICATION_BACK_BUTTON" = "الرجوع";
/* Text field placeholder for SMS verification code during registration */
"VERIFICATION_CHALLENGE_DEFAULT_TEXT" = "رمز التحقق";
/* button text during registration to request phone number verification be done via phone call */
"VERIFICATION_CHALLENGE_SEND_VIA_VOICE" = "Call Me Instead";
"VERIFICATION_CHALLENGE_SEND_VIA_VOICE" = "اتصل بي بدلاً من ذلك";
/* button text during registration to request another SMS code be sent */
"VERIFICATION_CHALLENGE_SUBMIT_AGAIN" = "Resend Code by SMS";
"VERIFICATION_CHALLENGE_SUBMIT_AGAIN" = "إعادة ارسال الشفرة عبر الرسائل النصية";
/* button text during registration to submit your SMS verification code */
"VERIFICATION_CHALLENGE_SUBMIT_CODE" = "تقديم رمز التحقق";
/* Label indicating the phone number currently being verified. */
"VERIFICATION_PHONE_NUMBER_FORMAT" = "Enter the verification code we sent to %@.";
"VERIFICATION_PHONE_NUMBER_FORMAT" = "ادخال شفرة التحقق التي أرسلناها إلى %@.";
/* table cell label in conversation settings */
"VERIFY_PRIVACY" = "التحقق من الرقم اﻷمان";

View File

@ -188,10 +188,10 @@
"CALL_STATUS_FORMAT" = "Signal %@";
/* Reminder to the user of the benefits of enabling CallKit and disabling CallKit privacy. */
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL" = "You can answer calls directly from your lock screen and see the name and phone number for incoming calls if you change your settings.\n\nSee the privacy settings for details.";
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_ALL" = "Você pode atender chamadas diretamente da sua tela bloqueada e ver o nome e o número de telefone de chamadas recebidas se você mudar suas configurações.\n\nPara detalhes, veja as configurações de privacidade.";
/* Reminder to the user of the benefits of disabling CallKit privacy. */
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_PRIVACY" = "You can see the name and phone number for incoming calls if you change your settings.\n\nSee the privacy settings for details.";
"CALL_VIEW_SETTINGS_NAG_DESCRIPTION_PRIVACY" = "Você pode ver o nome e o número de telefone de chamadas recebidas se você mudar suas configurações.\n\nPara detalhes, veja as configurações de privacidade.";
/* Label for button that dismiss the call view's settings nag. */
"CALL_VIEW_SETTINGS_NAG_NOT_NOW_BUTTON" = "Agora não";
@ -1043,7 +1043,7 @@
"SETTINGS_PRIVACY_CALLKIT_PRIVACY_TITLE" = "Exibir o nome e número do contato";
/* Short table cell label */
"SETTINGS_PRIVACY_CALLKIT_TITLE" = "iOS Call Integration";
"SETTINGS_PRIVACY_CALLKIT_TITLE" = "Integração de Chamada do iOS";
/* No comment provided by engineer. */
"SETTINGS_PRIVACY_TITLE" = "Privacidade";
@ -1055,10 +1055,10 @@
"SETTINGS_SCREEN_SECURITY" = "Habilitar Segurança de Tela";
/* No comment provided by engineer. */
"SETTINGS_SCREEN_SECURITY_DETAIL" = "Prevent Signal previews from appearing in the app switcher.";
"SETTINGS_SCREEN_SECURITY_DETAIL" = "Impeça que pré-vizualizações apareçam no seletor de aplicativos.";
/* Settings table section footer. */
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "iOS Call Integration shows Signal calls on your lock screen and in the system's call history. You may optionally show your contact's name and number. If iCloud is enabled, this call history will be shared with Apple.";
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "A Integração de Chamadas do iOS exibe chamadas do Signal na tela bloqueada e no histórico de chamadas do sistema. Você pode optar por exibir o nome e o número do seu contato. Se o iCloud estiver ativado, esse histórico de ligações será compartilhado com a Apple.";
/* settings topic header for table section */
"SETTINGS_SECTION_TITLE_CALLING" = "Chamando";
@ -1151,7 +1151,7 @@
"UPDATE_BUTTON_TITLE" = "Atualizar";
/* Description of CallKit to upgrading (existing) users */
"UPGRADE_EXPERIENCE_CALLKIT_DESCRIPTION" = "Answering calls from your lock screen is easy with iOS call integration. We anonymize your caller by default, so it's private too.";
"UPGRADE_EXPERIENCE_CALLKIT_DESCRIPTION" = "Atender ligações da sua tela bloqueada é fácil com a integração de chamada do iOS. Nós anonimizamos a identidade daquele que liga para que ela também seja privada.";
/* button label shown once when when user upgrades app, in context of call kit */
"UPGRADE_EXPERIENCE_CALLKIT_PRIVACY_SETTINGS_BUTTON" = "Saiba mais nas configurações de privacidade.";

View File

@ -110,7 +110,7 @@
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Неподдерживаемый файл";
/* An explanation of the consequences of blocking another user. */
"BLOCK_BEHAVIOR_EXPLANATION" = "Заблокированные пользователь не смогут звонить или отправлять сообщения Вам.";
"BLOCK_BEHAVIOR_EXPLANATION" = "Заблокированные пользователи не смогут звонить или отправлять сообщения Вам.";
/* Button label for the 'block' button */
"BLOCK_LIST_BLOCK_BUTTON" = "Заблокировать";
@ -245,16 +245,16 @@
"CONVERSATION_SETTINGS" = "Настройки разговоров";
/* table cell label in conversation settings */
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Заблокировать этого пользователя";
"CONVERSATION_SETTINGS_BLOCK_THIS_USER" = "Заблокировать";
/* Title of the 'mute this thread' action sheet. */
"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE" = "Беззвучный режим";
"CONVERSATION_SETTINGS_MUTE_ACTION_SHEET_TITLE" = "Без звука";
/* label for 'mute thread' cell in conversation settings */
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Беззвучный режим";
"CONVERSATION_SETTINGS_MUTE_LABEL" = "Без звука";
/* Indicates that the current thread is not muted. */
"CONVERSATION_SETTINGS_MUTE_NOT_MUTED" = "Звук уведомлений включен";
"CONVERSATION_SETTINGS_MUTE_NOT_MUTED" = "Выкл.";
/* Label for button to mute a thread for a day. */
"CONVERSATION_SETTINGS_MUTE_ONE_DAY_ACTION" = "Беззвучный режим на 1 день";