Version 10.13

This commit is contained in:
Kylmakalle 2024-07-02 19:58:37 +03:00
parent 5e64c0ebd7
commit 851bbf76a3
634 changed files with 31000 additions and 1245 deletions

View File

@ -1,8 +1,8 @@
name: CI
on:
push:
branches: [ master ]
# push:
# branches: [ master ]
workflow_dispatch:

2
.gitignore vendored
View File

@ -65,3 +65,5 @@ xcodeproj.bazelrc
build-input/*
**/*.pyc
*.pyc
submodules/**/.build/*
swiftgram-scripts

5
.gitmodules vendored
View File

@ -1,7 +1,6 @@
[submodule "submodules/rlottie/rlottie"]
path = submodules/rlottie/rlottie
url=../rlottie.git
url=https://github.com/TelegramMessenger/rlottie.git
[submodule "build-system/bazel-rules/rules_apple"]
path = build-system/bazel-rules/rules_apple
url=https://github.com/ali-fareed/rules_apple.git
@ -19,7 +18,7 @@ url=https://github.com/bazelbuild/rules_swift.git
url=https://github.com/bazelbuild/tulsi.git
[submodule "submodules/TgVoipWebrtc/tgcalls"]
path = submodules/TgVoipWebrtc/tgcalls
url=../tgcalls.git
url=https://github.com/TelegramMessenger/tgcalls.git
[submodule "third-party/libvpx/libvpx"]
path = third-party/libvpx/libvpx
url = https://github.com/webmproject/libvpx.git

View File

@ -1,3 +1,16 @@
# Swiftgram
Supercharged Telegram fork for iOS
[<img src="https://developer.apple.com/assets/elements/badges/download-on-the-app-store.svg" height="50">](https://apps.apple.com/app/apple-store/id6471879502?pt=126511626&ct=gh&mt=8)
- Download: [App Store](https://apps.apple.com/app/apple-store/id6471879502?pt=126511626&ct=gh&mt=8)
- Telegram channel: https://t.me/swiftgram
- Telegram chat: https://t.me/swiftgramchat
- TestFlight beta, local chats, translations and other [@SwiftgramLinks](https://t.me/s/SwiftgramLinks)
Swiftgram's compilation steps are the same as for the official app. Below you'll find a complete compilation guide based on the official app.
# Telegram iOS Source Code Compilation Guide
We welcome all developers to use our API and source code to create applications on our platform.
@ -16,7 +29,7 @@ There are several things we require from **all developers** for the moment.
## Get the Code
```
git clone --recursive -j8 https://github.com/TelegramMessenger/Telegram-iOS.git
git clone --recursive -j8 https://github.com/Swiftgram/Telegram-iOS.git
```
## Setup Xcode
@ -29,7 +42,7 @@ Install Xcode (directly from https://developer.apple.com/download/applications o
```
openssl rand -hex 8
```
2. Create a new Xcode project. Use `Telegram` as the Product Name. Use `org.{identifier from step 1}` as the Organization Identifier.
2. Create a new Xcode project. Use `Swiftgram` as the Product Name. Use `org.{identifier from step 1}` as the Organization Identifier.
3. Open `Keychain Access` and navigate to `Certificates`. Locate `Apple Development: your@email.address (XXXXXXXXXX)` and double tap the certificate. Under `Details`, locate `Organizational Unit`. This is the Team ID.
4. Edit `build-system/template_minimal_development_configuration.json`. Use data from the previous steps.

View File

@ -0,0 +1,9 @@
filegroup(
name = "AppleStyleFolders",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
filegroup(
name = "ChatControllerImplExtension",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,225 @@
import SGSimpleSettings
import Foundation
import UIKit
import Postbox
import SwiftSignalKit
import Display
import AsyncDisplayKit
import TelegramCore
import SafariServices
import MobileCoreServices
import Intents
import LegacyComponents
import TelegramPresentationData
import TelegramUIPreferences
import DeviceAccess
import TextFormat
import TelegramBaseController
import AccountContext
import TelegramStringFormatting
import OverlayStatusController
import DeviceLocationManager
import ShareController
import UrlEscaping
import ContextUI
import ComposePollUI
import AlertUI
import PresentationDataUtils
import UndoUI
import TelegramCallsUI
import TelegramNotices
import GameUI
import ScreenCaptureDetection
import GalleryUI
import OpenInExternalAppUI
import LegacyUI
import InstantPageUI
import LocationUI
import BotPaymentsUI
import DeleteChatPeerActionSheetItem
import HashtagSearchUI
import LegacyMediaPickerUI
import Emoji
import PeerAvatarGalleryUI
import PeerInfoUI
import RaiseToListen
import UrlHandling
import AvatarNode
import AppBundle
import LocalizedPeerData
import PhoneNumberFormat
import SettingsUI
import UrlWhitelist
import TelegramIntents
import TooltipUI
import StatisticsUI
import MediaResources
import GalleryData
import ChatInterfaceState
import InviteLinksUI
import Markdown
import TelegramPermissionsUI
import Speak
import TranslateUI
import UniversalMediaPlayer
import WallpaperBackgroundNode
import ChatListUI
import CalendarMessageScreen
import ReactionSelectionNode
import ReactionListContextMenuContent
import AttachmentUI
import AttachmentTextInputPanelNode
import MediaPickerUI
import ChatPresentationInterfaceState
import Pasteboard
import ChatSendMessageActionUI
import ChatTextLinkEditUI
import WebUI
import PremiumUI
import ImageTransparency
import StickerPackPreviewUI
import TextNodeWithEntities
import EntityKeyboard
import ChatTitleView
import EmojiStatusComponent
import ChatTimerScreen
import MediaPasteboardUI
import ChatListHeaderComponent
import ChatControllerInteraction
import FeaturedStickersScreen
import ChatEntityKeyboardInputNode
import StorageUsageScreen
import AvatarEditorScreen
import ChatScheduleTimeController
import ICloudResources
import StoryContainerScreen
import MoreHeaderButton
import VolumeButtons
import ChatAvatarNavigationNode
import ChatContextQuery
import PeerReportScreen
import PeerSelectionController
import SaveToCameraRoll
import ChatMessageDateAndStatusNode
import ReplyAccessoryPanelNode
import TextSelectionNode
import ChatMessagePollBubbleContentNode
import ChatMessageItem
import ChatMessageItemImpl
import ChatMessageItemView
import ChatMessageItemCommon
import ChatMessageAnimatedStickerItemNode
import ChatMessageBubbleItemNode
import ChatNavigationButton
import WebsiteType
import ChatQrCodeScreen
import PeerInfoScreen
import MediaEditorScreen
import WallpaperGalleryScreen
import WallpaperGridScreen
import VideoMessageCameraScreen
import TopMessageReactions
import AudioWaveform
import PeerNameColorScreen
import ChatEmptyNode
import ChatMediaInputStickerGridItem
import AdsInfoScreen
extension ChatControllerImpl {
func forwardMessagesToCloud(messageIds: [MessageId], removeNames: Bool, openCloud: Bool, resetCurrent: Bool = false) {
let _ = (self.context.engine.data.get(EngineDataMap(
messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init)
))
|> deliverOnMainQueue).startStandalone(next: { [weak self] messages in
guard let strongSelf = self else {
return
}
if resetCurrent {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withoutSelectionState() }) })
}
let sortedMessages = messages.values.compactMap { $0?._asMessage() }.sorted { lhs, rhs in
return lhs.id < rhs.id
}
var attributes: [MessageAttribute] = []
if removeNames {
attributes.append(ForwardOptionsMessageAttribute(hideNames: true, hideCaptions: false))
}
if !openCloud {
Queue.mainQueue().after(0.88) {
strongSelf.chatDisplayNode.hapticFeedback.success()
}
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] value in
if case .info = value, let strongSelf = self {
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.context.account.peerId))
|> deliverOnMainQueue).startStandalone(next: { peer in
guard let strongSelf = self, let peer = peer, let navigationController = strongSelf.effectiveNavigationController else {
return
}
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil))
})
return true
}
return false
}), in: .current)
}
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.context.account.peerId, messages: sortedMessages.map { message -> EnqueueMessage in
return .forward(source: message.id, threadId: nil, grouping: .auto, attributes: attributes, correlationId: nil)
})
|> deliverOnMainQueue).startStandalone(next: { messageIds in
guard openCloud else {
return
}
if let strongSelf = self {
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
guard let id = id else {
return nil
}
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
if status != nil {
return .never()
} else {
return .single(true)
}
}
|> take(1)
})
if strongSelf.shareStatusDisposable == nil {
strongSelf.shareStatusDisposable = MetaDisposable()
}
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|> deliverOnMainQueue).startStrict(next: { [weak strongSelf] _ in
guard let strongSelf = strongSelf else {
return
}
strongSelf.chatDisplayNode.hapticFeedback.success()
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.context.account.peerId))
|> deliverOnMainQueue).startStandalone(next: { [weak strongSelf] peer in
guard let strongSelf = strongSelf, let peer = peer, let navigationController = strongSelf.effectiveNavigationController else {
return
}
var navigationSubject: ChatControllerSubject? = nil
for messageId in messageIds {
if let messageId = messageId {
navigationSubject = .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil)
break
}
}
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: navigationSubject, keepStack: .always, purposefulAction: {}, peekData: nil))
})
} ))
}
})
})
}
}

0
Swiftgram/FLEX/BUILD Normal file
View File

68
Swiftgram/FLEX/FLEX.BUILD Normal file
View File

@ -0,0 +1,68 @@
objc_library(
name = "FLEX",
module_name = "FLEX",
srcs = glob(
["Classes/**/*"],
exclude = [
"Classes/Info.plist",
"Classes/Utility/APPLE_LICENSE",
"Classes/Network/OSCache/LICENSE.md",
"Classes/Network/PonyDebugger/LICENSE",
"Classes/GlobalStateExplorers/DatabaseBrowser/LICENSE",
"Classes/GlobalStateExplorers/Keychain/SSKeychain_LICENSE",
"Classes/GlobalStateExplorers/SystemLog/LLVM_LICENSE.TXT",
]
),
hdrs = glob([
"Classes/**/*.h"
]),
includes = [
"Classes",
"Classes/Core",
"Classes/Core/Controllers",
"Classes/Core/Views",
"Classes/Core/Views/Cells",
"Classes/Core/Views/Carousel",
"Classes/ObjectExplorers",
"Classes/ObjectExplorers/Sections",
"Classes/ObjectExplorers/Sections/Shortcuts",
"Classes/Network",
"Classes/Network/PonyDebugger",
"Classes/Network/OSCache",
"Classes/Toolbar",
"Classes/Manager",
"Classes/Manager/Private",
"Classes/Editing",
"Classes/Editing/ArgumentInputViews",
"Classes/Headers",
"Classes/ExplorerInterface",
"Classes/ExplorerInterface/Tabs",
"Classes/ExplorerInterface/Bookmarks",
"Classes/GlobalStateExplorers",
"Classes/GlobalStateExplorers/Globals",
"Classes/GlobalStateExplorers/Keychain",
"Classes/GlobalStateExplorers/FileBrowser",
"Classes/GlobalStateExplorers/SystemLog",
"Classes/GlobalStateExplorers/DatabaseBrowser",
"Classes/GlobalStateExplorers/RuntimeBrowser",
"Classes/GlobalStateExplorers/RuntimeBrowser/DataSources",
"Classes/ViewHierarchy",
"Classes/ViewHierarchy/SnapshotExplorer",
"Classes/ViewHierarchy/SnapshotExplorer/Scene",
"Classes/ViewHierarchy/TreeExplorer",
"Classes/Utility",
"Classes/Utility/Runtime",
"Classes/Utility/Runtime/Objc",
"Classes/Utility/Runtime/Objc/Reflection",
"Classes/Utility/Categories",
"Classes/Utility/Categories/Private",
"Classes/Utility/Keyboard"
],
copts = [
"-Wno-deprecated-declarations",
"-Wno-strict-prototypes",
"-Wno-unsupported-availability-guard",
],
deps = [],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,17 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SFSafariViewControllerPlus",
module_name = "SFSafariViewControllerPlus",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,14 @@
import SafariServices
public class SFSafariViewControllerPlusDidFinish: SFSafariViewController, SFSafariViewControllerDelegate {
public var onDidFinish: (() -> Void)?
public override init(url URL: URL, configuration: SFSafariViewController.Configuration = SFSafariViewController.Configuration()) {
super.init(url: URL, configuration: configuration)
self.delegate = self
}
public func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
onDidFinish?()
}
}

25
Swiftgram/SGAPI/BUILD Normal file
View File

@ -0,0 +1,25 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGAPI",
module_name = "SGAPI",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//Swiftgram/SGLogging:SGLogging",
"//Swiftgram/SGWebAppExtensions:SGWebAppExtensions",
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
"//Swiftgram/SGWebSettingsScheme:SGWebSettingsScheme",
"//Swiftgram/SGRegDateScheme:SGRegDateScheme",
"//Swiftgram/SGRequests:SGRequests",
"//Swiftgram/SGConfig:SGConfig"
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,145 @@
import Foundation
import SwiftSignalKit
import SGConfig
import SGLogging
import SGSimpleSettings
import SGWebAppExtensions
import SGWebSettingsScheme
import SGRequests
import SGRegDateScheme
private let API_VERSION: String = "0"
private func buildApiUrl(_ endpoint: String) -> String {
return "\(SG_CONFIG.apiUrl)/v\(API_VERSION)/\(endpoint)"
}
public let SG_API_AUTHORIZATION_HEADER = "Authorization"
public let SG_API_DEVICE_TOKEN_HEADER = "Device-Token"
private enum HTTPRequestError {
case network
}
public enum SGAPIError {
case generic(String? = nil)
}
public func getSGSettings(token: String) -> Signal<SGWebSettings, SGAPIError> {
return Signal { subscriber in
let url = URL(string: buildApiUrl("settings"))!
let headers = [SG_API_AUTHORIZATION_HEADER: "Token \(token)"]
let completed = Atomic<Bool>(value: false)
var request = URLRequest(url: url)
headers.forEach { key, value in
request.addValue(value, forHTTPHeaderField: key)
}
let downloadSignal = requestsCustom(request: request).start(next: { data, urlResponse in
let _ = completed.swap(true)
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let settings = try decoder.decode(SGWebSettings.self, from: data)
subscriber.putNext(settings)
subscriber.putCompletion()
} catch {
subscriber.putError(.generic("Can't parse user settings: \(error). Response: \(String(data: data, encoding: .utf8) ?? "")"))
}
}, error: { error in
subscriber.putError(.generic("Error requesting user settings: \(String(describing: error))"))
})
return ActionDisposable {
if !completed.with({ $0 }) {
downloadSignal.dispose()
}
}
}
}
public func postSGSettings(token: String, data: [String:Any]) -> Signal<Void, SGAPIError> {
return Signal { subscriber in
let url = URL(string: buildApiUrl("settings"))!
let headers = [SG_API_AUTHORIZATION_HEADER: "Token \(token)"]
let completed = Atomic<Bool>(value: false)
var request = URLRequest(url: url)
headers.forEach { key, value in
request.addValue(value, forHTTPHeaderField: key)
}
request.httpMethod = "POST"
let jsonData = try? JSONSerialization.data(withJSONObject: data, options: [])
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
let dataSignal = requestsCustom(request: request).start(next: { data, urlResponse in
let _ = completed.swap(true)
if let httpResponse = urlResponse as? HTTPURLResponse {
switch httpResponse.statusCode {
case 200...299:
subscriber.putCompletion()
default:
subscriber.putError(.generic("Can't update settings: \(httpResponse.statusCode). Response: \(String(data: data, encoding: .utf8) ?? "")"))
}
} else {
subscriber.putError(.generic("Not an HTTP response: \(String(describing: urlResponse))"))
}
}, error: { error in
subscriber.putError(.generic("Error updating settings: \(String(describing: error))"))
})
return ActionDisposable {
if !completed.with({ $0 }) {
dataSignal.dispose()
}
}
}
}
public func getSGAPIRegDate(token: String, deviceToken: String, userId: Int64) -> Signal<RegDate, SGAPIError> {
return Signal { subscriber in
let url = URL(string: buildApiUrl("regdate/\(userId)"))!
let headers = [
SG_API_AUTHORIZATION_HEADER: "Token \(token)",
SG_API_DEVICE_TOKEN_HEADER: deviceToken
]
let completed = Atomic<Bool>(value: false)
var request = URLRequest(url: url)
headers.forEach { key, value in
request.addValue(value, forHTTPHeaderField: key)
}
request.timeoutInterval = 10
let downloadSignal = requestsCustom(request: request).start(next: { data, urlResponse in
let _ = completed.swap(true)
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let settings = try decoder.decode(RegDate.self, from: data)
subscriber.putNext(settings)
subscriber.putCompletion()
} catch {
subscriber.putError(.generic("Can't parse regDate: \(error). Response: \(String(data: data, encoding: .utf8) ?? "")"))
}
}, error: { error in
subscriber.putError(.generic("Error requesting regDate: \(String(describing: error))"))
})
return ActionDisposable {
if !completed.with({ $0 }) {
downloadSignal.dispose()
}
}
}
}

View File

@ -0,0 +1,24 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGAPIToken",
module_name = "SGAPIToken",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramCore:TelegramCore",
"//Swiftgram/SGLogging:SGLogging",
"//Swiftgram/SGWebSettingsScheme:SGWebSettingsScheme",
"//Swiftgram/SGConfig:SGConfig",
"//Swiftgram/SGWebAppExtensions:SGWebAppExtensions",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,133 @@
import Foundation
import SwiftSignalKit
import AccountContext
import TelegramCore
import SGLogging
import SGConfig
import SGWebAppExtensions
private let tokenExpirationTime: TimeInterval = 30 * 60 // 30 minutes
private var tokenCache: [Int64: (token: String, expiration: Date)] = [:]
public enum SGAPITokenError {
case generic(String? = nil)
}
public func getSGApiToken(context: AccountContext, botUsername: String = SG_CONFIG.botUsername) -> Signal<String, SGAPITokenError> {
let userId = context.account.peerId.id._internalGetInt64Value()
if let (token, expiration) = tokenCache[userId], Date() < expiration {
// SGLogger.shared.log("SGAPI", "Using cached token. Expiring at: \(expiration)")
return Signal { subscriber in
subscriber.putNext(token)
subscriber.putCompletion()
return EmptyDisposable
}
}
SGLogger.shared.log("SGAPI", "Requesting new token")
// Workaround for Apple Review
if context.account.testingEnvironment {
return context.account.postbox.transaction { transaction -> String? in
if let testUserPeer = transaction.getPeer(context.account.peerId) as? TelegramUser, let testPhone = testUserPeer.phone {
return testPhone
} else {
return nil
}
}
|> mapToSignalPromotingError { phone -> Signal<String, SGAPITokenError> in
if let phone = phone {
// https://core.telegram.org/api/auth#test-accounts
if phone.starts(with: String(99966)) {
SGLogger.shared.log("SGAPI", "Using demo token")
tokenCache[userId] = (phone, Date().addingTimeInterval(tokenExpirationTime))
return .single(phone)
} else {
return .fail(.generic("Non-demo phone number on test DC"))
}
} else {
return .fail(.generic("Missing test account peer or it's number (how?)"))
}
}
}
return Signal { subscriber in
let getSettingsURLSignal = getSGSettingsURL(context: context, botUsername: botUsername).start(next: { url in
if let hashPart = url.components(separatedBy: "#").last {
let parsedParams = urlParseHashParams(hashPart)
if let token = parsedParams["tgWebAppData"], let token = token {
tokenCache[userId] = (token, Date().addingTimeInterval(tokenExpirationTime))
#if DEBUG
print("[SGAPI]", "API Token: \(token)")
#endif
subscriber.putNext(token)
subscriber.putCompletion()
} else {
subscriber.putError(.generic("Invalid or missing token in response url! \(url)"))
}
} else {
subscriber.putError(.generic("No hash part in URL \(url)"))
}
})
return ActionDisposable {
getSettingsURLSignal.dispose()
}
}
}
public func getSGSettingsURL(context: AccountContext, botUsername: String = SG_CONFIG.botUsername, url: String = SG_CONFIG.webappUrl, themeParams: [String: Any]? = nil) -> Signal<String, SGAPITokenError> {
return Signal { subscriber in
// themeParams = generateWebAppThemeParams(
// context.sharedContext.currentPresentationData.with { $0 }.theme
// )
var requestWebViewSignalDisposable: Disposable? = nil
var requestUpdatePeerIsBlocked: Disposable? = nil
let resolvePeerSignal = (
context.engine.peers.resolvePeerByName(name: botUsername)
|> mapToSignal { result -> Signal<EnginePeer?, NoError> in
guard case let .result(result) = result else {
return .complete()
}
return .single(result)
}).start(next: { botPeer in
if let botPeer = botPeer {
SGLogger.shared.log("SGAPI", "Botpeer found for \(botUsername)")
let requestWebViewSignal = context.engine.messages.requestWebView(peerId: botPeer.id, botId: botPeer.id, url: url, payload: nil, themeParams: themeParams, fromMenu: true, replyToMessageId: nil, threadId: nil)
requestWebViewSignalDisposable = requestWebViewSignal.start(next: { webViewResult in
subscriber.putNext(webViewResult.url)
subscriber.putCompletion()
}, error: { e in
SGLogger.shared.log("SGAPI", "Webview request error, retrying with unblock")
// if e.errorDescription == "YOU_BLOCKED_USER" {
requestUpdatePeerIsBlocked = (context.engine.privacy.requestUpdatePeerIsBlocked(peerId: botPeer.id, isBlocked: false)
|> afterDisposed(
{
requestWebViewSignalDisposable?.dispose()
requestWebViewSignalDisposable = requestWebViewSignal.start(next: { webViewResult in
SGLogger.shared.log("SGAPI", "Webview retry success \(webViewResult)")
subscriber.putNext(webViewResult.url)
subscriber.putCompletion()
}, error: { e in
SGLogger.shared.log("SGAPI", "Webview retry failure \(e)")
subscriber.putError(.generic("Webview retry failure \(e)"))
})
})).start()
// }
})
} else {
SGLogger.shared.log("SGAPI", "Botpeer not found for \(botUsername)")
subscriber.putError(.generic())
}
})
return ActionDisposable {
resolvePeerSignal.dispose()
requestUpdatePeerIsBlocked?.dispose()
requestWebViewSignalDisposable?.dispose()
}
}
}

View File

@ -0,0 +1,23 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGAPIWebSettings",
module_name = "SGAPIWebSettings",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//Swiftgram/SGAPI:SGAPI",
"//Swiftgram/SGAPIToken:SGAPIToken",
"//Swiftgram/SGLogging:SGLogging",
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramCore:TelegramCore",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,49 @@
import Foundation
import SGAPIToken
import SGAPI
import SGLogging
import AccountContext
import SGSimpleSettings
import TelegramCore
public func updateSGWebSettingsInteractivelly(context: AccountContext) {
let _ = getSGApiToken(context: context).startStandalone(next: { token in
let _ = getSGSettings(token: token).startStandalone(next: { webSettings in
SGLogger.shared.log("SGAPI", "New SGWebSettings for id \(context.account.peerId.id._internalGetInt64Value()): \(webSettings) ")
SGSimpleSettings.shared.canUseStealthMode = webSettings.global.storiesAvailable
let _ = (context.account.postbox.transaction { transaction in
updateAppConfiguration(transaction: transaction, { configuration -> AppConfiguration in
var configuration = configuration
configuration.sgWebSettings = webSettings
return configuration
})
}).startStandalone()
}, error: { e in
if case let .generic(errorMessage) = e, let errorMessage = errorMessage {
SGLogger.shared.log("SGAPI", errorMessage)
}
})
}, error: { e in
if case let .generic(errorMessage) = e, let errorMessage = errorMessage {
SGLogger.shared.log("SGAPI", errorMessage)
}
})
}
public func postSGWebSettingsInteractivelly(context: AccountContext, data: [String: Any]) {
let _ = getSGApiToken(context: context).startStandalone(next: { token in
let _ = postSGSettings(token: token, data: data).startStandalone(error: { e in
if case let .generic(errorMessage) = e, let errorMessage = errorMessage {
SGLogger.shared.log("SGAPI", errorMessage)
}
})
}, error: { e in
if case let .generic(errorMessage) = e, let errorMessage = errorMessage {
SGLogger.shared.log("SGAPI", errorMessage)
}
})
}

View File

@ -0,0 +1,17 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGActionRequestHandlerSanitizer",
module_name = "SGActionRequestHandlerSanitizer",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,15 @@
import Foundation
public func sgActionRequestHandlerSanitizer(_ url: URL) -> URL {
var url = url
if let scheme = url.scheme {
let openInPrefix = "\(scheme)://parseurl?url="
let urlString = url.absoluteString
if urlString.hasPrefix(openInPrefix) {
if let unwrappedUrlString = String(urlString.dropFirst(openInPrefix.count)).removingPercentEncoding, let newUrl = URL(string: unwrappedUrlString) {
url = newUrl
}
}
}
return url
}

18
Swiftgram/SGConfig/BUILD Normal file
View File

@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGConfig",
module_name = "SGConfig",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/BuildConfig:BuildConfig"
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,20 @@
import Foundation
import BuildConfig
public struct SGConfig: Codable {
public var apiUrl: String = "https://api.swiftgram.app"
public var webappUrl: String = "https://my.swiftgram.app"
public var botUsername: String = "SwiftgramBot"
}
private func parseSGConfig(_ jsonString: String) -> SGConfig {
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return (try? decoder.decode(SGConfig.self, from: jsonData)) ?? SGConfig()
}
private let baseAppBundleId = Bundle.main.bundleIdentifier!
private let buildConfig = BuildConfig(baseAppBundleId: baseAppBundleId)
public let SG_CONFIG: SGConfig = parseSGConfig(buildConfig.sgConfig)
public let SG_API_WEBAPP_URL_PARSED = URL(string: SG_CONFIG.webappUrl)!

View File

@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGContentAnalysis",
module_name = "SGContentAnalysis",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,64 @@
import SensitiveContentAnalysis
import SwiftSignalKit
public enum ContentAnalysisError: Error {
case generic(_ message: String)
}
public enum ContentAnalysisMediaType {
case image
case video
}
public func canAnalyzeMedia() -> Bool {
if #available(iOS 17, *) {
let analyzer = SCSensitivityAnalyzer()
let policy = analyzer.analysisPolicy
return policy != .disabled
} else {
return false
}
}
public func analyzeMediaSignal(_ url: URL, mediaType: ContentAnalysisMediaType = .image) -> Signal<Bool, Error> {
return Signal { subscriber in
analyzeMedia(url: url, mediaType: mediaType, completion: { result, error in
if let result = result {
subscriber.putNext(result)
subscriber.putCompletion()
} else if let error = error {
subscriber.putError(error)
} else {
subscriber.putError(ContentAnalysisError.generic("Unknown response"))
}
})
return ActionDisposable {
}
}
}
private func analyzeMedia(url: URL, mediaType: ContentAnalysisMediaType, completion: @escaping (Bool?, Error?) -> Void) {
if #available(iOS 17, *) {
let analyzer = SCSensitivityAnalyzer()
switch mediaType {
case .image:
analyzer.analyzeImage(at: url) { analysisResult, analysisError in
completion(analysisResult?.isSensitive, analysisError)
}
case .video:
Task {
do {
let handler = analyzer.videoAnalysis(forFileAt: url)
let response = try await handler.hasSensitiveContent()
completion(response.isSensitive, nil)
} catch {
completion(nil, error)
}
}
}
} else {
completion(false, nil)
}
}

View File

@ -0,0 +1,9 @@
filegroup(
name = "SGDBReset",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,47 @@
import UIKit
import Foundation
import SGLogging
private let dbResetKey = "sg_db_reset"
public func sgDBResetIfNeeded(databasePath: String, present: ((UIViewController) -> ())?) {
guard UserDefaults.standard.bool(forKey: dbResetKey) else {
return
}
NSLog("[SG.DBReset] Resetting DB with system settings")
let alert = UIAlertController(
title: "Database reset.\nPlease wait...",
message: nil,
preferredStyle: .alert
)
present?(alert)
do {
let _ = try FileManager.default.removeItem(atPath: databasePath)
NSLog("[SG.DBReset] Done. Reset completed")
let successAlert = UIAlertController(
title: "Database reset completed",
message: nil,
preferredStyle: .alert
)
successAlert.addAction(UIAlertAction(title: "Restart App", style: .cancel) { _ in
exit(0)
})
successAlert.addAction(UIAlertAction(title: "OK", style: .default))
alert.dismiss(animated: false) {
present?(successAlert)
}
} catch {
NSLog("[SG.DBReset] ERROR. Failed to reset database: \(error)")
let failAlert = UIAlertController(
title: "ERROR. Failed to reset database",
message: "\(error)",
preferredStyle: .alert
)
alert.dismiss(animated: false) {
present?(failAlert)
}
}
UserDefaults.standard.set(false, forKey: dbResetKey)
// let semaphore = DispatchSemaphore(value: 0)
// semaphore.wait()
}

46
Swiftgram/SGDebugUI/BUILD Normal file
View File

@ -0,0 +1,46 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
config_setting(
name = "debug_build",
values = {
"compilation_mode": "dbg",
},
)
flex_dependency = select({
":debug_build": [
"@flex_sdk//:FLEX"
],
"//conditions:default": [],
})
swift_library(
name = "SGDebugUI",
module_name = "SGDebugUI",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//Swiftgram/SGItemListUI:SGItemListUI",
"//Swiftgram/SGLogging:SGLogging",
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
"//Swiftgram/SGStrings:SGStrings",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Postbox:Postbox",
"//submodules/Display:Display",
"//submodules/TelegramCore:TelegramCore",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/ItemListUI:ItemListUI",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/AccountContext:AccountContext",
"//submodules/UndoUI:UndoUI",
] + flex_dependency,
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,105 @@
import Foundation
import SGItemListUI
import UndoUI
import AccountContext
import Display
import TelegramCore
import ItemListUI
import SwiftSignalKit
import TelegramPresentationData
import PresentationDataUtils
// Optional
import SGSimpleSettings
import SGLogging
import OverlayStatusController
#if DEBUG
import FLEX
#endif
private enum SGDebugControllerSection: Int32, SGItemListSection {
case base
}
private enum SGDebugActions: String {
case flexing
case clearRegDateCache
}
private typealias SGDebugControllerEntry = SGItemListUIEntry<SGDebugControllerSection, AnyHashable, AnyHashable, AnyHashable, AnyHashable, SGDebugActions>
private func SGDebugControllerEntries(presentationData: PresentationData) -> [SGDebugControllerEntry] {
var entries: [SGDebugControllerEntry] = []
let id = SGItemListCounter()
#if DEBUG
entries.append(.action(id: id.count, section: .base, actionType: .flexing, text: "FLEX", kind: .generic))
#endif
entries.append(.action(id: id.count, section: .base, actionType: .clearRegDateCache, text: "Clear Regdate cache", kind: .generic))
return entries
}
private func okUndoController(_ text: String, _ presentationData: PresentationData) -> UndoOverlayController {
return UndoOverlayController(presentationData: presentationData, content: .succeed(text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false })
}
public func sgDebugController(context: AccountContext) -> ViewController {
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
let simplePromise = ValuePromise(true, ignoreRepeated: false)
let arguments = SGItemListArguments<AnyHashable, AnyHashable, AnyHashable, AnyHashable, SGDebugActions>(context: context, action: { actionType in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
switch actionType {
case .clearRegDateCache:
SGLogger.shared.log("SGDebug", "Regdate cache cleanup init")
/*
let spinner = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(spinner, nil)
*/
SGSimpleSettings.shared.regDateCache.drop()
SGLogger.shared.log("SGDebug", "Regdate cache cleanup succesfull")
presentControllerImpl?(okUndoController("OK: Regdate cache cleaned", presentationData), nil)
/*
Queue.mainQueue().async() { [weak spinner] in
spinner?.dismiss()
}
*/
case .flexing:
#if DEBUG
FLEXManager.shared.toggleExplorer()
#endif
}
})
let signal = combineLatest(context.sharedContext.presentationData, simplePromise.get())
|> map { presentationData, _ -> (ItemListControllerState, (ItemListNodeState, Any)) in
let entries = SGDebugControllerEntries(presentationData: presentationData)
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Swiftgram Debug"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, ensureVisibleItemTag: /*focusOnItemTag*/ nil, initialScrollToItem: nil /* scrollToItem*/ )
return (controllerState, (listState, arguments))
}
let controller = ItemListController(context: context, state: signal)
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushControllerImpl = { [weak controller] c in
(controller?.navigationController as? NavigationController)?.pushViewController(c)
}
// Workaround
let _ = pushControllerImpl
return controller
}

View File

@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGDeviceToken",
module_name = "SGDeviceToken",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,31 @@
import SwiftSignalKit
import DeviceCheck
public enum SGDeviceTokenError {
case unsupportedDevice
case generic(String)
}
public func getDeviceToken() -> Signal<String, SGDeviceTokenError> {
return Signal { subscriber in
let currentDevice = DCDevice.current
if currentDevice.isSupported {
currentDevice.generateToken { (data, error) in
guard error == nil else {
subscriber.putError(.generic(error!.localizedDescription))
return
}
if let tokenData = data {
subscriber.putNext(tokenData.base64EncodedString())
subscriber.putCompletion()
} else {
subscriber.putError(.generic("Empty Token"))
}
}
} else {
subscriber.putError(.unsupportedDevice)
}
return ActionDisposable {
}
}
}

View File

@ -0,0 +1,9 @@
filegroup(
name = "SGDoubleTapMessageAction",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,13 @@
import Foundation
import SGSimpleSettings
import Postbox
import TelegramCore
func sgDoubleTapMessageAction(incoming: Bool, message: Message) -> String {
if incoming {
return SGSimpleSettings.MessageDoubleTapAction.default.rawValue
} else {
return SGSimpleSettings.shared.messageDoubleTapActionOutgoing
}
}

View File

@ -0,0 +1,9 @@
filegroup(
name = "SGEmojiKeyboardDefaultFirst",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,23 @@
import Foundation
func sgPatchEmojiKeyboardItems(_ items: [EmojiPagerContentComponent.ItemGroup]) -> [EmojiPagerContentComponent.ItemGroup] {
var items = items
let staticEmojisIndex = items.firstIndex { item in
if let groupId = item.groupId.base as? String, groupId == "static" {
return true
}
return false
}
let recentEmojisIndex = items.firstIndex { item in
if let groupId = item.groupId.base as? String, groupId == "recent" {
return true
}
return false
}
if let staticEmojisIndex = staticEmojisIndex {
let staticEmojiItem = items.remove(at: staticEmojisIndex)
items.insert(staticEmojiItem, at: (recentEmojisIndex ?? -1) + 1 )
}
return items
}

View File

@ -0,0 +1,30 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGItemListUI",
module_name = "SGItemListUI",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Display:Display",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/MtProtoKit:MtProtoKit",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/ItemListUI:ItemListUI",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/AccountContext:AccountContext",
"//submodules/AppBundle:AppBundle",
"//submodules/TelegramUI/Components/Settings/PeerNameColorScreen",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,211 @@
// MARK: Swiftgram
import SGLogging
import SGSimpleSettings
import SGStrings
import SGAPIToken
import Foundation
import UIKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import MtProtoKit
import MessageUI
import TelegramPresentationData
import TelegramUIPreferences
import ItemListUI
import PresentationDataUtils
import OverlayStatusController
import AccountContext
import AppBundle
import WebKit
import PeerNameColorScreen
public class SGItemListCounter {
private var _count = 0
public init() {}
public var count: Int {
_count += 1
return _count
}
public func increment(_ amount: Int) {
_count += amount
}
public func countWith(_ amount: Int) -> Int {
_count += amount
return count
}
}
public protocol SGItemListSection: Equatable {
var rawValue: Int32 { get }
}
public final class SGItemListArguments<BoolSetting: Hashable, SliderSetting: Hashable, OneFromManySetting: Hashable, DisclosureLink: Hashable, ActionType: Hashable> {
let context: AccountContext
//
let setBoolValue: (BoolSetting, Bool) -> Void
let updateSliderValue: (SliderSetting, Int32) -> Void
let setOneFromManyValue: (OneFromManySetting) -> Void
let openDisclosureLink: (DisclosureLink) -> Void
let action: (ActionType) -> Void
public init(
context: AccountContext,
//
setBoolValue: @escaping (BoolSetting, Bool) -> Void = { _,_ in },
updateSliderValue: @escaping (SliderSetting, Int32) -> Void = { _,_ in },
setOneFromManyValue: @escaping (OneFromManySetting) -> Void = { _ in },
openDisclosureLink: @escaping (DisclosureLink) -> Void = { _ in},
action: @escaping (ActionType) -> Void = { _ in }
) {
self.context = context
//
self.setBoolValue = setBoolValue
self.updateSliderValue = updateSliderValue
self.setOneFromManyValue = setOneFromManyValue
self.openDisclosureLink = openDisclosureLink
self.action = action
}
}
public enum SGItemListUIEntry<Section: SGItemListSection, BoolSetting: Hashable, SliderSetting: Hashable, OneFromManySetting: Hashable, DisclosureLink: Hashable, ActionType: Hashable>: ItemListNodeEntry {
case header(id: Int, section: Section, text: String, badge: String?)
case toggle(id: Int, section: Section, settingName: BoolSetting, value: Bool, text: String, enabled: Bool)
case notice(id: Int, section: Section, text: String)
case percentageSlider(id: Int, section: Section, settingName: SliderSetting, value: Int32)
case oneFromManySelector(id: Int, section: Section, settingName: OneFromManySetting, text: String, value: String, enabled: Bool)
case disclosure(id: Int, section: Section, link: DisclosureLink, text: String)
case peerColorDisclosurePreview(id: Int, section: Section, name: String, color: UIColor)
case action(id: Int, section: Section, actionType: ActionType, text: String, kind: ItemListActionKind)
public var section: ItemListSectionId {
switch self {
case let .header(_, sectionId, _, _):
return sectionId.rawValue
case let .toggle(_, sectionId, _, _, _, _):
return sectionId.rawValue
case let .notice(_, sectionId, _):
return sectionId.rawValue
case let .disclosure(_, sectionId, _, _):
return sectionId.rawValue
case let .percentageSlider(_, sectionId, _, _):
return sectionId.rawValue
case let .peerColorDisclosurePreview(_, sectionId, _, _):
return sectionId.rawValue
case let .oneFromManySelector(_, sectionId, _, _, _, _):
return sectionId.rawValue
case let .action(_, sectionId, _, _, _):
return sectionId.rawValue
}
}
public var stableId: Int {
switch self {
case let .header(stableIdValue, _, _, _):
return stableIdValue
case let .toggle(stableIdValue, _, _, _, _, _):
return stableIdValue
case let .notice(stableIdValue, _, _):
return stableIdValue
case let .disclosure(stableIdValue, _, _, _):
return stableIdValue
case let .percentageSlider(stableIdValue, _, _, _):
return stableIdValue
case let .peerColorDisclosurePreview(stableIdValue, _, _, _):
return stableIdValue
case let .oneFromManySelector(stableIdValue, _, _, _, _, _):
return stableIdValue
case let .action(stableIdValue, _, _, _, _):
return stableIdValue
}
}
public static func <(lhs: SGItemListUIEntry, rhs: SGItemListUIEntry) -> Bool {
return lhs.stableId < rhs.stableId
}
public static func ==(lhs: SGItemListUIEntry, rhs: SGItemListUIEntry) -> Bool {
switch (lhs, rhs) {
case let (.header(id1, section1, text1, badge1), .header(id2, section2, text2, badge2)):
return id1 == id2 && section1 == section2 && text1 == text2 && badge1 == badge2
case let (.toggle(id1, section1, settingName1, value1, text1, enabled1), .toggle(id2, section2, settingName2, value2, text2, enabled2)):
return id1 == id2 && section1 == section2 && settingName1 == settingName2 && value1 == value2 && text1 == text2 && enabled1 == enabled2
case let (.notice(id1, section1, text1), .notice(id2, section2, text2)):
return id1 == id2 && section1 == section2 && text1 == text2
case let (.percentageSlider(id1, section1, settingName1, value1), .percentageSlider(id2, section2, settingName2, value2)):
return id1 == id2 && section1 == section2 && value1 == value2 && settingName1 == settingName2
case let (.disclosure(id1, section1, link1, text1), .disclosure(id2, section2, link2, text2)):
return id1 == id2 && section1 == section2 && link1 == link2 && text1 == text2
case let (.peerColorDisclosurePreview(id1, section1, name1, currentColor1), .peerColorDisclosurePreview(id2, section2, name2, currentColor2)):
return id1 == id2 && section1 == section2 && name1 == name2 && currentColor1 == currentColor2
case let (.oneFromManySelector(id1, section1, settingName1, text1, value1, enabled1), .oneFromManySelector(id2, section2, settingName2, text2, value2, enabled2)):
return id1 == id2 && section1 == section2 && settingName1 == settingName2 && text1 == text2 && value1 == value2 && enabled1 == enabled2
case let (.action(id1, section1, actionType1, text1, kind1), .action(id2, section2, actionType2, text2, kind2)):
return id1 == id2 && section1 == section2 && actionType1 == actionType2 && text1 == text2 && kind1 == kind2
default:
return false
}
}
public func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! SGItemListArguments<BoolSetting, SliderSetting, OneFromManySetting, DisclosureLink, ActionType>
switch self {
case let .header(_, _, string, badge):
return ItemListSectionHeaderItem(presentationData: presentationData, text: string, badge: badge, sectionId: self.section)
case let .toggle(_, _, setting, value, text, enabled):
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in
arguments.setBoolValue(setting, value)
})
case let .notice(_, _, string):
return ItemListTextItem(presentationData: presentationData, text: .markdown(string), sectionId: self.section)
case let .disclosure(_, _, link, text):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks) {
arguments.openDisclosureLink(link)
}
case let .percentageSlider(_, _, setting, value):
return SliderPercentageItem(
theme: presentationData.theme,
strings: presentationData.strings,
value: value,
sectionId: self.section,
updated: { value in
arguments.updateSliderValue(setting, value)
}
)
case let .peerColorDisclosurePreview(_, _, name, color):
return ItemListDisclosureItem(presentationData: presentationData, title: " ", enabled: false, label: name, labelStyle: .semitransparentBadge(color), centerLabelAlignment: true, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
})
case let .oneFromManySelector(_, _, settingName, text, value, enabled):
return ItemListDisclosureItem(presentationData: presentationData, title: text, enabled: enabled, label: value, sectionId: self.section, style: .blocks, action: {
arguments.setOneFromManyValue(settingName)
})
case let .action(_, _, actionType, text, kind):
return ItemListActionItem(presentationData: presentationData, title: text, kind: kind, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.action(actionType)
})
}
}
}

View File

@ -0,0 +1,353 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramCore
import TelegramPresentationData
import LegacyComponents
import ItemListUI
import PresentationDataUtils
import AppBundle
public class SliderPercentageItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let strings: PresentationStrings
let value: Int32
public let sectionId: ItemListSectionId
let updated: (Int32) -> Void
public init(theme: PresentationTheme, strings: PresentationStrings, value: Int32, sectionId: ItemListSectionId, updated: @escaping (Int32) -> Void) {
self.theme = theme
self.strings = strings
self.value = value
self.sectionId = sectionId
self.updated = updated
}
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
async {
let node = SliderPercentageItemNode()
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
node.contentSize = layout.contentSize
node.insets = layout.insets
Queue.mainQueue().async {
completion(node, {
return (nil, { _ in apply() })
})
}
}
}
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
Queue.mainQueue().async {
if let nodeValue = node() as? SliderPercentageItemNode {
let makeLayout = nodeValue.asyncLayout()
async {
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
Queue.mainQueue().async {
completion(layout, { _ in
apply()
})
}
}
}
}
}
}
private func rescalePercentageValueToSlider(_ value: CGFloat) -> CGFloat {
return max(0.0, min(1.0, value))
}
private func rescaleSliderValueToPercentageValue(_ value: CGFloat) -> CGFloat {
return max(0.0, min(1.0, value))
}
class SliderPercentageItemNode: ListViewItemNode {
private let backgroundNode: ASDisplayNode
private let topStripeNode: ASDisplayNode
private let bottomStripeNode: ASDisplayNode
private let maskNode: ASImageNode
private var sliderView: TGPhotoEditorSliderView?
private let leftTextNode: ImmediateTextNode
private let rightTextNode: ImmediateTextNode
private let centerTextNode: ImmediateTextNode
private let centerMeasureTextNode: ImmediateTextNode
private let batteryImage: UIImage?
private let batteryBackgroundNode: ASImageNode
private let batteryForegroundNode: ASImageNode
private var item: SliderPercentageItem?
private var layoutParams: ListViewItemLayoutParams?
// MARK: Swiftgram
private let activateArea: AccessibilityAreaNode
init() {
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
self.topStripeNode = ASDisplayNode()
self.topStripeNode.isLayerBacked = true
self.bottomStripeNode = ASDisplayNode()
self.bottomStripeNode.isLayerBacked = true
self.maskNode = ASImageNode()
self.leftTextNode = ImmediateTextNode()
self.rightTextNode = ImmediateTextNode()
self.centerTextNode = ImmediateTextNode()
self.centerMeasureTextNode = ImmediateTextNode()
self.batteryImage = nil //UIImage(bundleImageName: "Settings/UsageBatteryFrame")
self.batteryBackgroundNode = ASImageNode()
self.batteryForegroundNode = ASImageNode()
// MARK: Swiftgram
self.activateArea = AccessibilityAreaNode()
super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.leftTextNode)
self.addSubnode(self.rightTextNode)
self.addSubnode(self.centerTextNode)
self.addSubnode(self.batteryBackgroundNode)
self.addSubnode(self.batteryForegroundNode)
self.addSubnode(self.activateArea)
// MARK: Swiftgram
self.activateArea.increment = { [weak self] in
if let self {
self.sliderView?.increase(by: 0.10)
}
}
self.activateArea.decrement = { [weak self] in
if let self {
self.sliderView?.decrease(by: 0.10)
}
}
}
override func didLoad() {
super.didLoad()
let sliderView = TGPhotoEditorSliderView()
sliderView.enableEdgeTap = true
sliderView.enablePanHandling = true
sliderView.trackCornerRadius = 1.0
sliderView.lineSize = 4.0
sliderView.minimumValue = 0.0
sliderView.startValue = 0.0
sliderView.maximumValue = 1.0
sliderView.disablesInteractiveTransitionGestureRecognizer = true
sliderView.displayEdges = true
if let item = self.item, let params = self.layoutParams {
sliderView.value = rescalePercentageValueToSlider(CGFloat(item.value) / 100.0)
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
sliderView.backColor = item.theme.list.itemSwitchColors.frameColor
sliderView.trackColor = item.theme.list.itemAccentColor
sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
}
self.view.addSubview(sliderView)
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
self.sliderView = sliderView
}
func asyncLayout() -> (_ item: SliderPercentageItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
let currentItem = self.item
return { item, params, neighbors in
var themeUpdated = false
if currentItem?.theme !== item.theme {
themeUpdated = true
}
let contentSize: CGSize
let insets: UIEdgeInsets
let separatorHeight = UIScreenPixel
contentSize = CGSize(width: params.width, height: 88.0)
insets = itemListNeighborsGroupedInsets(neighbors, params)
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
let layoutSize = layout.size
return (layout, { [weak self] in
if let strongSelf = self {
strongSelf.item = item
strongSelf.layoutParams = params
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
if strongSelf.backgroundNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
}
if strongSelf.topStripeNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
}
if strongSelf.bottomStripeNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
}
if strongSelf.maskNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = itemListHasRoundedBlockLayout(params)
var hasTopCorners = false
var hasBottomCorners = false
switch neighbors.top {
case .sameSection(false):
strongSelf.topStripeNode.isHidden = true
default:
hasTopCorners = true
strongSelf.topStripeNode.isHidden = hasCorners
}
let bottomStripeInset: CGFloat
let bottomStripeOffset: CGFloat
switch neighbors.bottom {
case .sameSection(false):
bottomStripeInset = params.leftInset + 16.0
bottomStripeOffset = -separatorHeight
strongSelf.bottomStripeNode.isHidden = false
default:
bottomStripeInset = 0.0
bottomStripeOffset = 0.0
hasBottomCorners = true
strongSelf.bottomStripeNode.isHidden = hasCorners
}
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))
strongSelf.leftTextNode.attributedText = NSAttributedString(string: "0%", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "100%", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
let centralText: String = "\(item.value)%"
let centralMeasureText: String = centralText
strongSelf.batteryBackgroundNode.isHidden = true
strongSelf.batteryForegroundNode.isHidden = strongSelf.batteryBackgroundNode.isHidden
strongSelf.centerTextNode.attributedText = NSAttributedString(string: centralText, font: Font.regular(16.0), textColor: item.theme.list.itemPrimaryTextColor)
strongSelf.centerMeasureTextNode.attributedText = NSAttributedString(string: centralMeasureText, font: Font.regular(16.0), textColor: item.theme.list.itemPrimaryTextColor)
strongSelf.leftTextNode.isAccessibilityElement = true
strongSelf.leftTextNode.accessibilityLabel = "Minimum: \(Int32(rescaleSliderValueToPercentageValue(strongSelf.sliderView?.minimumValue ?? 0.0) * 100.0))%"
strongSelf.rightTextNode.isAccessibilityElement = true
strongSelf.rightTextNode.accessibilityLabel = "Maximum: \(Int32(rescaleSliderValueToPercentageValue(strongSelf.sliderView?.maximumValue ?? 1.0) * 100.0))%"
let leftTextSize = strongSelf.leftTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
let rightTextSize = strongSelf.rightTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
let centerTextSize = strongSelf.centerTextNode.updateLayout(CGSize(width: 200.0, height: 100.0))
let centerMeasureTextSize = strongSelf.centerMeasureTextNode.updateLayout(CGSize(width: 200.0, height: 100.0))
let sideInset: CGFloat = 18.0
strongSelf.leftTextNode.frame = CGRect(origin: CGPoint(x: params.leftInset + sideInset, y: 15.0), size: leftTextSize)
strongSelf.rightTextNode.frame = CGRect(origin: CGPoint(x: params.width - params.leftInset - sideInset - rightTextSize.width, y: 15.0), size: rightTextSize)
var centerFrame = CGRect(origin: CGPoint(x: floor((params.width - centerMeasureTextSize.width) / 2.0), y: 11.0), size: centerTextSize)
if !strongSelf.batteryBackgroundNode.isHidden {
centerFrame.origin.x -= 12.0
}
strongSelf.centerTextNode.frame = centerFrame
if let frameImage = strongSelf.batteryImage {
strongSelf.batteryBackgroundNode.image = generateImage(frameImage.size, rotatedContext: { size, context in
UIGraphicsPushContext(context)
context.clear(CGRect(origin: CGPoint(), size: size))
if let image = generateTintedImage(image: frameImage, color: item.theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.9)) {
image.draw(in: CGRect(origin: CGPoint(), size: size))
let contentRect = CGRect(origin: CGPoint(x: 3.0, y: (size.height - 9.0) * 0.5), size: CGSize(width: 20.8, height: 9.0))
context.addPath(UIBezierPath(roundedRect: contentRect, cornerRadius: 2.0).cgPath)
context.clip()
}
UIGraphicsPopContext()
})
strongSelf.batteryForegroundNode.image = generateImage(frameImage.size, rotatedContext: { size, context in
UIGraphicsPushContext(context)
context.clear(CGRect(origin: CGPoint(), size: size))
let contentRect = CGRect(origin: CGPoint(x: 3.0, y: (size.height - 9.0) * 0.5), size: CGSize(width: 20.8, height: 9.0))
context.addPath(UIBezierPath(roundedRect: contentRect, cornerRadius: 2.0).cgPath)
context.clip()
context.setFillColor(UIColor.white.cgColor)
context.addPath(UIBezierPath(roundedRect: CGRect(origin: contentRect.origin, size: CGSize(width: contentRect.width * CGFloat(item.value) / 100.0, height: contentRect.height)), cornerRadius: 1.0).cgPath)
context.fillPath()
UIGraphicsPopContext()
})
let batteryColor: UIColor
if item.value <= 20 {
batteryColor = UIColor(rgb: 0xFF3B30)
} else {
batteryColor = item.theme.list.itemSwitchColors.positiveColor
}
if strongSelf.batteryForegroundNode.layer.layerTintColor == nil {
strongSelf.batteryForegroundNode.layer.layerTintColor = batteryColor.cgColor
} else {
ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut).updateTintColor(layer: strongSelf.batteryForegroundNode.layer, color: batteryColor)
}
strongSelf.batteryBackgroundNode.frame = CGRect(origin: CGPoint(x: centerFrame.minX + centerMeasureTextSize.width + 4.0, y: floor(centerFrame.midY - frameImage.size.height * 0.5)), size: frameImage.size)
strongSelf.batteryForegroundNode.frame = strongSelf.batteryBackgroundNode.frame
}
if let sliderView = strongSelf.sliderView {
if themeUpdated {
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
sliderView.backColor = item.theme.list.itemSecondaryTextColor
sliderView.trackColor = item.theme.list.itemAccentColor.withAlphaComponent(0.45)
sliderView.knobImage = PresentationResourcesItemList.knobImage(item.theme)
}
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
}
strongSelf.activateArea.accessibilityLabel = "Slider"
strongSelf.activateArea.accessibilityValue = centralMeasureText
strongSelf.activateArea.accessibilityTraits = .adjustable
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
}
})
}
}
override func animateInsertion(_ currentTimestamp: Double, duration: Double, options: ListViewItemAnimationOptions) {
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
}
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
}
@objc func sliderValueChanged() {
guard let sliderView = self.sliderView else {
return
}
self.item?.updated(Int32(rescaleSliderValueToPercentageValue(sliderView.value) * 100.0))
}
}

19
Swiftgram/SGLogging/BUILD Normal file
View File

@ -0,0 +1,19 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGLogging",
module_name = "SGLogging",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/ManagedFile:ManagedFile"
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,236 @@
import Foundation
import SwiftSignalKit
import ManagedFile
private let queue = DispatchQueue(label: "app.swiftgram.ios.trace", qos: .utility)
private var sharedLogger: SGLogger?
private let binaryEventMarker: UInt64 = 0xcadebabef00dcafe
private func rootPathForBasePath(_ appGroupPath: String) -> String {
return appGroupPath + "/telegram-data"
}
public final class SGLogger {
private let queue = Queue(name: "app.swiftgram.ios.log", qos: .utility)
private let maxLength: Int = 2 * 1024 * 1024
private let maxShortLength: Int = 1 * 1024 * 1024
private let maxFiles: Int = 20
private let rootPath: String
private let basePath: String
private var file: (ManagedFile, Int)?
private var shortFile: (ManagedFile, Int)?
public static let sgLogsPath = "/logs/app-logs-sg"
public var logToFile: Bool = true
public var logToConsole: Bool = true
public var redactSensitiveData: Bool = true
public static func setSharedLogger(_ logger: SGLogger) {
sharedLogger = logger
}
public static var shared: SGLogger {
if let sharedLogger = sharedLogger {
return sharedLogger
} else {
print("SGLogger setup...")
guard let baseAppBundleId = Bundle.main.bundleIdentifier else {
print("Can't setup logger (1)!")
return SGLogger(rootPath: "", basePath: "")
}
let appGroupName = "group.\(baseAppBundleId)"
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
guard let appGroupUrl = maybeAppGroupUrl else {
print("Can't setup logger (2)!")
return SGLogger(rootPath: "", basePath: "")
}
let newRootPath = rootPathForBasePath(appGroupUrl.path)
let newLogsPath = newRootPath + sgLogsPath
let _ = try? FileManager.default.createDirectory(atPath: newLogsPath, withIntermediateDirectories: true, attributes: nil)
self.setSharedLogger(SGLogger(rootPath: newRootPath, basePath: newLogsPath))
if let sharedLogger = sharedLogger {
return sharedLogger
} else {
print("Can't setup logger (3)!")
return SGLogger(rootPath: "", basePath: "")
}
}
}
public init(rootPath: String, basePath: String) {
self.rootPath = rootPath
self.basePath = basePath
}
public func collectLogs(prefix: String? = nil) -> Signal<[(String, String)], NoError> {
return Signal { subscriber in
self.queue.async {
let logsPath: String
if let prefix = prefix {
logsPath = self.rootPath + prefix
} else {
logsPath = self.basePath
}
var result: [(Date, String, String)] = []
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: logsPath), includingPropertiesForKeys: [URLResourceKey.creationDateKey], options: []) {
for url in files {
if url.lastPathComponent.hasPrefix("log-") {
if let creationDate = (try? url.resourceValues(forKeys: Set([.creationDateKey])))?.creationDate {
result.append((creationDate, url.lastPathComponent, url.path))
}
}
}
}
result.sort(by: { $0.0 < $1.0 })
subscriber.putNext(result.map { ($0.1, $0.2) })
subscriber.putCompletion()
}
return EmptyDisposable
}
}
public func collectLogs(basePath: String) -> Signal<[(String, String)], NoError> {
return Signal { subscriber in
self.queue.async {
let logsPath: String = basePath
var result: [(Date, String, String)] = []
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: logsPath), includingPropertiesForKeys: [URLResourceKey.creationDateKey], options: []) {
for url in files {
if url.lastPathComponent.hasPrefix("log-") {
if let creationDate = (try? url.resourceValues(forKeys: Set([.creationDateKey])))?.creationDate {
result.append((creationDate, url.lastPathComponent, url.path))
}
}
}
}
result.sort(by: { $0.0 < $1.0 })
subscriber.putNext(result.map { ($0.1, $0.2) })
subscriber.putCompletion()
}
return EmptyDisposable
}
}
public func log(_ tag: String, _ what: @autoclosure () -> String) {
if !self.logToFile && !self.logToConsole {
return
}
let string = what()
var rawTime = time_t()
time(&rawTime)
var timeinfo = tm()
localtime_r(&rawTime, &timeinfo)
var curTime = timeval()
gettimeofday(&curTime, nil)
let milliseconds = curTime.tv_usec / 1000
var consoleContent: String?
if self.logToConsole {
let content = String(format: "[SG.%@] %d-%d-%d %02d:%02d:%02d.%03d %@", arguments: [tag, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_mday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(timeinfo.tm_sec), Int(milliseconds), string])
consoleContent = content
print(content)
}
if self.logToFile {
self.queue.async {
let content: String
if let consoleContent = consoleContent {
content = consoleContent
} else {
content = String(format: "[SG.%@] %d-%d-%d %02d:%02d:%02d.%03d %@", arguments: [tag, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_mday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(timeinfo.tm_sec), Int(milliseconds), string])
}
var currentFile: ManagedFile?
var openNew = false
if let (file, length) = self.file {
if length >= self.maxLength {
self.file = nil
openNew = true
} else {
currentFile = file
}
} else {
openNew = true
}
if openNew {
let _ = try? FileManager.default.createDirectory(atPath: self.basePath, withIntermediateDirectories: true, attributes: nil)
var createNew = false
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: self.basePath), includingPropertiesForKeys: [URLResourceKey.creationDateKey], options: []) {
var minCreationDate: (Date, URL)?
var maxCreationDate: (Date, URL)?
var count = 0
for url in files {
if url.lastPathComponent.hasPrefix("log-") {
if let values = try? url.resourceValues(forKeys: Set([URLResourceKey.creationDateKey])), let creationDate = values.creationDate {
count += 1
if minCreationDate == nil || minCreationDate!.0 > creationDate {
minCreationDate = (creationDate, url)
}
if maxCreationDate == nil || maxCreationDate!.0 < creationDate {
maxCreationDate = (creationDate, url)
}
}
}
}
if let (_, url) = minCreationDate, count >= self.maxFiles {
let _ = try? FileManager.default.removeItem(at: url)
}
if let (_, url) = maxCreationDate {
var value = stat()
if stat(url.path, &value) == 0 && Int(value.st_size) < self.maxLength {
if let file = ManagedFile(queue: self.queue, path: url.path, mode: .append) {
self.file = (file, Int(value.st_size))
currentFile = file
}
} else {
createNew = true
}
} else {
createNew = true
}
}
if createNew {
let fileName = String(format: "log-%d-%d-%d_%02d-%02d-%02d.%03d.txt", arguments: [Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_mday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), Int(timeinfo.tm_sec), Int(milliseconds)])
let path = self.basePath + "/" + fileName
if let file = ManagedFile(queue: self.queue, path: path, mode: .append) {
self.file = (file, 0)
currentFile = file
}
}
}
if let currentFile = currentFile {
if let data = content.data(using: .utf8) {
data.withUnsafeBytes { rawBytes -> Void in
let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
let _ = currentFile.write(bytes, count: data.count)
}
var newline: UInt8 = 0x0a
let _ = currentFile.write(&newline, count: 1)
if let file = self.file {
self.file = (file.0, file.1 + data.count + 1)
} else {
assertionFailure()
}
}
}
}
}
}
}

View File

@ -0,0 +1,6 @@
//import Foundation
//
//public func extractNameFromPath(_ path: String) -> String {
// let fileName = URL(fileURLWithPath: path).lastPathComponent
// return String(fileName.prefix(upTo: fileName.lastIndex { $0 == "." } ?? fileName.endIndex))
//}

27
Swiftgram/SGRegDate/BUILD Normal file
View File

@ -0,0 +1,27 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGRegDate",
module_name = "SGRegDate",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//Swiftgram/SGRegDateScheme:SGRegDateScheme",
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
"//Swiftgram/SGAPI:SGAPI",
"//Swiftgram/SGAPIToken:SGAPIToken",
"//Swiftgram/SGDeviceToken:SGDeviceToken",
"//Swiftgram/SGStrings:SGStrings",
"//submodules/AccountContext:AccountContext",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/TelegramPresentationData:TelegramPresentationData",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,45 @@
import Foundation
import SwiftSignalKit
import TelegramPresentationData
import SGLogging
import SGStrings
import SGRegDateScheme
import AccountContext
import SGSimpleSettings
import SGAPI
import SGAPIToken
import SGDeviceToken
public enum RegDateError {
case generic
}
public func getRegDate(context: AccountContext, peerId: Int64) -> Signal<RegDate?, NoError> {
return Signal { subscriber in
var tokensRequestSignal: Disposable? = nil
var apiRequestSignal: Disposable? = nil
if let regDateData = SGSimpleSettings.shared.regDateCache[String(peerId)], let regDate = try? JSONDecoder().decode(RegDate.self, from: regDateData), regDate.validUntil == 0 || regDate.validUntil > Int64(Date().timeIntervalSince1970) {
subscriber.putNext(regDate)
subscriber.putCompletion()
} else if SGSimpleSettings.shared.showRegDate {
tokensRequestSignal = combineLatest(getDeviceToken() |> mapError { error -> Void in SGLogger.shared.log("SGDeviceToken", "Error generating token: \(error)"); return Void() } , getSGApiToken(context: context) |> mapError { _ -> Void in return Void() }).start(next: { deviceToken, apiToken in
apiRequestSignal = getSGAPIRegDate(token: apiToken, deviceToken: deviceToken, userId: peerId).start(next: { regDate in
if let data = try? JSONEncoder().encode(regDate) {
SGSimpleSettings.shared.regDateCache[String(peerId)] = data
}
subscriber.putNext(regDate)
subscriber.putCompletion()
})
})
} else {
subscriber.putNext(nil)
subscriber.putCompletion()
}
return ActionDisposable {
tokensRequestSignal?.dispose()
apiRequestSignal?.dispose()
}
}
}

View File

@ -0,0 +1,17 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGRegDateScheme",
module_name = "SGRegDateScheme",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,7 @@
import Foundation
public struct RegDate: Codable {
public let from: Int64
public let to: Int64
public let validUntil: Int64
}

View File

@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGRequests",
module_name = "SGRequests",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit"
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,72 @@
import Foundation
import SwiftSignalKit
public func requestsDownload(url: URL) -> Signal<(Data, URLResponse?), Error?> {
return Signal { subscriber in
let completed = Atomic<Bool>(value: false)
let downloadTask = URLSession.shared.downloadTask(with: url, completionHandler: { location, response, error in
let _ = completed.swap(true)
if let location = location, let data = try? Data(contentsOf: location) {
subscriber.putNext((data, response))
subscriber.putCompletion()
} else {
subscriber.putError(error)
}
})
downloadTask.resume()
return ActionDisposable {
if !completed.with({ $0 }) {
downloadTask.cancel()
}
}
}
}
public func requestsGet(url: URL) -> Signal<(Data, URLResponse?), Error?> {
return Signal { subscriber in
let completed = Atomic<Bool>(value: false)
let urlTask = URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
let _ = completed.swap(true)
if let strongData = data {
subscriber.putNext((strongData, response))
subscriber.putCompletion()
} else {
subscriber.putError(error)
}
})
urlTask.resume()
return ActionDisposable {
if !completed.with({ $0 }) {
urlTask.cancel()
}
}
}
}
public func requestsCustom(request: URLRequest) -> Signal<(Data, URLResponse?), Error?> {
return Signal { subscriber in
let completed = Atomic<Bool>(value: false)
let urlTask = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
_ = completed.swap(true)
if let strongData = data {
subscriber.putNext((strongData, response))
subscriber.putCompletion()
} else {
subscriber.putError(error)
}
})
urlTask.resume()
return ActionDisposable {
if !completed.with({ $0 }) {
urlTask.cancel()
}
}
}
}

View File

@ -0,0 +1,10 @@
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_bundle_import")
apple_bundle_import(
name = "SGSettingsBundle",
bundle_imports = glob([
"Settings.bundle/*",
"Settings.bundle/**/*",
]),
visibility = ["//visibility:public"]
)

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>FooterText</key>
<string>Reset.Notice</string>
<key>Title</key>
<string>Reset.Title</string>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Reset.Toggle</string>
<key>Key</key>
<string>sg_db_reset</string>
<key>DefaultValue</key>
<false/>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
"Reset.Title" = "TROUBLESHOOTING";
"Reset.Toggle" = "Reset caches on next launch";
"Reset.Notice" = "Use in case you're stuck and can't open the app. This WILL NOT logout your accounts, but all secret chats will be lost.";

View File

@ -0,0 +1,3 @@
"Reset.Title" = "РЕШЕНИЕ ПРОБЛЕМ";
"Reset.Toggle" = "Сбросить кэш при следующем запуске";
"Reset.Notice" = "Используйте, если приложение вылетает или не загружается. Эта опция НЕ СБРАСЫВАЕТ ваши аккаунты, но удалит все секретные чаты.";

View File

@ -0,0 +1,42 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
filegroup(
name = "SGUIAssets",
srcs = glob(["Images.xcassets/**"]),
visibility = ["//visibility:public"],
)
swift_library(
name = "SGSettingsUI",
module_name = "SGSettingsUI",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//Swiftgram/SGItemListUI:SGItemListUI",
"//Swiftgram/SGLogging:SGLogging",
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
"//Swiftgram/SGStrings:SGStrings",
# "//Swiftgram/SGAPI:SGAPI",
"//Swiftgram/SGAPIToken:SGAPIToken",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Display:Display",
"//submodules/Postbox:Postbox",
"//submodules/TelegramCore:TelegramCore",
"//submodules/MtProtoKit:MtProtoKit",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/TelegramUIPreferences:TelegramUIPreferences",
"//submodules/ItemListUI:ItemListUI",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/AccountContext:AccountContext",
"//submodules/AppBundle:AppBundle",
"//submodules/TelegramUI/Components/Settings/PeerNameColorScreen",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_lt_savetocloud.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "swiftgram_context_menu.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,81 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 2.964844 cm
0.000000 0.000000 0.000000 scn
15.076375 10.766671 m
15.473662 11.399487 14.937258 12.204764 14.200223 12.081993 c
9.059459 11.225675 l
8.855769 11.191745 8.670359 11.348825 8.670359 11.555322 c
8.670359 18.524288 l
8.670359 19.289572 7.652856 19.554642 7.279467 18.886631 c
1.036950 7.718488 l
0.658048 7.040615 1.293577 6.244993 2.038416 6.464749 c
9.378864 8.630468 l
9.637225 8.706696 9.814250 8.373775 9.606588 8.202201 c
6.918006 5.980853 l
6.462659 5.604639 6.199009 5.044809 6.199009 4.454151 c
6.199009 -0.793964 l
6.199009 -1.539309 7.174314 -1.820084 7.570620 -1.188831 c
15.076375 10.766671 l
h
f*
n
Q
endstream
endobj
3 0 obj
702
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000792 00000 n
0000000814 00000 n
0000000987 00000 n
0000001061 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1120
%%EOF

View File

@ -0,0 +1,13 @@
{
"images" : [
{
"filename" : "Swiftgram.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,242 @@
%PDF-1.7
1 0 obj
<< /Length 2 0 R
/Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ]
/Domain [ 0.000000 1.000000 ]
/FunctionType 4
>>
stream
{ 1.000000 exch 0.764706 exch 0.415686 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.098039 mul 1.000000 add exch dup 0.000000 sub -0.764706 mul 0.764706 add exch dup 0.000000 sub -0.415686 mul 0.415686 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.901961 exch 0.000000 exch 0.000000 exch } if pop }
endstream
endobj
2 0 obj
339
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << /Pattern << /P1 << /Matrix [ -625.250061 -1215.250000 1215.250000 -625.250061 -946.303711 1659.980225 ]
/Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ]
/ColorSpace /DeviceRGB
/Function 1 0 R
/Domain [ 0.000000 1.000000 ]
/ShadingType 2
/Extend [ true true ]
>>
/PatternType 2
/Type /Pattern
>> >> >>
/BBox [ 0.000000 0.000000 512.000000 512.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
/Pattern cs
/P1 scn
0.000000 320.853333 m
0.000000 387.754669 0.000000 421.205322 12.970667 446.805328 c
24.405334 469.333344 42.666668 487.594666 65.194672 499.029327 c
90.794670 512.000000 124.245338 512.000000 191.146667 512.000000 c
320.853333 512.000000 l
387.754669 512.000000 421.205353 512.000000 446.805359 499.029327 c
469.333374 487.594666 487.594696 469.333344 499.029358 446.805328 c
512.000000 421.205322 512.000000 387.754669 512.000000 320.853333 c
512.000000 191.146667 l
512.000000 124.245331 512.000000 90.794647 499.029358 65.194641 c
487.594696 42.666626 469.333374 24.405304 446.805359 12.970642 c
421.205353 0.000000 387.754669 0.000000 320.853333 0.000000 c
191.146667 0.000000 l
124.245338 0.000000 90.794670 0.000000 65.194672 12.970642 c
42.666668 24.405304 24.405334 42.666626 12.970667 65.194641 c
0.000000 90.794647 0.000000 124.245331 0.000000 191.146667 c
0.000000 320.853333 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 119.500000 103.400391 cm
1.000000 1.000000 1.000000 scn
256.015533 182.826599 m
262.761963 193.572601 253.653152 207.247192 241.137390 205.162399 c
153.840836 190.621048 l
150.381927 190.044891 147.233429 192.712296 147.233429 196.218872 c
147.233429 314.560455 l
147.233429 327.555908 129.954987 332.057098 123.614365 320.713440 c
17.608702 131.064743 l
11.174477 119.553635 21.966566 106.042999 34.614845 109.774734 c
159.264740 146.551285 l
163.652023 147.845703 166.658112 142.192291 163.131760 139.278763 c
117.476318 101.557587 l
109.743965 95.169006 105.266861 85.662384 105.266861 75.632263 c
105.266861 -13.487152 l
105.266861 -26.143982 121.828712 -30.911926 128.558456 -20.192505 c
256.015533 182.826599 l
h
f*
n
Q
endstream
endobj
4 0 obj
1771
endobj
5 0 obj
<< /Length 6 0 R
/Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ]
/Domain [ 0.000000 1.000000 ]
/FunctionType 4
>>
stream
{ 1.000000 exch 0.764706 exch 0.415686 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub -0.098039 mul 1.000000 add exch dup 0.000000 sub -0.764706 mul 0.764706 add exch dup 0.000000 sub -0.415686 mul 0.415686 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.901961 exch 0.000000 exch 0.000000 exch } if pop }
endstream
endobj
6 0 obj
339
endobj
7 0 obj
<< /Type /XObject
/Length 8 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << /Pattern << /P1 << /Matrix [ -625.250061 -1215.250000 1215.250000 -625.250061 -946.303711 1659.980225 ]
/Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ]
/ColorSpace /DeviceRGB
/Function 5 0 R
/Domain [ 0.000000 1.000000 ]
/ShadingType 2
/Extend [ true true ]
>>
/PatternType 2
/Type /Pattern
>> >> >>
/BBox [ 0.000000 0.000000 512.000000 512.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
/Pattern cs
/P1 scn
0.000000 320.853333 m
0.000000 387.754669 0.000000 421.205322 12.970667 446.805328 c
24.405334 469.333344 42.666668 487.594666 65.194672 499.029327 c
90.794670 512.000000 124.245338 512.000000 191.146667 512.000000 c
320.853333 512.000000 l
387.754669 512.000000 421.205353 512.000000 446.805359 499.029327 c
469.333374 487.594666 487.594696 469.333344 499.029358 446.805328 c
512.000000 421.205322 512.000000 387.754669 512.000000 320.853333 c
512.000000 191.146667 l
512.000000 124.245331 512.000000 90.794647 499.029358 65.194641 c
487.594696 42.666626 469.333374 24.405304 446.805359 12.970642 c
421.205353 0.000000 387.754669 0.000000 320.853333 0.000000 c
191.146667 0.000000 l
124.245338 0.000000 90.794670 0.000000 65.194672 12.970642 c
42.666668 24.405304 24.405334 42.666626 12.970667 65.194641 c
0.000000 90.794647 0.000000 124.245331 0.000000 191.146667 c
0.000000 320.853333 l
h
f
n
Q
endstream
endobj
8 0 obj
1006
endobj
9 0 obj
<< /XObject << /X1 3 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 7 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
10 0 obj
<< /Length 11 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
11 0 obj
46
endobj
12 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 512.000000 512.000000 ]
/Resources 9 0 R
/Contents 10 0 R
/Parent 13 0 R
>>
endobj
13 0 obj
<< /Kids [ 12 0 R ]
/Count 1
/Type /Pages
>>
endobj
14 0 obj
<< /Pages 13 0 R
/Type /Catalog
>>
endobj
xref
0 15
0000000000 65535 f
0000000010 00000 n
0000000533 00000 n
0000000555 00000 n
0000003331 00000 n
0000003354 00000 n
0000003877 00000 n
0000003899 00000 n
0000005910 00000 n
0000005933 00000 n
0000006231 00000 n
0000006335 00000 n
0000006357 00000 n
0000006535 00000 n
0000006611 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 14 0 R
/Size 15
>>
startxref
6672
%%EOF

View File

@ -0,0 +1,636 @@
// MARK: Swiftgram
import SGLogging
import SGSimpleSettings
import SGStrings
import SGAPIToken
import SGItemListUI
import Foundation
import UIKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import MtProtoKit
import MessageUI
import TelegramPresentationData
import TelegramUIPreferences
import ItemListUI
import PresentationDataUtils
import OverlayStatusController
import AccountContext
import AppBundle
import WebKit
import PeerNameColorScreen
private enum SGControllerSection: Int32, SGItemListSection {
case content
case tabs
case folders
case chatList
case profiles
case stories
case translation
case photo
case stickers
case videoNotes
case contextMenu
case accountColors
case other
}
private enum SGBoolSetting: String {
case hidePhoneInSettings
case showTabNames
case showContactsTab
case showCallsTab
case foldersAtBottom
case startTelescopeWithRearCam
case hideStories
case uploadSpeedBoost
case showProfileId
case warnOnStoriesOpen
case sendWithReturnKey
case rememberLastFolder
case sendLargePhotos
case storyStealthMode
case disableSwipeToRecordStory
case quickTranslateButton
case hideReactions
case showRepostToStory
case contextShowSelectFromUser
case contextShowSaveToCloud
case contextShowHideForwardName
case contextShowRestrict
case contextShowReport
case contextShowReply
case contextShowPin
case contextShowSaveMedia
case contextShowMessageReplies
case contextShowJson
case disableScrollToNextChannel
case disableScrollToNextTopic
case disableChatSwipeOptions
case disableGalleryCamera
case disableSendAsButton
case disableSnapDeletionEffect
case stickerTimestamp
case hideRecordingButton
case hideTabBar
case showDC
case showCreationDate
case showRegDate
case compactChatList
case compactFolderNames
case allChatsHidden
case defaultEmojisFirst
case messageDoubleTapActionOutgoingEdit
case wideChannelPosts
case forceEmojiTab
case forceBuiltInMic
}
private enum SGOneFromManySetting: String {
case bottomTabStyle
case downloadSpeedBoost
case allChatsTitleLengthOverride
// case allChatsFolderPositionOverride
}
private enum SGSliderSetting: String {
case accountColorsSaturation
case outgoingPhotoQuality
case stickerSize
}
private enum SGDisclosureLink: String {
case contentSettings
case languageSettings
}
private struct PeerNameColorScreenState: Equatable {
var updatedNameColor: PeerNameColor?
var updatedBackgroundEmojiId: Int64?
}
private typealias SGControllerEntry = SGItemListUIEntry<SGControllerSection, SGBoolSetting, SGSliderSetting, SGOneFromManySetting, SGDisclosureLink, AnyHashable>
private func SGControllerEntries(presentationData: PresentationData, callListSettings: CallListSettings, experimentalUISettings: ExperimentalUISettings, SGSettings: SGUISettings, appConfiguration: AppConfiguration, nameColors: PeerNameColors /*state: PeerNameColorScreenState,*/) -> [SGControllerEntry] {
let lang = presentationData.strings.baseLanguageCode
var entries: [SGControllerEntry] = []
let id = SGItemListCounter()
if appConfiguration.sgWebSettings.global.canEditSettings {
entries.append(.disclosure(id: id.count, section: .content, link: .contentSettings, text: i18n("Settings.ContentSettings", lang)))
} else {
id.increment(1)
}
entries.append(.header(id: id.count, section: .tabs, text: i18n("Settings.Tabs.Header", lang), badge: nil))
entries.append(.toggle(id: id.count, section: .tabs, settingName: .hideTabBar, value: SGSimpleSettings.shared.hideTabBar, text: i18n("Settings.Tabs.HideTabBar", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .tabs, settingName: .showContactsTab, value: callListSettings.showContactsTab, text: i18n("Settings.Tabs.ShowContacts", lang), enabled: !SGSimpleSettings.shared.hideTabBar))
entries.append(.toggle(id: id.count, section: .tabs, settingName: .showCallsTab, value: callListSettings.showTab, text: presentationData.strings.CallSettings_TabIcon, enabled: !SGSimpleSettings.shared.hideTabBar))
entries.append(.toggle(id: id.count, section: .tabs, settingName: .showTabNames, value: SGSimpleSettings.shared.showTabNames, text: i18n("Settings.Tabs.ShowNames", lang), enabled: !SGSimpleSettings.shared.hideTabBar))
entries.append(.header(id: id.count, section: .folders, text: presentationData.strings.Settings_ChatFolders.uppercased(), badge: nil))
entries.append(.toggle(id: id.count, section: .folders, settingName: .foldersAtBottom, value: experimentalUISettings.foldersTabAtBottom, text: i18n("Settings.Folders.BottomTab", lang), enabled: true))
entries.append(.oneFromManySelector(id: id.count, section: .folders, settingName: .bottomTabStyle, text: i18n("Settings.Folders.BottomTabStyle", lang), value: i18n("Settings.Folders.BottomTabStyle.\(SGSimpleSettings.shared.bottomTabStyle)", lang), enabled: experimentalUISettings.foldersTabAtBottom))
entries.append(.toggle(id: id.count, section: .folders, settingName: .allChatsHidden, value: SGSimpleSettings.shared.allChatsHidden, text: i18n("Settings.Folders.AllChatsHidden", lang, presentationData.strings.ChatList_Tabs_AllChats), enabled: true))
#if DEBUG
// entries.append(.oneFromManySelector(id: id.count, section: .folders, settingName: .allChatsFolderPositionOverride, text: i18n("Settings.Folders.AllChatsPlacement", lang), value: i18n("Settings.Folders.AllChatsPlacement.\(SGSimpleSettings.shared.allChatsFolderPositionOverride)", lang), enabled: true))
#endif
entries.append(.toggle(id: id.count, section: .folders, settingName: .compactFolderNames, value: SGSimpleSettings.shared.compactFolderNames, text: i18n("Settings.Folders.CompactNames", lang), enabled: SGSimpleSettings.shared.bottomTabStyle != SGSimpleSettings.BottomTabStyleValues.ios.rawValue))
entries.append(.oneFromManySelector(id: id.count, section: .folders, settingName: .allChatsTitleLengthOverride, text: i18n("Settings.Folders.AllChatsTitle", lang), value: i18n("Settings.Folders.AllChatsTitle.\(SGSimpleSettings.shared.allChatsTitleLengthOverride)", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .folders, settingName: .rememberLastFolder, value: SGSimpleSettings.shared.rememberLastFolder, text: i18n("Settings.Folders.RememberLast", lang), enabled: true))
entries.append(.notice(id: id.count, section: .folders, text: i18n("Settings.Folders.RememberLast.Notice", lang)))
entries.append(.header(id: id.count, section: .chatList, text: i18n("Settings.ChatList.Header", lang), badge: nil))
entries.append(.toggle(id: id.count, section: .chatList, settingName: .compactChatList, value: SGSimpleSettings.shared.compactChatList, text: i18n("Settings.CompactChatList", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .chatList, settingName: .disableChatSwipeOptions, value: !SGSimpleSettings.shared.disableChatSwipeOptions, text: i18n("Settings.ChatSwipeOptions", lang), enabled: true))
entries.append(.header(id: id.count, section: .profiles, text: i18n("Settings.Profiles.Header", lang), badge: nil))
entries.append(.toggle(id: id.count, section: .profiles, settingName: .showProfileId, value: SGSettings.showProfileId, text: i18n("Settings.ShowProfileID", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .profiles, settingName: .showDC, value: SGSimpleSettings.shared.showDC, text: i18n("Settings.ShowDC", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .profiles, settingName: .showRegDate, value: SGSimpleSettings.shared.showRegDate, text: i18n("Settings.ShowRegDate", lang), enabled: true))
entries.append(.notice(id: id.count, section: .profiles, text: i18n("Settings.ShowRegDate.Notice", lang)))
entries.append(.toggle(id: id.count, section: .profiles, settingName: .showCreationDate, value: SGSimpleSettings.shared.showCreationDate, text: i18n("Settings.ShowCreationDate", lang), enabled: true))
entries.append(.notice(id: id.count, section: .profiles, text: i18n("Settings.ShowCreationDate.Notice", lang)))
entries.append(.header(id: id.count, section: .stories, text: presentationData.strings.AutoDownloadSettings_Stories.uppercased(), badge: nil))
entries.append(.toggle(id: id.count, section: .stories, settingName: .hideStories, value: SGSettings.hideStories, text: i18n("Settings.Stories.Hide", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .stories, settingName: .disableSwipeToRecordStory, value: SGSimpleSettings.shared.disableSwipeToRecordStory, text: i18n("Settings.Stories.DisableSwipeToRecord", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .stories, settingName: .warnOnStoriesOpen, value: SGSettings.warnOnStoriesOpen, text: i18n("Settings.Stories.WarnBeforeView", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .stories, settingName: .showRepostToStory, value: SGSimpleSettings.shared.showRepostToStory, text: presentationData.strings.Share_RepostToStory.replacingOccurrences(of: "\n", with: " "), enabled: true))
if SGSimpleSettings.shared.canUseStealthMode {
entries.append(.toggle(id: id.count, section: .stories, settingName: .storyStealthMode, value: SGSimpleSettings.shared.storyStealthMode, text: presentationData.strings.Story_StealthMode_Title, enabled: true))
entries.append(.notice(id: id.count, section: .stories, text: presentationData.strings.Story_StealthMode_ControlText))
} else {
id.increment(2)
}
entries.append(.header(id: id.count, section: .translation, text: presentationData.strings.Localization_TranslateMessages.uppercased(), badge: nil))
entries.append(.toggle(id: id.count, section: .translation, settingName: .quickTranslateButton, value: SGSimpleSettings.shared.quickTranslateButton, text: i18n("Settings.Translation.QuickTranslateButton", lang), enabled: true))
entries.append(.disclosure(id: id.count, section: .translation, link: .languageSettings, text: presentationData.strings.Localization_TranslateEntireChat))
entries.append(.notice(id: id.count, section: .translation, text: i18n("Common.NoTelegramPremiumNeeded", lang, presentationData.strings.Settings_Premium)))
entries.append(.header(id: id.count, section: .photo, text: presentationData.strings.NetworkUsageSettings_MediaImageDataSection, badge: nil))
entries.append(.header(id: id.count, section: .photo, text: presentationData.strings.PhotoEditor_QualityTool.uppercased(), badge: nil))
entries.append(.percentageSlider(id: id.count, section: .photo, settingName: .outgoingPhotoQuality, value: SGSimpleSettings.shared.outgoingPhotoQuality))
entries.append(.notice(id: id.count, section: .photo, text: i18n("Settings.Photo.Quality.Notice", lang)))
entries.append(.toggle(id: id.count, section: .photo, settingName: .sendLargePhotos, value: SGSimpleSettings.shared.sendLargePhotos, text: i18n("Settings.Photo.SendLarge", lang), enabled: true))
entries.append(.notice(id: id.count, section: .photo, text: i18n("Settings.Photo.SendLarge.Notice", lang)))
entries.append(.header(id: id.count, section: .stickers, text: presentationData.strings.StickerPacksSettings_Title.uppercased(), badge: nil))
entries.append(.header(id: id.count, section: .stickers, text: i18n("Settings.Stickers.Size", lang), badge: nil))
entries.append(.percentageSlider(id: id.count, section: .stickers, settingName: .stickerSize, value: SGSimpleSettings.shared.stickerSize))
entries.append(.toggle(id: id.count, section: .stickers, settingName: .stickerTimestamp, value: SGSimpleSettings.shared.stickerTimestamp, text: i18n("Settings.Stickers.Timestamp", lang), enabled: true))
entries.append(.header(id: id.count, section: .videoNotes, text: i18n("Settings.VideoNotes.Header", lang), badge: nil))
entries.append(.toggle(id: id.count, section: .videoNotes, settingName: .startTelescopeWithRearCam, value: SGSimpleSettings.shared.startTelescopeWithRearCam, text: i18n("Settings.VideoNotes.StartWithRearCam", lang), enabled: true))
entries.append(.header(id: id.count, section: .contextMenu, text: i18n("Settings.ContextMenu", lang), badge: nil))
entries.append(.notice(id: id.count, section: .contextMenu, text: i18n("Settings.ContextMenu.Notice", lang)))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowSaveToCloud, value: SGSimpleSettings.shared.contextShowSaveToCloud, text: i18n("ContextMenu.SaveToCloud", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowHideForwardName, value: SGSimpleSettings.shared.contextShowHideForwardName, text: presentationData.strings.Conversation_ForwardOptions_HideSendersNames, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowSelectFromUser, value: SGSimpleSettings.shared.contextShowSelectFromUser, text: i18n("ContextMenu.SelectFromUser", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowRestrict, value: SGSimpleSettings.shared.contextShowRestrict, text: presentationData.strings.Conversation_ContextMenuBan, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowReport, value: SGSimpleSettings.shared.contextShowReport, text: presentationData.strings.Conversation_ContextMenuReport, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowReply, value: SGSimpleSettings.shared.contextShowReply, text: presentationData.strings.Conversation_ContextMenuReply, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowPin, value: SGSimpleSettings.shared.contextShowPin, text: presentationData.strings.Conversation_Pin, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowSaveMedia, value: SGSimpleSettings.shared.contextShowSaveMedia, text: presentationData.strings.Conversation_SaveToFiles, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowMessageReplies, value: SGSimpleSettings.shared.contextShowMessageReplies, text: presentationData.strings.Conversation_ContextViewThread, enabled: true))
entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowJson, value: SGSimpleSettings.shared.contextShowJson, text: "JSON", enabled: true))
/* entries.append(.toggle(id: id.count, section: .contextMenu, settingName: .contextShowRestrict, value: SGSimpleSettings.shared.contextShowRestrict, text: presentationData.strings.Conversation_ContextMenuBan)) */
entries.append(.header(id: id.count, section: .accountColors, text: i18n("Settings.CustomColors.Header", lang), badge: nil))
entries.append(.header(id: id.count, section: .accountColors, text: i18n("Settings.CustomColors.Saturation", lang), badge: nil))
let accountColorSaturation = SGSimpleSettings.shared.accountColorsSaturation
entries.append(.percentageSlider(id: id.count, section: .accountColors, settingName: .accountColorsSaturation, value: accountColorSaturation))
// let nameColor: PeerNameColor
// if let updatedNameColor = state.updatedNameColor {
// nameColor = updatedNameColor
// } else {
// nameColor = .blue
// }
// let _ = nameColors.get(nameColor, dark: presentationData.theme.overallDarkAppearance)
// entries.append(.peerColorPicker(id: entries.count, section: .other,
// colors: nameColors,
// currentColor: nameColor, // TODO: PeerNameColor(rawValue: <#T##Int32#>)
// currentSaturation: accountColorSaturation
// ))
if accountColorSaturation == 0 {
id.increment(100)
entries.append(.peerColorDisclosurePreview(id: id.count, section: .accountColors, name: "\(presentationData.strings.UserInfo_FirstNamePlaceholder) \(presentationData.strings.UserInfo_LastNamePlaceholder)", color: presentationData.theme.chat.message.incoming.accentTextColor))
} else {
id.increment(200)
for index in nameColors.displayOrder.prefix(3) {
let color: PeerNameColor = PeerNameColor(rawValue: index)
let colors = nameColors.get(color, dark: presentationData.theme.overallDarkAppearance)
entries.append(.peerColorDisclosurePreview(id: id.count, section: .accountColors, name: "\(presentationData.strings.UserInfo_FirstNamePlaceholder) \(presentationData.strings.UserInfo_LastNamePlaceholder)", color: colors.main))
}
}
entries.append(.notice(id: id.count, section: .accountColors, text: i18n("Settings.CustomColors.Saturation.Notice", lang)))
id.increment(10000)
entries.append(.header(id: id.count, section: .other, text: presentationData.strings.Appearance_Other.uppercased(), badge: nil))
entries.append(.toggle(id: id.count, section: .other, settingName: .wideChannelPosts, value: SGSimpleSettings.shared.wideChannelPosts, text: i18n("Settings.wideChannelPosts", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .forceBuiltInMic, value: SGSimpleSettings.shared.forceBuiltInMic, text: i18n("Settings.forceBuiltInMic", lang), enabled: true))
entries.append(.notice(id: id.count, section: .other, text: i18n("Settings.forceBuiltInMic.Notice", lang)))
entries.append(.toggle(id: id.count, section: .other, settingName: .messageDoubleTapActionOutgoingEdit, value: SGSimpleSettings.shared.messageDoubleTapActionOutgoing == SGSimpleSettings.MessageDoubleTapAction.edit.rawValue, text: i18n("Settings.messageDoubleTapActionOutgoingEdit", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .hideRecordingButton, value: !SGSimpleSettings.shared.hideRecordingButton, text: i18n("Settings.RecordingButton", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .disableSnapDeletionEffect, value: !SGSimpleSettings.shared.disableSnapDeletionEffect, text: i18n("Settings.SnapDeletionEffect", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .disableSendAsButton, value: !SGSimpleSettings.shared.disableSendAsButton, text: i18n("Settings.SendAsButton", lang, presentationData.strings.Conversation_SendMesageAs), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .disableGalleryCamera, value: !SGSimpleSettings.shared.disableGalleryCamera, text: i18n("Settings.GalleryCamera", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .disableScrollToNextChannel, value: !SGSimpleSettings.shared.disableScrollToNextChannel, text: i18n("Settings.PullToNextChannel", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .disableScrollToNextTopic, value: !SGSimpleSettings.shared.disableScrollToNextTopic, text: i18n("Settings.PullToNextTopic", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .hideReactions, value: SGSimpleSettings.shared.hideReactions, text: i18n("Settings.HideReactions", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .uploadSpeedBoost, value: SGSimpleSettings.shared.uploadSpeedBoost, text: i18n("Settings.UploadsBoost", lang), enabled: true))
entries.append(.oneFromManySelector(id: id.count, section: .other, settingName: .downloadSpeedBoost, text: i18n("Settings.DownloadsBoost", lang), value: i18n("Settings.DownloadsBoost.\(SGSimpleSettings.shared.downloadSpeedBoost)", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .sendWithReturnKey, value: SGSettings.sendWithReturnKey, text: i18n("Settings.SendWithReturnKey", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .forceEmojiTab, value: SGSimpleSettings.shared.forceEmojiTab, text: i18n("Settings.ForceEmojiTab", lang), enabled: true))
entries.append(.toggle(id: id.count, section: .other, settingName: .defaultEmojisFirst, value: SGSimpleSettings.shared.defaultEmojisFirst, text: i18n("Settings.DefaultEmojisFirst", lang), enabled: true))
entries.append(.notice(id: id.count, section: .other, text: i18n("Settings.DefaultEmojisFirst.Notice", lang)))
entries.append(.toggle(id: id.count, section: .other, settingName: .hidePhoneInSettings, value: SGSimpleSettings.shared.hidePhoneInSettings, text: i18n("Settings.HidePhoneInSettingsUI", lang), enabled: true))
entries.append(.notice(id: id.count, section: .other, text: i18n("Settings.HidePhoneInSettingsUI.Notice", lang)))
return entries
}
public func sgSettingsController(context: AccountContext/*, focusOnItemTag: Int? = nil*/) -> ViewController {
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
// var getRootControllerImpl: (() -> UIViewController?)?
// var getNavigationControllerImpl: (() -> NavigationController?)?
var askForRestart: (() -> Void)?
// let statePromise = ValuePromise(PeerNameColorScreenState(), ignoreRepeated: true)
// let stateValue = Atomic(value: PeerNameColorScreenState())
// let updateState: ((PeerNameColorScreenState) -> PeerNameColorScreenState) -> Void = { f in
// statePromise.set(stateValue.modify { f($0) })
// }
// let sliderPromise = ValuePromise(SGSimpleSettings.shared.accountColorsSaturation, ignoreRepeated: true)
// let sliderStateValue = Atomic(value: SGSimpleSettings.shared.accountColorsSaturation)
// let _: ((Int32) -> Int32) -> Void = { f in
// sliderPromise.set(sliderStateValue.modify( {f($0)}))
// }
let simplePromise = ValuePromise(true, ignoreRepeated: false)
let arguments = SGItemListArguments<SGBoolSetting, SGSliderSetting, SGOneFromManySetting, SGDisclosureLink, AnyHashable>(
context: context,
/*updatePeerColor: { color in
updateState { state in
var updatedState = state
updatedState.updatedNameColor = color
return updatedState
}
},*/ setBoolValue: { setting, value in
switch setting {
case .hidePhoneInSettings:
SGSimpleSettings.shared.hidePhoneInSettings = value
askForRestart?()
case .showTabNames:
SGSimpleSettings.shared.showTabNames = value
askForRestart?()
case .showContactsTab:
let _ = (
updateCallListSettingsInteractively(
accountManager: context.sharedContext.accountManager, { $0.withUpdatedShowContactsTab(value) }
)
).start()
case .showCallsTab:
let _ = (
updateCallListSettingsInteractively(
accountManager: context.sharedContext.accountManager, { $0.withUpdatedShowTab(value) }
)
).start()
case .foldersAtBottom:
let _ = (
updateExperimentalUISettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in
var settings = settings
settings.foldersTabAtBottom = value
return settings
}
)
).start()
case .startTelescopeWithRearCam:
SGSimpleSettings.shared.startTelescopeWithRearCam = value
case .hideStories:
let _ = (
updateSGUISettings(engine: context.engine, { settings in
var settings = settings
settings.hideStories = value
return settings
})
).start()
case .showProfileId:
let _ = (
updateSGUISettings(engine: context.engine, { settings in
var settings = settings
settings.showProfileId = value
return settings
})
).start()
case .warnOnStoriesOpen:
let _ = (
updateSGUISettings(engine: context.engine, { settings in
var settings = settings
settings.warnOnStoriesOpen = value
return settings
})
).start()
case .sendWithReturnKey:
let _ = (
updateSGUISettings(engine: context.engine, { settings in
var settings = settings
settings.sendWithReturnKey = value
return settings
})
).start()
case .rememberLastFolder:
SGSimpleSettings.shared.rememberLastFolder = value
case .sendLargePhotos:
SGSimpleSettings.shared.sendLargePhotos = value
case .storyStealthMode:
SGSimpleSettings.shared.storyStealthMode = value
case .disableSwipeToRecordStory:
SGSimpleSettings.shared.disableSwipeToRecordStory = value
case .quickTranslateButton:
SGSimpleSettings.shared.quickTranslateButton = value
case .uploadSpeedBoost:
SGSimpleSettings.shared.uploadSpeedBoost = value
case .hideReactions:
SGSimpleSettings.shared.hideReactions = value
case .showRepostToStory:
SGSimpleSettings.shared.showRepostToStory = value
case .contextShowSelectFromUser:
SGSimpleSettings.shared.contextShowSelectFromUser = value
case .contextShowSaveToCloud:
SGSimpleSettings.shared.contextShowSaveToCloud = value
case .contextShowRestrict:
SGSimpleSettings.shared.contextShowRestrict = value
case .contextShowHideForwardName:
SGSimpleSettings.shared.contextShowHideForwardName = value
case .disableScrollToNextChannel:
SGSimpleSettings.shared.disableScrollToNextChannel = !value
case .disableScrollToNextTopic:
SGSimpleSettings.shared.disableScrollToNextTopic = !value
case .disableChatSwipeOptions:
SGSimpleSettings.shared.disableChatSwipeOptions = !value
askForRestart?()
case .disableGalleryCamera:
SGSimpleSettings.shared.disableGalleryCamera = !value
case .disableSendAsButton:
SGSimpleSettings.shared.disableSendAsButton = !value
case .disableSnapDeletionEffect:
SGSimpleSettings.shared.disableSnapDeletionEffect = !value
case .contextShowReport:
SGSimpleSettings.shared.contextShowReport = value
case .contextShowReply:
SGSimpleSettings.shared.contextShowReply = value
case .contextShowPin:
SGSimpleSettings.shared.contextShowPin = value
case .contextShowSaveMedia:
SGSimpleSettings.shared.contextShowSaveMedia = value
case .contextShowMessageReplies:
SGSimpleSettings.shared.contextShowMessageReplies = value
case .stickerTimestamp:
SGSimpleSettings.shared.stickerTimestamp = value
case .contextShowJson:
SGSimpleSettings.shared.contextShowJson = value
case .hideRecordingButton:
SGSimpleSettings.shared.hideRecordingButton = !value
case .hideTabBar:
SGSimpleSettings.shared.hideTabBar = value
simplePromise.set(true) // Trigger update for 'enabled' field of other toggles
askForRestart?()
case .showDC:
SGSimpleSettings.shared.showDC = value
case .showCreationDate:
SGSimpleSettings.shared.showCreationDate = value
case .showRegDate:
SGSimpleSettings.shared.showRegDate = value
case .compactChatList:
SGSimpleSettings.shared.compactChatList = value
askForRestart?()
case .compactFolderNames:
SGSimpleSettings.shared.compactFolderNames = value
case .allChatsHidden:
SGSimpleSettings.shared.allChatsHidden = value
askForRestart?()
case .defaultEmojisFirst:
SGSimpleSettings.shared.defaultEmojisFirst = value
case .messageDoubleTapActionOutgoingEdit:
SGSimpleSettings.shared.messageDoubleTapActionOutgoing = value ? SGSimpleSettings.MessageDoubleTapAction.edit.rawValue : SGSimpleSettings.MessageDoubleTapAction.default.rawValue
case .wideChannelPosts:
SGSimpleSettings.shared.wideChannelPosts = value
case .forceEmojiTab:
SGSimpleSettings.shared.forceEmojiTab = value
case .forceBuiltInMic:
SGSimpleSettings.shared.forceBuiltInMic = value
}
}, updateSliderValue: { setting, value in
switch (setting) {
case .accountColorsSaturation:
if SGSimpleSettings.shared.accountColorsSaturation != value {
SGSimpleSettings.shared.accountColorsSaturation = value
simplePromise.set(true)
}
case .outgoingPhotoQuality:
if SGSimpleSettings.shared.outgoingPhotoQuality != value {
SGSimpleSettings.shared.outgoingPhotoQuality = value
simplePromise.set(true)
}
case .stickerSize:
if SGSimpleSettings.shared.stickerSize != value {
SGSimpleSettings.shared.stickerSize = value
simplePromise.set(true)
}
}
}, setOneFromManyValue: { setting in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
switch (setting) {
case .downloadSpeedBoost:
let setAction: (String) -> Void = { value in
SGSimpleSettings.shared.downloadSpeedBoost = value
let enableDownloadX: Bool
switch (value) {
case SGSimpleSettings.DownloadSpeedBoostValues.none.rawValue:
enableDownloadX = false
default:
enableDownloadX = true
}
// Updating controller
simplePromise.set(true)
let _ = updateNetworkSettingsInteractively(postbox: context.account.postbox, network: context.account.network, { settings in
var settings = settings
settings.useExperimentalDownload = enableDownloadX
return settings
}).start(completed: {
Queue.mainQueue().async {
askForRestart?()
}
})
}
for value in SGSimpleSettings.DownloadSpeedBoostValues.allCases {
items.append(ActionSheetButtonItem(title: i18n("Settings.DownloadsBoost.\(value.rawValue)", presentationData.strings.baseLanguageCode), color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
setAction(value.rawValue)
}))
}
case .bottomTabStyle:
let setAction: (String) -> Void = { value in
SGSimpleSettings.shared.bottomTabStyle = value
simplePromise.set(true)
}
for value in SGSimpleSettings.BottomTabStyleValues.allCases {
items.append(ActionSheetButtonItem(title: i18n("Settings.Folders.BottomTabStyle.\(value.rawValue)", presentationData.strings.baseLanguageCode), color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
setAction(value.rawValue)
}))
}
case .allChatsTitleLengthOverride:
let setAction: (String) -> Void = { value in
SGSimpleSettings.shared.allChatsTitleLengthOverride = value
simplePromise.set(true)
}
for value in SGSimpleSettings.AllChatsTitleLengthOverride.allCases {
let title: String
switch (value) {
case SGSimpleSettings.AllChatsTitleLengthOverride.short:
title = "\"\(presentationData.strings.ChatList_Tabs_All)\""
case SGSimpleSettings.AllChatsTitleLengthOverride.long:
title = "\"\(presentationData.strings.ChatList_Tabs_AllChats)\""
default:
title = i18n("Settings.Folders.AllChatsTitle.none", presentationData.strings.baseLanguageCode)
}
items.append(ActionSheetButtonItem(title: title, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
setAction(value.rawValue)
}))
}
// case .allChatsFolderPositionOverride:
// let setAction: (String) -> Void = { value in
// SGSimpleSettings.shared.allChatsFolderPositionOverride = value
// simplePromise.set(true)
// }
//
// for value in SGSimpleSettings.AllChatsFolderPositionOverride.allCases {
// items.append(ActionSheetButtonItem(title: i18n("Settings.Folders.AllChatsTitle.\(value)", presentationData.strings.baseLanguageCode), color: .accent, action: { [weak actionSheet] in
// actionSheet?.dismissAnimated()
// setAction(value.rawValue)
// }))
// }
}
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, openDisclosureLink: { link in
switch (link) {
case .languageSettings:
pushControllerImpl?(context.sharedContext.makeLocalizationListController(context: context))
case .contentSettings:
let _ = (getSGSettingsURL(context: context) |> deliverOnMainQueue).start(next: { [weak context] url in
guard let strongContext = context else {
return
}
strongContext.sharedContext.applicationBindings.openUrl(url)
})
}
})
let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.callListSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings])
let preferences = context.account.postbox.preferencesView(keys: [ApplicationSpecificPreferencesKeys.SGUISettings, PreferencesKeys.appConfiguration])
let updatedContentSettingsConfiguration = contentSettingsConfiguration(network: context.account.network)
|> map(Optional.init)
let contentSettingsConfiguration = Promise<ContentSettingsConfiguration?>()
contentSettingsConfiguration.set(.single(nil)
|> then(updatedContentSettingsConfiguration))
let signal = combineLatest(simplePromise.get(), /*sliderPromise.get(),*/ /*statePromise.get(),*/ context.sharedContext.presentationData, sharedData, preferences, contentSettingsConfiguration.get(),
context.engine.accountData.observeAvailableColorOptions(scope: .replies),
context.engine.accountData.observeAvailableColorOptions(scope: .profile)
)
|> map { _, /*sliderValue,*/ /*state,*/ presentationData, sharedData, view, contentSettingsConfiguration, availableReplyColors, availableProfileColors -> (ItemListControllerState, (ItemListNodeState, Any)) in
let sgUISettings: SGUISettings = view.values[ApplicationSpecificPreferencesKeys.SGUISettings]?.get(SGUISettings.self) ?? SGUISettings.default
let appConfiguration: AppConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
let callListSettings: CallListSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.callListSettings]?.get(CallListSettings.self) ?? CallListSettings.defaultSettings
let experimentalUISettings: ExperimentalUISettings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings]?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
let entries = SGControllerEntries(presentationData: presentationData, callListSettings: callListSettings, experimentalUISettings: experimentalUISettings, SGSettings: sgUISettings, appConfiguration: appConfiguration, nameColors: PeerNameColors.with(availableReplyColors: availableReplyColors, availableProfileColors: availableProfileColors) /*state: state,*/)
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Swiftgram"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
// TODO(swiftgram): focusOnItemTag support
/* var index = 0
var scrollToItem: ListViewScrollToItem?
if let focusOnItemTag = focusOnItemTag {
for entry in entries {
if entry.tag?.isEqual(to: focusOnItemTag) ?? false {
scrollToItem = ListViewScrollToItem(index: index, position: .top(0.0), animated: false, curve: .Default(duration: 0.0), directionHint: .Up)
}
index += 1
}
} */
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, ensureVisibleItemTag: /*focusOnItemTag*/ nil, initialScrollToItem: nil /* scrollToItem*/ )
return (controllerState, (listState, arguments))
}
let controller = ItemListController(context: context, state: signal)
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushControllerImpl = { [weak controller] c in
(controller?.navigationController as? NavigationController)?.pushViewController(c)
}
// getRootControllerImpl = { [weak controller] in
// return controller?.view.window?.rootViewController
// }
// getNavigationControllerImpl = { [weak controller] in
// return controller?.navigationController as? NavigationController
// }
askForRestart = { [weak context] in
guard let context = context else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: i18n("Common.RestartRequired", presentationData.strings.baseLanguageCode)),
ActionSheetButtonItem(title: i18n("Common.RestartNow", presentationData.strings.baseLanguageCode), color: .destructive, font: .default, action: {
exit(0)
})
]), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
return controller
}

View File

@ -0,0 +1,9 @@
filegroup(
name = "SGShowMessageJson",
srcs = glob([
"Sources/**/*.swift",
]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,76 @@
import Foundation
import Wrap
import SGLogging
import ChatControllerInteraction
import ChatPresentationInterfaceState
import Postbox
import TelegramCore
import AccountContext
public func showMessageJson(controllerInteraction: ChatControllerInteraction, chatPresentationInterfaceState: ChatPresentationInterfaceState, message: Message, context: AccountContext) {
if let navigationController = controllerInteraction.navigationController(), let rootController = navigationController.view.window?.rootViewController {
var writingOptions: JSONSerialization.WritingOptions = [
.prettyPrinted,
//.sortedKeys,
]
if #available(iOS 13.0, *) {
writingOptions.insert(.withoutEscapingSlashes)
}
var messageData: Data? = nil
do {
messageData = try wrap(
message,
writingOptions: writingOptions
)
} catch {
SGLogger.shared.log("ShowMessageJSON", "Error parsing data: \(error)")
messageData = nil
}
guard let messageData = messageData else { return }
let id = Int64.random(in: Int64.min ... Int64.max)
let fileResource = LocalFileMediaResource(fileId: id, size: Int64(messageData.count), isSecretRelated: false)
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: messageData, synchronous: true)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/json; charset=utf-8", size: Int64(messageData.count), attributes: [.FileName(fileName: "message.json")])
presentDocumentPreviewController(rootController: rootController, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, postbox: context.account.postbox, file: file, canShare: !message.isCopyProtected())
}
}
extension MemoryBuffer: WrapCustomizable {
public func wrap(context: Any?, dateFormatter: DateFormatter?) -> Any? {
let hexString = self.description
return ["string": hexStringToString(hexString) ?? hexString]
}
}
// There's a chacne we will need it for each empty/weird type, or it will be a runtime crash.
extension ContentRequiresValidationMessageAttribute: WrapCustomizable {
public func wrap(context: Any?, dateFormatter: DateFormatter?) -> Any? {
return ["@type": "ContentRequiresValidationMessageAttribute"]
}
}
func hexStringToString(_ hexString: String) -> String? {
var chars = Array(hexString)
var result = ""
while chars.count > 0 {
let c = String(chars[0...1])
chars = Array(chars.dropFirst(2))
if let byte = UInt8(c, radix: 16) {
let scalar = UnicodeScalar(byte)
result.append(String(scalar))
} else {
return nil
}
}
return result
}

View File

@ -0,0 +1,17 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGSimpleSettings",
module_name = "SGSimpleSettings",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,58 @@
//// A copy of Atomic from SwiftSignalKit
//import Foundation
//
//public enum AtomicWrapperLockError: Error {
// case isLocked
//}
//
//public final class AtomicWrapper<T> {
// private var lock: pthread_mutex_t
// private var value: T
//
// public init(value: T) {
// self.lock = pthread_mutex_t()
// self.value = value
//
// pthread_mutex_init(&self.lock, nil)
// }
//
// deinit {
// pthread_mutex_destroy(&self.lock)
// }
//
// public func with<R>(_ f: (T) -> R) -> R {
// pthread_mutex_lock(&self.lock)
// let result = f(self.value)
// pthread_mutex_unlock(&self.lock)
//
// return result
// }
//
// public func tryWith<R>(_ f: (T) -> R) throws -> R {
// if pthread_mutex_trylock(&self.lock) == 0 {
// let result = f(self.value)
// pthread_mutex_unlock(&self.lock)
// return result
// } else {
// throw AtomicWrapperLockError.isLocked
// }
// }
//
// public func modify(_ f: (T) -> T) -> T {
// pthread_mutex_lock(&self.lock)
// let result = f(self.value)
// self.value = result
// pthread_mutex_unlock(&self.lock)
//
// return result
// }
//
// public func swap(_ value: T) -> T {
// pthread_mutex_lock(&self.lock)
// let previous = self.value
// self.value = value
// pthread_mutex_unlock(&self.lock)
//
// return previous
// }
//}

View File

@ -0,0 +1,36 @@
//
// RWLock.swift
// SwiftConcurrentCollections
//
// Created by Pete Prokop on 09/02/2020.
// Copyright © 2020 Pete Prokop. All rights reserved.
//
import Foundation
public final class RWLock {
private var lock: pthread_rwlock_t
// MARK: Lifecycle
deinit {
pthread_rwlock_destroy(&lock)
}
public init() {
lock = pthread_rwlock_t()
pthread_rwlock_init(&lock, nil)
}
// MARK: Public
public func writeLock() {
pthread_rwlock_wrlock(&lock)
}
public func readLock() {
pthread_rwlock_rdlock(&lock)
}
public func unlock() {
pthread_rwlock_unlock(&lock)
}
}

View File

@ -0,0 +1,394 @@
import Foundation
public class SGSimpleSettings {
public static let shared = SGSimpleSettings()
private init() {
setDefaultValues()
preCacheValues()
}
private func setDefaultValues() {
UserDefaults.standard.register(defaults: SGSimpleSettings.defaultValues)
}
private func preCacheValues() {
// let dispatchGroup = DispatchGroup()
let tasks = [
// { let _ = self.allChatsFolderPositionOverride },
{ let _ = self.allChatsHidden },
{ let _ = self.hideTabBar },
{ let _ = self.bottomTabStyle },
{ let _ = self.compactChatList },
{ let _ = self.compactFolderNames },
{ let _ = self.disableSwipeToRecordStory },
{ let _ = self.rememberLastFolder },
{ let _ = self.quickTranslateButton },
{ let _ = self.stickerSize },
{ let _ = self.stickerTimestamp },
{ let _ = self.hideReactions },
{ let _ = self.disableGalleryCamera },
{ let _ = self.disableSendAsButton },
{ let _ = self.disableSnapDeletionEffect },
{ let _ = self.startTelescopeWithRearCam },
{ let _ = self.hideRecordingButton }
]
tasks.forEach { task in
DispatchQueue.global(qos: .background).async(/*group: dispatchGroup*/) {
task()
}
}
// dispatchGroup.notify(queue: DispatchQueue.main) {}
}
public enum Keys: String, CaseIterable {
case hidePhoneInSettings
case showTabNames
case startTelescopeWithRearCam
case accountColorsSaturation
case uploadSpeedBoost
case downloadSpeedBoost
case bottomTabStyle
case rememberLastFolder
case lastAccountFolders
case localDNSForProxyHost
case sendLargePhotos
case outgoingPhotoQuality
case storyStealthMode
case canUseStealthMode
case disableSwipeToRecordStory
case quickTranslateButton
case outgoingLanguageTranslation
case hideReactions
case showRepostToStory
case contextShowSelectFromUser
case contextShowSaveToCloud
case contextShowRestrict
// case contextShowBan
case contextShowHideForwardName
case contextShowReport
case contextShowReply
case contextShowPin
case contextShowSaveMedia
case contextShowMessageReplies
case contextShowJson
case disableScrollToNextChannel
case disableScrollToNextTopic
case disableChatSwipeOptions
case disableGalleryCamera
case disableSendAsButton
case disableSnapDeletionEffect
case stickerSize
case stickerTimestamp
case hideRecordingButton
case hideTabBar
case showDC
case showCreationDate
case showRegDate
case regDateCache
case compactChatList
case compactFolderNames
case allChatsTitleLengthOverride
// case allChatsFolderPositionOverride
case allChatsHidden
case defaultEmojisFirst
case messageDoubleTapActionOutgoing
case wideChannelPosts
case forceEmojiTab
case forceBuiltInMic
}
public enum DownloadSpeedBoostValues: String, CaseIterable {
case none
case medium
case maximum
}
public enum BottomTabStyleValues: String, CaseIterable {
case telegram
case ios
}
public enum AllChatsTitleLengthOverride: String, CaseIterable {
case none
case short
case long
}
public enum AllChatsFolderPositionOverride: String, CaseIterable {
case none
case last
case hidden
}
public enum MessageDoubleTapAction: String, CaseIterable {
case `default`
case none
case edit
}
public static let defaultValues: [String: Any] = [
Keys.hidePhoneInSettings.rawValue: true,
Keys.showTabNames.rawValue: true,
Keys.startTelescopeWithRearCam.rawValue: false,
Keys.accountColorsSaturation.rawValue: 100,
Keys.uploadSpeedBoost.rawValue: false,
Keys.downloadSpeedBoost.rawValue: DownloadSpeedBoostValues.none.rawValue,
Keys.rememberLastFolder.rawValue: false,
Keys.bottomTabStyle.rawValue: BottomTabStyleValues.telegram.rawValue,
Keys.lastAccountFolders.rawValue: [:],
Keys.localDNSForProxyHost.rawValue: false,
Keys.sendLargePhotos.rawValue: false,
Keys.outgoingPhotoQuality.rawValue: 70,
Keys.storyStealthMode.rawValue: false,
Keys.canUseStealthMode.rawValue: true,
Keys.disableSwipeToRecordStory.rawValue: false,
Keys.quickTranslateButton.rawValue: false,
Keys.outgoingLanguageTranslation.rawValue: [:],
Keys.hideReactions.rawValue: false,
Keys.showRepostToStory.rawValue: true,
Keys.contextShowSelectFromUser.rawValue: true,
Keys.contextShowSaveToCloud.rawValue: true,
Keys.contextShowRestrict.rawValue: true,
// Keys.contextShowBan.rawValue: true,
Keys.contextShowHideForwardName.rawValue: true,
Keys.contextShowReport.rawValue: true,
Keys.contextShowReply.rawValue: true,
Keys.contextShowPin.rawValue: true,
Keys.contextShowSaveMedia.rawValue: true,
Keys.contextShowMessageReplies.rawValue: true,
Keys.contextShowJson.rawValue: false,
Keys.disableScrollToNextChannel.rawValue: false,
Keys.disableScrollToNextTopic.rawValue: false,
Keys.disableChatSwipeOptions.rawValue: false,
Keys.disableGalleryCamera.rawValue: false,
Keys.disableSendAsButton.rawValue: false,
Keys.disableSnapDeletionEffect.rawValue: false,
Keys.stickerSize.rawValue: 100,
Keys.stickerTimestamp.rawValue: true,
Keys.hideRecordingButton.rawValue: false,
Keys.hideTabBar.rawValue: false,
Keys.showDC.rawValue: false,
Keys.showCreationDate.rawValue: true,
Keys.showRegDate.rawValue: true,
Keys.regDateCache.rawValue: [:],
Keys.compactChatList.rawValue: false,
Keys.compactFolderNames.rawValue: false,
Keys.allChatsTitleLengthOverride.rawValue: AllChatsTitleLengthOverride.none.rawValue,
// Keys.allChatsFolderPositionOverride.rawValue: AllChatsFolderPositionOverride.none.rawValue
Keys.allChatsHidden.rawValue: false,
Keys.defaultEmojisFirst.rawValue: false,
Keys.messageDoubleTapActionOutgoing.rawValue: MessageDoubleTapAction.default.rawValue,
Keys.wideChannelPosts.rawValue: false,
Keys.forceEmojiTab.rawValue: false,
]
@UserDefault(key: Keys.hidePhoneInSettings.rawValue)
public var hidePhoneInSettings: Bool
@UserDefault(key: Keys.showTabNames.rawValue)
public var showTabNames: Bool
@UserDefault(key: Keys.startTelescopeWithRearCam.rawValue)
public var startTelescopeWithRearCam: Bool
@UserDefault(key: Keys.accountColorsSaturation.rawValue)
public var accountColorsSaturation: Int32
@UserDefault(key: Keys.uploadSpeedBoost.rawValue)
public var uploadSpeedBoost: Bool
@UserDefault(key: Keys.downloadSpeedBoost.rawValue)
public var downloadSpeedBoost: String
@UserDefault(key: Keys.rememberLastFolder.rawValue)
public var rememberLastFolder: Bool
@UserDefault(key: Keys.bottomTabStyle.rawValue)
public var bottomTabStyle: String
public var lastAccountFolders = UserDefaultsBackedDictionary<String, Int32>(userDefaultsKey: Keys.lastAccountFolders.rawValue, threadSafe: false)
@UserDefault(key: Keys.localDNSForProxyHost.rawValue)
public var localDNSForProxyHost: Bool
@UserDefault(key: Keys.sendLargePhotos.rawValue)
public var sendLargePhotos: Bool
@UserDefault(key: Keys.outgoingPhotoQuality.rawValue)
public var outgoingPhotoQuality: Int32
@UserDefault(key: Keys.storyStealthMode.rawValue)
public var storyStealthMode: Bool
@UserDefault(key: Keys.canUseStealthMode.rawValue)
public var canUseStealthMode: Bool
@UserDefault(key: Keys.disableSwipeToRecordStory.rawValue)
public var disableSwipeToRecordStory: Bool
@UserDefault(key: Keys.quickTranslateButton.rawValue)
public var quickTranslateButton: Bool
public var outgoingLanguageTranslation = UserDefaultsBackedDictionary<String, String>(userDefaultsKey: Keys.outgoingLanguageTranslation.rawValue, threadSafe: false)
@UserDefault(key: Keys.hideReactions.rawValue)
public var hideReactions: Bool
@UserDefault(key: Keys.showRepostToStory.rawValue)
public var showRepostToStory: Bool
@UserDefault(key: Keys.contextShowRestrict.rawValue)
public var contextShowRestrict: Bool
/*@UserDefault(key: Keys.contextShowBan.rawValue)
public var contextShowBan: Bool*/
@UserDefault(key: Keys.contextShowSelectFromUser.rawValue)
public var contextShowSelectFromUser: Bool
@UserDefault(key: Keys.contextShowSaveToCloud.rawValue)
public var contextShowSaveToCloud: Bool
@UserDefault(key: Keys.contextShowHideForwardName.rawValue)
public var contextShowHideForwardName: Bool
@UserDefault(key: Keys.contextShowReport.rawValue)
public var contextShowReport: Bool
@UserDefault(key: Keys.contextShowReply.rawValue)
public var contextShowReply: Bool
@UserDefault(key: Keys.contextShowPin.rawValue)
public var contextShowPin: Bool
@UserDefault(key: Keys.contextShowSaveMedia.rawValue)
public var contextShowSaveMedia: Bool
@UserDefault(key: Keys.contextShowMessageReplies.rawValue)
public var contextShowMessageReplies: Bool
@UserDefault(key: Keys.contextShowJson.rawValue)
public var contextShowJson: Bool
@UserDefault(key: Keys.disableScrollToNextChannel.rawValue)
public var disableScrollToNextChannel: Bool
@UserDefault(key: Keys.disableScrollToNextTopic.rawValue)
public var disableScrollToNextTopic: Bool
@UserDefault(key: Keys.disableChatSwipeOptions.rawValue)
public var disableChatSwipeOptions: Bool
@UserDefault(key: Keys.disableGalleryCamera.rawValue)
public var disableGalleryCamera: Bool
@UserDefault(key: Keys.disableSendAsButton.rawValue)
public var disableSendAsButton: Bool
@UserDefault(key: Keys.disableSnapDeletionEffect.rawValue)
public var disableSnapDeletionEffect: Bool
@UserDefault(key: Keys.stickerSize.rawValue)
public var stickerSize: Int32
@UserDefault(key: Keys.stickerTimestamp.rawValue)
public var stickerTimestamp: Bool
@UserDefault(key: Keys.hideRecordingButton.rawValue)
public var hideRecordingButton: Bool
@UserDefault(key: Keys.hideTabBar.rawValue)
public var hideTabBar: Bool
@UserDefault(key: Keys.showDC.rawValue)
public var showDC: Bool
@UserDefault(key: Keys.showCreationDate.rawValue)
public var showCreationDate: Bool
@UserDefault(key: Keys.showRegDate.rawValue)
public var showRegDate: Bool
public var regDateCache = UserDefaultsBackedDictionary<String, Data>(userDefaultsKey: Keys.regDateCache.rawValue, threadSafe: false)
@UserDefault(key: Keys.compactChatList.rawValue)
public var compactChatList: Bool
@UserDefault(key: Keys.compactFolderNames.rawValue)
public var compactFolderNames: Bool
@UserDefault(key: Keys.allChatsTitleLengthOverride.rawValue)
public var allChatsTitleLengthOverride: String
//
// @UserDefault(key: Keys.allChatsFolderPositionOverride.rawValue)
// public var allChatsFolderPositionOverride: String
@UserDefault(key: Keys.allChatsHidden.rawValue)
public var allChatsHidden: Bool
@UserDefault(key: Keys.defaultEmojisFirst.rawValue)
public var defaultEmojisFirst: Bool
@UserDefault(key: Keys.messageDoubleTapActionOutgoing.rawValue)
public var messageDoubleTapActionOutgoing: String
@UserDefault(key: Keys.wideChannelPosts.rawValue)
public var wideChannelPosts: Bool
@UserDefault(key: Keys.forceEmojiTab.rawValue)
public var forceEmojiTab: Bool
@UserDefault(key: Keys.forceBuiltInMic.rawValue)
public var forceBuiltInMic: Bool
}
extension SGSimpleSettings {
public var isStealthModeEnabled: Bool {
return storyStealthMode && canUseStealthMode
}
public static func makeOutgoingLanguageTranslationKey(accountId: Int64, peerId: Int64) -> String {
return "\(accountId):\(peerId)"
}
}
public func getSGDownloadPartSize(_ default: Int64) -> Int64 {
let currentDownloadSetting = SGSimpleSettings.shared.downloadSpeedBoost
switch (currentDownloadSetting) {
case SGSimpleSettings.DownloadSpeedBoostValues.medium.rawValue:
return 512 * 1024
case SGSimpleSettings.DownloadSpeedBoostValues.maximum.rawValue:
return 1024 * 1024
default:
return `default`
}
}
public func getSGMaxPendingParts(_ default: Int) -> Int {
let currentDownloadSetting = SGSimpleSettings.shared.downloadSpeedBoost
switch (currentDownloadSetting) {
case SGSimpleSettings.DownloadSpeedBoostValues.medium.rawValue:
return 8
case SGSimpleSettings.DownloadSpeedBoostValues.maximum.rawValue:
return 12
default:
return `default`
}
}
public func sgUseShortAllChatsTitle(_ default: Bool) -> Bool {
let currentOverride = SGSimpleSettings.shared.allChatsTitleLengthOverride
switch (currentOverride) {
case SGSimpleSettings.AllChatsTitleLengthOverride.short.rawValue:
return true
case SGSimpleSettings.AllChatsTitleLengthOverride.long.rawValue:
return false
default:
return `default`
}
}

View File

@ -0,0 +1,406 @@
import Foundation
public protocol AllowedUserDefaultTypes {}
/* // This one is more painful than helpful
extension Bool: AllowedUserDefaultTypes {}
extension String: AllowedUserDefaultTypes {}
extension Int: AllowedUserDefaultTypes {}
extension Int32: AllowedUserDefaultTypes {}
extension Double: AllowedUserDefaultTypes {}
extension Float: AllowedUserDefaultTypes {}
extension Data: AllowedUserDefaultTypes {}
extension URL: AllowedUserDefaultTypes {}
//extension Dictionary<String, Any>: AllowedUserDefaultTypes {}
extension Array: AllowedUserDefaultTypes where Element: AllowedUserDefaultTypes {}
*/
// Does not support Optional types due to caching
@propertyWrapper
public class UserDefault<T> /*where T: AllowedUserDefaultTypes*/ {
public let key: String
public let userDefaults: UserDefaults
private var cachedValue: T?
public init(key: String, userDefaults: UserDefaults = .standard) {
self.key = key
self.userDefaults = userDefaults
}
public var wrappedValue: T {
get {
#if DEBUG && false
SGtrace("UD.\(key)", what: "GET")
#endif
if let strongCachedValue = cachedValue {
#if DEBUG && false
SGtrace("UD", what: "CACHED \(key) \(strongCachedValue)")
#endif
return strongCachedValue
}
cachedValue = readFromUserDefaults()
#if DEBUG
SGtrace("UD.\(key)", what: "EXTRACTED: \(cachedValue!)")
#endif
return cachedValue!
}
set {
cachedValue = newValue
#if DEBUG
SGtrace("UD.\(key)", what: "CACHE UPDATED \(cachedValue!)")
#endif
userDefaults.set(newValue, forKey: key)
}
}
fileprivate func readFromUserDefaults() -> T {
switch T.self {
case is Bool.Type:
return (userDefaults.bool(forKey: key) as! T)
case is String.Type:
return (userDefaults.string(forKey: key) as! T)
case is Int32.Type:
return (Int32(exactly: userDefaults.integer(forKey: key)) as! T)
case is Int.Type:
return (userDefaults.integer(forKey: key) as! T)
case is Double.Type:
return (userDefaults.double(forKey: key) as! T)
case is Float.Type:
return (userDefaults.float(forKey: key) as! T)
case is Data.Type:
return (userDefaults.data(forKey: key) as! T)
case is URL.Type:
return (userDefaults.url(forKey: key) as! T)
case is Array<String>.Type:
return (userDefaults.stringArray(forKey: key) as! T)
case is Array<Any>.Type:
return (userDefaults.array(forKey: key) as! T)
default:
fatalError("Unsupported UserDefault type \(T.self)")
// cachedValue = (userDefaults.object(forKey: key) as! T)
}
}
}
//public class AtomicUserDefault<T>: UserDefault<T> {
// private let atomicCachedValue: AtomicWrapper<T?> = AtomicWrapper(value: nil)
//
// public override var wrappedValue: T {
// get {
// return atomicCachedValue.modify({ value in
// if let strongValue = value {
// return strongValue
// }
// return self.readFromUserDefaults()
// })!
// }
// set {
// let _ = atomicCachedValue.modify({ _ in
// userDefaults.set(newValue, forKey: key)
// return newValue
// })
// }
// }
//}
// Based on ConcurrentDictionary.swift from https://github.com/peterprokop/SwiftConcurrentCollections
/// Thread-safe UserDefaults dictionary wrapper
/// - Important: Note that this is a `class`, i.e. reference (not value) type
/// - Important: Key can only be String type
public class UserDefaultsBackedDictionary<Key: Hashable, Value> {
public let userDefaultsKey: String
public let userDefaults: UserDefaults
private var container: [Key: Value]? = nil
private let rwlock = RWLock()
private let threadSafe: Bool
public var keys: [Key] {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "KEYS")
#endif
let result: [Key]
if threadSafe {
rwlock.readLock()
}
if container == nil {
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "EXTRACTED: \(container!)")
#endif
} else {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "FROM CACHE: \(container!)")
#endif
}
result = Array(container!.keys)
if threadSafe {
rwlock.unlock()
}
return result
}
public var values: [Value] {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "VALUES")
#endif
let result: [Value]
if threadSafe {
rwlock.readLock()
}
if container == nil {
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "EXTRACTED: \(container!)")
#endif
} else {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "FROM CACHE: \(container!)")
#endif
}
result = Array(container!.values)
if threadSafe {
rwlock.unlock()
}
return result
}
public init(userDefaultsKey: String, userDefaults: UserDefaults = .standard, threadSafe: Bool) {
self.userDefaultsKey = userDefaultsKey
self.userDefaults = userDefaults
self.threadSafe = threadSafe
}
/// Sets the value for key
///
/// - Parameters:
/// - value: The value to set for key
/// - key: The key to set value for
public func set(value: Value, forKey key: Key) {
if threadSafe {
rwlock.writeLock()
}
_set(value: value, forKey: key)
if threadSafe {
rwlock.unlock()
}
}
@discardableResult
public func remove(_ key: Key) -> Value? {
let result: Value?
if threadSafe {
rwlock.writeLock()
}
result = _remove(key)
if threadSafe {
rwlock.unlock()
}
return result
}
@discardableResult
public func removeValue(forKey: Key) -> Value? {
return self.remove(forKey)
}
public func contains(_ key: Key) -> Bool {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "CONTAINS")
#endif
let result: Bool
if threadSafe {
rwlock.readLock()
}
if container == nil {
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "EXTRACTED: \(container!)")
#endif
} else {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "FROM CACHE: \(container!)")
#endif
}
result = container!.index(forKey: key) != nil
if threadSafe {
rwlock.unlock()
}
return result
}
public func value(forKey key: Key) -> Value? {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "VALUE")
#endif
let result: Value?
if threadSafe {
rwlock.readLock()
}
if container == nil {
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "EXTRACTED: \(container!)")
#endif
} else {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "FROM CACHE: \(container!)")
#endif
}
result = container![key]
if threadSafe {
rwlock.unlock()
}
return result
}
public func mutateValue(forKey key: Key, mutation: (Value) -> Value) {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "MUTATE")
#endif
if threadSafe {
rwlock.writeLock()
}
if container == nil {
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "EXTRACTED: \(container!)")
#endif
} else {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "FROM CACHE: \(container!)")
#endif
}
if let value = container![key] {
container![key] = mutation(value)
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "UPDATING CACHE \(key): \(value), \(container!)")
#endif
userDefaultsContainer = container!
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "CACHE UPDATED \(key): \(value), \(container!)")
#endif
}
if threadSafe {
rwlock.unlock()
}
}
public var isEmpty: Bool {
return self.keys.isEmpty
}
// MARK: Subscript
public subscript(key: Key) -> Value? {
get {
return value(forKey: key)
}
set {
if threadSafe {
rwlock.writeLock()
}
defer {
if threadSafe {
rwlock.unlock()
}
}
guard let newValue = newValue else {
_remove(key)
return
}
_set(value: newValue, forKey: key)
}
}
// MARK: Private
@inline(__always)
private func _set(value: Value, forKey key: Key) {
if container == nil {
container = userDefaultsContainer
}
self.container![key] = value
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "UPDATING CACHE \(key): \(value), \(container!)")
#endif
userDefaultsContainer = container!
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "CACHE UPDATED \(key): \(value), \(container!)")
#endif
}
@inline(__always)
@discardableResult
private func _remove(_ key: Key) -> Value? {
if container == nil {
container = userDefaultsContainer
}
guard let index = container!.index(forKey: key) else { return nil }
let tuple = container!.remove(at: index)
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "UPDATING CACHE REMOVE \(key) \(container!)")
#endif
userDefaultsContainer = container!
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "CACHE UPDATED REMOVED \(key) \(container!)")
#endif
return tuple.value
}
private var userDefaultsContainer: [Key: Value] {
get {
return userDefaults.dictionary(forKey: userDefaultsKey) as! [Key: Value]
}
set {
userDefaults.set(newValue, forKey: userDefaultsKey)
}
}
public func drop() {
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "DROPPING")
#endif
if threadSafe {
rwlock.writeLock()
}
userDefaults.removeObject(forKey: userDefaultsKey)
container = userDefaultsContainer
#if DEBUG
SGtrace("UD.\(userDefaultsKey)\(threadSafe ? "-ts" : "")", what: "DROPPED: \(container!)")
#endif
if threadSafe {
rwlock.unlock()
}
}
}
#if DEBUG
private let queue = DispatchQueue(label: "app.swiftgram.ios.trace", qos: .utility)
public func SGtrace(_ domain: String, what: @autoclosure() -> String) {
let string = what()
var rawTime = time_t()
time(&rawTime)
var timeinfo = tm()
localtime_r(&rawTime, &timeinfo)
var curTime = timeval()
gettimeofday(&curTime, nil)
let seconds = Int(curTime.tv_sec % 60) // Extracting the current second
let microseconds = curTime.tv_usec // Full microsecond precision
queue.async {
let result = String(format: "[%@] %d-%d-%d %02d:%02d:%02d.%06d %@", arguments: [domain, Int(timeinfo.tm_year) + 1900, Int(timeinfo.tm_mon + 1), Int(timeinfo.tm_mday), Int(timeinfo.tm_hour), Int(timeinfo.tm_min), seconds, microseconds, string])
print(result)
}
}
#endif

27
Swiftgram/SGStrings/BUILD Normal file
View File

@ -0,0 +1,27 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SGStrings",
module_name = "SGStrings",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AppBundle:AppBundle",
"//Swiftgram/SGLogging:SGLogging"
],
visibility = [
"//visibility:public",
],
)
filegroup(
name = "SGLocalizableStrings",
srcs = glob(["Strings/*.lproj/SGLocalizable.strings"]),
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,121 @@
import Foundation
// Assuming NGLogging and AppBundle are custom modules, they are imported here.
import SGLogging
import AppBundle
public let SGFallbackLocale = "en"
public class SGLocalizationManager {
public static let shared = SGLocalizationManager()
private let appBundle: Bundle
private var localizations: [String: [String: String]] = [:]
private var webLocalizations: [String: [String: String]] = [:]
private let fallbackMappings: [String: String] = [
// "from": "to"
"zh-hant": "zh-hans",
"be": "ru",
"nb": "no",
"ckb": "ku",
"sdh": "ku"
]
private init(fetchLocale: String = SGFallbackLocale) {
self.appBundle = getAppBundle()
// Iterating over all the app languages and loading SGLocalizable.strings
self.appBundle.localizations.forEach { locale in
if locale != "Base" {
localizations[locale] = loadLocalDictionary(for: locale)
}
}
// Downloading one specific locale
self.downloadLocale(fetchLocale)
}
public func localizedString(_ key: String, _ locale: String = SGFallbackLocale, args: CVarArg...) -> String {
let sanitizedLocale = self.sanitizeLocale(locale)
if let localizedString = findLocalizedString(forKey: key, inLocale: sanitizedLocale) {
if args.isEmpty {
return String(format: localizedString)
} else {
return String(format: localizedString, arguments: args)
}
}
SGLogger.shared.log("Strings", "Missing string for key: \(key) in locale: \(locale)")
return key
}
private func loadLocalDictionary(for locale: String) -> [String: String] {
guard let path = self.appBundle.path(forResource: "SGLocalizable", ofType: "strings", inDirectory: nil, forLocalization: locale) else {
// SGLogger.shared.log("Localization", "Unable to find path for locale: \(locale)")
return [:]
}
guard let dictionary = NSDictionary(contentsOf: URL(fileURLWithPath: path)) as? [String: String] else {
// SGLogger.shared.log("Localization", "Unable to load dictionary for locale: \(locale)")
return [:]
}
return dictionary
}
public func downloadLocale(_ locale: String) {
let sanitizedLocale = self.sanitizeLocale(locale)
guard let url = URL(string: self.getStringsUrl(for: sanitizedLocale)) else {
SGLogger.shared.log("Strings", "Invalid URL for locale: \(sanitizedLocale)")
return
}
DispatchQueue.global(qos: .background).async {
if let localeDict = NSDictionary(contentsOf: url) as? [String: String] {
DispatchQueue.main.async {
self.webLocalizations[sanitizedLocale] = localeDict
SGLogger.shared.log("Strings", "Successfully downloaded locale \(sanitizedLocale)")
}
} else {
SGLogger.shared.log("Strings", "Failed to download \(sanitizedLocale)")
}
}
}
private func sanitizeLocale(_ locale: String) -> String {
var sanitizedLocale = locale
let rawSuffix = "-raw"
if locale.hasSuffix(rawSuffix) {
sanitizedLocale = String(locale.dropLast(rawSuffix.count))
}
if sanitizedLocale == "pt-br" {
sanitizedLocale = "pt"
} else if sanitizedLocale == "nb" {
sanitizedLocale = "no"
}
return sanitizedLocale
}
private func findLocalizedString(forKey key: String, inLocale locale: String) -> String? {
if let string = self.webLocalizations[locale]?[key], !string.isEmpty {
return string
}
if let string = self.localizations[locale]?[key], !string.isEmpty {
return string
}
if let fallbackLocale = self.fallbackMappings[locale] {
return self.findLocalizedString(forKey: key, inLocale: fallbackLocale)
}
return self.localizations[SGFallbackLocale]?[key]
}
private func getStringsUrl(for locale: String) -> String {
return "https://raw.githubusercontent.com/Swiftgram/Telegram-iOS/master/Swiftgram/SGStrings/Strings/\(locale).lproj/SGLocalizable.strings"
}
}
public let i18n = SGLocalizationManager.shared.localizedString

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Inhoudinstellings";
"Settings.Tabs.Header" = "OORTJIES";
"Settings.Tabs.HideTabBar" = "Versteek Tabbalk";
"Settings.Tabs.ShowContacts" = "Wys Kontak Oortjie";
"Settings.Tabs.ShowNames" = "Wys oortjiename";
"Settings.Folders.BottomTab" = "Lêers onderaan";
"Settings.Folders.BottomTabStyle" = "Bodem Lêerstyl";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Versteek \"%@\"";
"Settings.Folders.RememberLast" = "Maak laaste lêer oop";
"Settings.Folders.RememberLast.Notice" = "Swiftgram sal die laaste gebruikte lêer oopmaak na herbegin of rekeningwissel.";
"Settings.Folders.CompactNames" = "Kleiner spasie";
"Settings.Folders.AllChatsTitle" = "\"Alle Chats\" titel";
"Settings.Folders.AllChatsTitle.short" = "Kort";
"Settings.Folders.AllChatsTitle.long" = "Lank";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Verstek";
"Settings.ChatList.Header" = "CHATLYS";
"Settings.CompactChatList" = "Kompakte Chatlys";
"Settings.Profiles.Header" = "PROFIELE";
"Settings.Stories.Hide" = "Versteek Stories";
"Settings.Stories.WarnBeforeView" = "Vra voor besigtiging";
"Settings.Stories.DisableSwipeToRecord" = "Deaktiveer swiep om op te neem";
"Settings.Translation.QuickTranslateButton" = "Vinnige Vertaalknoppie";
"Stories.Warning.Author" = "Outeur";
"Stories.Warning.ViewStory" = "Besigtig Storie?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ SAL KAN SIEN dat jy hul Storie besigtig het.";
"Stories.Warning.NoticeStealth" = "%@ Sal nie kan sien dat jy hul Storie besigtig het nie.";
"Settings.Photo.Quality.Notice" = "Kwaliteit van uitgaande foto's en fotostories.";
"Settings.Photo.SendLarge" = "Stuur groot foto's";
"Settings.Photo.SendLarge.Notice" = "Verhoog die sybeperking op saamgeperste beelde tot 2560px.";
"Settings.VideoNotes.Header" = "RONDE VIDEOS";
"Settings.VideoNotes.StartWithRearCam" = "Begin met agterkamera";
"Settings.CustomColors.Header" = "REKENING KLEURE";
"Settings.CustomColors.Saturation" = "VERSATIGING";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Stel versadiging op 0%% om rekening kleure te deaktiveer.";
"Settings.UploadsBoost" = "Oplaai versterking";
"Settings.DownloadsBoost" = "Aflaai versterking";
"Settings.DownloadsBoost.none" = "Gedeaktiveer";
"Settings.DownloadsBoost.medium" = "Medium";
"Settings.DownloadsBoost.maximum" = "Maksimum";
"Settings.ShowProfileID" = "Wys profiel ID";
"Settings.ShowDC" = "Wys Data Sentrum";
"Settings.ShowCreationDate" = "Wys Geskep Datum van Geselskap";
"Settings.ShowCreationDate.Notice" = "Die skeppingsdatum mag onbekend wees vir sommige gesprekke.";
"Settings.ShowRegDate" = "Wys Registrasie Datum";
"Settings.ShowRegDate.Notice" = "Die registrasiedatum is benaderend.";
"Settings.SendWithReturnKey" = "Stuur met \"terug\" sleutel";
"Settings.HidePhoneInSettingsUI" = "Versteek telefoon in instellings";
"Settings.HidePhoneInSettingsUI.Notice" = "Dit sal slegs jou telefoonnommer versteek vanaf die instellingskoppelvlak. Om dit vir ander te versteek, gaan na Privaatheid en Sekuriteit.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "As weg vir 5 sekondes";
"ProxySettings.UseSystemDNS" = "Gebruik stelsel DNS";
"ProxySettings.UseSystemDNS.Notice" = "Gebruik stelsel DNS om uitvaltyd te omseil as jy nie toegang tot Google DNS het nie";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Jy **het nie nodig** %@ nie!";
"Common.RestartRequired" = "Herbegin benodig";
"Common.RestartNow" = "Herbegin Nou";
"Common.OpenTelegram" = "Maak Telegram oop";
"Common.UseTelegramForPremium" = "Let daarop dat om Telegram Premium te kry, moet jy die amptelike Telegram-app gebruik. Nadat jy Telegram Premium verkry het, sal al sy funksies beskikbaar word in Swiftgram.";
"Message.HoldToShowOrReport" = "Hou vas om te Wys of te Rapporteer.";
"Auth.AccountBackupReminder" = "Maak seker jy het 'n rugsteun toegangsmetode. Hou 'n SIM vir SMS of 'n addisionele sessie aangemeld om te verhoed dat jy uitgesluit word.";
"Auth.UnofficialAppCodeTitle" = "Jy kan die kode slegs met die amptelike app kry";
"Settings.SmallReactions" = "Klein reaksies";
"Settings.HideReactions" = "Verberg Reaksies";
"ContextMenu.SaveToCloud" = "Stoor na Wolk";
"ContextMenu.SelectFromUser" = "Kies vanaf Outeur";
"Settings.ContextMenu" = "KONTEKSMENU";
"Settings.ContextMenu.Notice" = "Gedeaktiveerde inskrywings sal beskikbaar wees in die \"Swiftgram\" sub-menu.";
"Settings.ChatSwipeOptions" = "Chat List Swipe Options";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Trek na Volgende Ongelese Kanaal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Trek na Volgende Onderwerp";
"Settings.GalleryCamera" = "Camera in Gallery";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Button";
"Settings.SnapDeletionEffect" = "Message Deletion Effects";
"Settings.Stickers.Size" = "SIZE";
"Settings.Stickers.Timestamp" = "Show Timestamp";
"Settings.RecordingButton" = "Voice Recording Button";
"Settings.DefaultEmojisFirst" = "Prioritise standaard emojis";
"Settings.DefaultEmojisFirst.Notice" = "Wys standaard emojis voor premium op die emoji sleutelbord";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "geskep: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Sluit aan by %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Geregistreer";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dubbelklik om boodskap te wysig";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "إعدادات المحتوى";
"Settings.Tabs.Header" = "تبويبات";
"Settings.Tabs.HideTabBar" = "إخفاء شريط علامات التبويب";
"Settings.Tabs.ShowContacts" = "إظهار تبويب جهات الاتصال";
"Settings.Tabs.ShowNames" = "إظهار أسماء التبويبات";
"Settings.Folders.BottomTab" = "المجلدات في الأسفل";
"Settings.Folders.BottomTabStyle" = "نمط المجلدات السفلية";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "إخفاء \"%@\"";
"Settings.Folders.RememberLast" = "فتح المجلد الأخير";
"Settings.Folders.RememberLast.Notice" = "سيفتح Swiftgram آخر مجلد مستخدم عند إعادة تشغيل التطبيق أو تبديل الحسابات.";
"Settings.Folders.CompactNames" = "مسافات أصغر";
"Settings.Folders.AllChatsTitle" = "عنوان \"كل المحادثات\"";
"Settings.Folders.AllChatsTitle.short" = "قصير";
"Settings.Folders.AllChatsTitle.long" = "طويل";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "الافتراضي";
"Settings.ChatList.Header" = "قائمة الفواصل";
"Settings.CompactChatList" = "قائمة الدردشة المدمجة";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "إخفاء الستوري";
"Settings.Stories.WarnBeforeView" = "اسأل قبل العرض";
"Settings.Stories.DisableSwipeToRecord" = "تعطيل السحب للتسجيل";
"Settings.Translation.QuickTranslateButton" = "زر الترجمة الفوري";
"Stories.Warning.Author" = "الكاتب";
"Stories.Warning.ViewStory" = "عرض القصة؟";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ WILL BE يتم إخبارهم بأنك شاهدت قصتهم.";
"Stories.Warning.NoticeStealth" = "%@ لن يتمكن من رؤية أنك شاهدت قصته.";
"Settings.Photo.Quality.Notice" = "جودة الصور والصور الصادرة والقصص.";
"Settings.Photo.SendLarge" = "إرسال صور كبيرة";
"Settings.Photo.SendLarge.Notice" = "زيادة الحد الجانبي للصور المضغوطة إلى 2560 بكسل.";
"Settings.VideoNotes.Header" = "فيديوهات مستديرة";
"Settings.VideoNotes.StartWithRearCam" = "البدء بالكاميرا الخلفية";
"Settings.CustomColors.Header" = "ألوان الحساب";
"Settings.CustomColors.Saturation" = "مستوى التشبع";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "تعيين التشبع إلى 0%% لتعطيل ألوان الحساب.";
"Settings.UploadsBoost" = "تعزيز التحميلات";
"Settings.DownloadsBoost" = "تعزيز التنزيلات";
"Settings.DownloadsBoost.none" = "تعطيل";
"Settings.DownloadsBoost.medium" = "متوسط";
"Settings.DownloadsBoost.maximum" = "الحد الاقصى";
"Settings.ShowProfileID" = "إظهار معرف الملف الشخصي ID";
"Settings.ShowDC" = "إظهار مركز البيانات";
"Settings.ShowCreationDate" = "إظهار تاريخ إنشاء المحادثة";
"Settings.ShowCreationDate.Notice" = "قد يكون تاريخ الإنشاء مفقوداً لبضع المحادثات.";
"Settings.ShowRegDate" = "إظهار تاريخ التسجيل";
"Settings.ShowRegDate.Notice" = "تاريخ التسجيل تقريبي.";
"Settings.SendWithReturnKey" = "إرسال مع مفتاح \"العودة\"";
"Settings.HidePhoneInSettingsUI" = "إخفاء الرقم من الإعدادات";
"Settings.HidePhoneInSettingsUI.Notice" = "سيتم اخفاء رقمك من التطبيق فقط. لأخفاءهُ من المستخدمين الآخرين، يرجى استخدام إعدادات الخصوصية.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "إذا كان بعيدا لمدة 5 ثوان";
"ProxySettings.UseSystemDNS" = "استخدم DNS النظام";
"ProxySettings.UseSystemDNS.Notice" = "استخدم نظام DNS لتجاوز المهلة إذا لم تكن لديك حق الوصول إلى Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "أنت **لا تحتاج** %@!";
"Common.RestartRequired" = "إعادة التشغيل مطلوب";
"Common.RestartNow" = "إعادة التشغيل الآن";
"Common.OpenTelegram" = "افتح Telegram";
"Common.UseTelegramForPremium" = "يُرجى ملاحظة أنه للحصول على Telegram Premium، يجب عليك استخدام تطبيق تيليجرام الرسمي. بمجرد حصولك على Telegram Premium، ستصبح جميع ميزاته متاحة في Swiftgram.";
"Message.HoldToShowOrReport" = "اضغط للعرض أو الإبلاغ.";
"Auth.AccountBackupReminder" = "تأكد من أن لديك طريقة الوصول إلى النسخ الاحتياطي. حافظ على شريحة SIM للرسائل القصيرة أو جلسة إضافية لتسجيل الدخول لتجنب أن تكون مغفلة.";
"Auth.UnofficialAppCodeTitle" = "يمكنك الحصول على الرمز فقط من خلال التطبيق الرسمي";
"Settings.SmallReactions" = "ردود أفعال صغيرة";
"Settings.HideReactions" = "إخفاء الردود";
"ContextMenu.SaveToCloud" = "الحفظ في السحابة";
"ContextMenu.SelectFromUser" = "حدد من المؤلف";
"Settings.ContextMenu" = "قائمة الإتصال";
"Settings.ContextMenu.Notice" = "المدخلات المعطلة ستكون متوفرة في القائمة الفرعية \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "خيارات التمرير لقائمة المحادثة";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "اسحب للقناة الغير مقروءة التالية";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "اسحب للموضوع التالي";
"Settings.GalleryCamera" = "الكاميرا في معرض الصور";
/* "Send Message As..." button */
"Settings.SendAsButton" = "زر \"%@\"";
"Settings.SnapDeletionEffect" = "تأثيرات حذف الرسالة";
"Settings.Stickers.Size" = "مقاس";
"Settings.Stickers.Timestamp" = "إظهار الطابع الزمني";
"Settings.RecordingButton" = "زر التسجيل الصوتي";
"Settings.DefaultEmojisFirst" = "الأفضلية للرموز التعبيرية القياسية";
"Settings.DefaultEmojisFirst.Notice" = "عرض الرموز التعبيرية القياسية قبل الرموز المتميزة في لوحة المفاتيح";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "تم إنشاؤه: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "انضم %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "مسجل";
"Settings.messageDoubleTapActionOutgoingEdit" = "اضغط مزدوجًا لتحرير الرسالة";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Configuració del Contingut";
"Settings.Tabs.Header" = "PESTANYES";
"Settings.Tabs.HideTabBar" = "Amagar barra de pestanyes";
"Settings.Tabs.ShowContacts" = "Mostrar Pestanya de Contactes";
"Settings.Tabs.ShowNames" = "Mostrar noms de les pestanyes";
"Settings.Folders.BottomTab" = "Carpetes a la part inferior";
"Settings.Folders.BottomTabStyle" = "Bottom Folders Style";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Amaga \"%@\"";
"Settings.Folders.RememberLast" = "Obrir l'última carpeta";
"Settings.Folders.RememberLast.Notice" = "Swiftgram obrirà l'última carpeta utilitzada després de reiniciar o canviar de compte.";
"Settings.Folders.CompactNames" = "Espaiat més petit";
"Settings.Folders.AllChatsTitle" = "Títol \"Tots els xats\"";
"Settings.Folders.AllChatsTitle.short" = "Curt";
"Settings.Folders.AllChatsTitle.long" = "Llarg";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Per defecte";
"Settings.ChatList.Header" = "LLISTA DE XATS";
"Settings.CompactChatList" = "Llista de xats compacta";
"Settings.Profiles.Header" = "PERFILS";
"Settings.Stories.Hide" = "Amagar Històries";
"Settings.Stories.WarnBeforeView" = "Preguntar abans de veure";
"Settings.Stories.DisableSwipeToRecord" = "Desactivar lliscar per enregistrar";
"Settings.Translation.QuickTranslateButton" = "Botó de Traducció Ràpida";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Veure Història?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ PODRÀ VEURE que has vist la seva Història.";
"Stories.Warning.NoticeStealth" = "%@ no podrà veure que has vist la seva Història.";
"Settings.Photo.Quality.Notice" = "Qualitat de les fotos sortints i històries de fotos.";
"Settings.Photo.SendLarge" = "Enviar fotos grans";
"Settings.Photo.SendLarge.Notice" = "Incrementar el límit de mida en imatges comprimides a 2560px.";
"Settings.VideoNotes.Header" = "VÍDEOS RODONS";
"Settings.VideoNotes.StartWithRearCam" = "Començar amb càmera posterior";
"Settings.CustomColors.Header" = "COLORS DEL COMPTE";
"Settings.CustomColors.Saturation" = "SATURACIÓ";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Estableix la saturació a 0%% per desactivar els colors del compte.";
"Settings.UploadsBoost" = "Millora de càrregues";
"Settings.DownloadsBoost" = "Millora de baixades";
"Settings.DownloadsBoost.none" = "Desactivat";
"Settings.DownloadsBoost.medium" = "Mitjà";
"Settings.DownloadsBoost.maximum" = "Màxim";
"Settings.ShowProfileID" = "Mostrar ID de perfil";
"Settings.ShowDC" = "Mostrar Data Center";
"Settings.ShowCreationDate" = "Mostrar Data de Creació de Xat";
"Settings.ShowCreationDate.Notice" = "La data de creació pot ser desconeguda per alguns xats.";
"Settings.ShowRegDate" = "Mostra la data d'inscripció";
"Settings.ShowRegDate.Notice" = "La data d'inscripció és aproximada.";
"Settings.SendWithReturnKey" = "Enviar amb clau \"retorn\"";
"Settings.HidePhoneInSettingsUI" = "Amagar telèfon en la interfície d'ajustos";
"Settings.HidePhoneInSettingsUI.Notice" = "Això només amagarà el teu número de telèfon de la interfície d'ajustos. Per amagar-lo als altres, ves a Privadesa i Seguretat.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Si no hi ha en 5 segons";
"ProxySettings.UseSystemDNS" = "Utilitzar DNS del sistema";
"ProxySettings.UseSystemDNS.Notice" = "Utilitzar DNS del sistema per evitar el temps d'espera si no tens accés a Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "No **necessites** %@!";
"Common.RestartRequired" = "Reinici requerit";
"Common.RestartNow" = "Reiniciar Ara";
"Common.OpenTelegram" = "Obrir Telegram";
"Common.UseTelegramForPremium" = "Recorda que per obtenir Telegram Premium, has d'utilitzar l'aplicació oficial de Telegram. Un cop hagis obtingut Telegram Premium, totes les seves funcions estaran disponibles a Swiftgram.";
"Message.HoldToShowOrReport" = "Mantingues per Mostrar o Informar.";
"Auth.AccountBackupReminder" = "Assegura't de tenir un mètode d'accés de reserva. Mantingues un SIM per a SMS o una sessió addicional registrada per evitar quedar bloquejat.";
"Auth.UnofficialAppCodeTitle" = "Només pots obtenir el codi amb l'aplicació oficial";
"Settings.SmallReactions" = "Petites reaccions";
"Settings.HideReactions" = "Amaga les reaccions";
"ContextMenu.SaveToCloud" = "Desar al Núvol";
"ContextMenu.SelectFromUser" = "Seleccionar de l'Autor";
"Settings.ContextMenu" = "MENÚ CONTEXTUAL";
"Settings.ContextMenu.Notice" = "Les entrades desactivades estaran disponibles al submenú \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "Opcions desplaçament de la llista de xats";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Arrossega cap al següent canal no llegit";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Arrosega cap al següent tema";
"Settings.GalleryCamera" = "Càmera a la galeria";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Botó";
"Settings.SnapDeletionEffect" = "Efectes d'eliminació de missatges";
"Settings.Stickers.Size" = "GRANOR";
"Settings.Stickers.Timestamp" = "Mostra l'estona";
"Settings.RecordingButton" = "Botó d'enregistrament de veu";
"Settings.DefaultEmojisFirst" = "Prioritzar emojis estàndard";
"Settings.DefaultEmojisFirst.Notice" = "Mostra emojis estàndard abans que premium al teclat emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "creada: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Unida a %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Inscrit";
"Settings.messageDoubleTapActionOutgoingEdit" = "Toqueu dues vegades per editar el missatge";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Nastavení obsahu";
"Settings.Tabs.Header" = "ZÁLOŽKY";
"Settings.Tabs.HideTabBar" = "Skrýt záložku";
"Settings.Tabs.ShowContacts" = "Zobrazit záložku kontaktů";
"Settings.Tabs.ShowNames" = "Zobrazit názvy záložek";
"Settings.Folders.BottomTab" = "Složky dole";
"Settings.Folders.BottomTabStyle" = "Styl dolní složky";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Skrýt \"%@\"";
"Settings.Folders.RememberLast" = "Otevřít poslední složku";
"Settings.Folders.RememberLast.Notice" = "Swiftgram otevře poslední použitou složku po restartu nebo přepnutí účtu.";
"Settings.Folders.CompactNames" = "Menší vzdálenost";
"Settings.Folders.AllChatsTitle" = "Název \"Všechny chaty\"";
"Settings.Folders.AllChatsTitle.short" = "Krátký";
"Settings.Folders.AllChatsTitle.long" = "Dlouhá";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Výchozí";
"Settings.ChatList.Header" = "CHAT SEZNAM";
"Settings.CompactChatList" = "Kompaktní seznam chatu";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Skrýt příběhy";
"Settings.Stories.WarnBeforeView" = "Upozornit před zobrazením";
"Settings.Stories.DisableSwipeToRecord" = "Zakázat přejetí prstem pro nahrávání";
"Settings.Translation.QuickTranslateButton" = "Tlačítko pro rychlý překlad";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Zobrazit příběh?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ BUDE VIDĚT, že jste si prohlédl jejich příběh.";
"Stories.Warning.NoticeStealth" = "%@ bude moci vidět, že jste si prohlédl jejich příběh.";
"Settings.Photo.Quality.Notice" = "Kvalita odchozích fotografií a foto-příběhů.";
"Settings.Photo.SendLarge" = "Poslat velké fotografie";
"Settings.Photo.SendLarge.Notice" = "Zvýšit limit velikosti komprimovaných obrázků na 2560px.";
"Settings.VideoNotes.Header" = "KRUHOVÁ VIDEA";
"Settings.VideoNotes.StartWithRearCam" = "Začít s zadní kamerou";
"Settings.CustomColors.Header" = "BARVY ÚČTU";
"Settings.CustomColors.Saturation" = "SYTOST";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Nastavit sytost na 0%% pro vypnutí barev účtu.";
"Settings.UploadsBoost" = "Zrychlení nahrávání";
"Settings.DownloadsBoost" = "Zrychlení stahování";
"Settings.DownloadsBoost.none" = "Vypnuto";
"Settings.DownloadsBoost.medium" = "Střední";
"Settings.DownloadsBoost.maximum" = "Maximální";
"Settings.ShowProfileID" = "Zobrazit ID profilu";
"Settings.ShowDC" = "Zobrazit Data Center";
"Settings.ShowCreationDate" = "Zobrazit datum vytvoření chatu";
"Settings.ShowCreationDate.Notice" = "Datum vytvoření chatu může být neznámé pro některé chaty.";
"Settings.ShowRegDate" = "Zobrazit datum registrace";
"Settings.ShowRegDate.Notice" = "Datum registrace je přibližné.";
"Settings.SendWithReturnKey" = "Poslat klávesou \"enter\"";
"Settings.HidePhoneInSettingsUI" = "Skrýt telefon v nastavení";
"Settings.HidePhoneInSettingsUI.Notice" = "Toto skryje vaše telefonní číslo pouze v nastavení rozhraní. Chcete-li je skryt před ostatními, přejděte na Soukromí a bezpečnost.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Zamknout za 5 sekund";
"ProxySettings.UseSystemDNS" = "Použít systémové DNS";
"ProxySettings.UseSystemDNS.Notice" = "Použít systémové DNS k obejití časového limitu, pokud nemáte přístup k Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Nepotřebujete **%@**!";
"Common.RestartRequired" = "Vyžadován restart";
"Common.RestartNow" = "Restartovat nyní";
"Common.OpenTelegram" = "Otevřít Telegram";
"Common.UseTelegramForPremium" = "Vezměte prosím na vědomí, že abyste získali Premium, musíte použít oficiální aplikaci Telegram . Jakmile získáte Telegram Premium, všechny jeho funkce budou k dispozici ve Swiftgramu.";
"Message.HoldToShowOrReport" = "Podržte pro zobrazení nebo nahlášení.";
"Auth.AccountBackupReminder" = "Ujistěte se, že máte záložní přístupovou metodu. Uchovávejte SIM pro SMS nebo další přihlášenou relaci, abyste předešli zamčení.";
"Auth.UnofficialAppCodeTitle" = "Kód můžete získat pouze s oficiální aplikací";
"Settings.SmallReactions" = "Malé reakce";
"Settings.HideReactions" = "Skrýt reakce";
"ContextMenu.SaveToCloud" = "Uložit do cloudu";
"ContextMenu.SelectFromUser" = "Vybrat od autora";
"Settings.ContextMenu" = "KONTEXTOVÉ MENU";
"Settings.ContextMenu.Notice" = "Zakázané položky budou dostupné v podmenu \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "Možnosti potáhnutí v seznamu chatu";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Táhnout na další nepřečtený kanál";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Přetáhněte na další téma";
"Settings.GalleryCamera" = "Fotoaparát v galerii";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Tlačítko \"%@\"";
"Settings.SnapDeletionEffect" = "Účinky odstranění zpráv";
"Settings.Stickers.Size" = "VELIKOST";
"Settings.Stickers.Timestamp" = "Zobrazit časové razítko";
"Settings.RecordingButton" = "Tlačítko nahrávání hlasu";
"Settings.DefaultEmojisFirst" = "Upřednostněte standardní emoji";
"Settings.DefaultEmojisFirst.Notice" = "Zobrazit standardní emoji před prémiovými na klávesnici s emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "vytvořeno: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Připojeno k %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrováno";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dvojitým klepnutím upravte zprávu";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Indholdindstillinger";
"Settings.Tabs.Header" = "Tabs";
"Settings.Tabs.HideTabBar" = "Skjul Tabbjælke";
"Settings.Tabs.ShowContacts" = "Kontakte Tab anzeigen";
"Settings.Tabs.ShowNames" = "Tabnamen anzeigen";
"Settings.Folders.BottomTab" = "Ordner - unten";
"Settings.Folders.BottomTabStyle" = "Bundmapper Stil";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Skjul \"%@\"";
"Settings.Folders.RememberLast" = "Åbn sidste mappe";
"Settings.Folders.RememberLast.Notice" = "Swiftgram vil åbne den sidst brugte mappe efter genstart eller konto skift.";
"Settings.Folders.CompactNames" = "Mindre afstand";
"Settings.Folders.AllChatsTitle" = "\"Alle Chats\" titel";
"Settings.Folders.AllChatsTitle.short" = "Kort";
"Settings.Folders.AllChatsTitle.long" = "Lang";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Standard";
"Settings.ChatList.Header" = "CHAT LISTE";
"Settings.CompactChatList" = "Kompakt Chatliste";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Skjul Historier";
"Settings.Stories.WarnBeforeView" = "Spørg før visning";
"Settings.Stories.DisableSwipeToRecord" = "Deaktiver swipe for at optage";
"Settings.Translation.QuickTranslateButton" = "Schnellübersetzen-Schaltfläche";
"Stories.Warning.Author" = "Forfatter";
"Stories.Warning.ViewStory" = "Se Historie?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ VIL KUNNE SE at du har set deres Historie.";
"Stories.Warning.NoticeStealth" = "%@ Vil ikke kunne se, at du har set deres Historie.";
"Settings.Photo.Quality.Notice" = "Kvalitet af udgående fotos og foto-historier.";
"Settings.Photo.SendLarge" = "Send store fotos";
"Settings.Photo.SendLarge.Notice" = "Forøg sidestørrelsesgrænsen på komprimerede billeder til 2560px.";
"Settings.VideoNotes.Header" = "RUNDE VIDEOS";
"Settings.VideoNotes.StartWithRearCam" = "Starte mit umgedrehter Kamera";
"Settings.CustomColors.Header" = "KONTOFARVER";
"Settings.CustomColors.Saturation" = "MÆTNING";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Indstil mætning til 0%% for at deaktivere konto farver.";
"Settings.UploadsBoost" = "Upload Boost";
"Settings.DownloadsBoost" = "Download Boost";
"Settings.DownloadsBoost.none" = "Deaktiveret";
"Settings.DownloadsBoost.medium" = "Mellem";
"Settings.DownloadsBoost.maximum" = "Maksimum";
"Settings.ShowProfileID" = "Profil-ID anzeigen";
"Settings.ShowDC" = "Vis Datacenter";
"Settings.ShowCreationDate" = "Vis Chattens Oprettelsesdato";
"Settings.ShowCreationDate.Notice" = "Oprettelsesdatoen kan være ukendt for nogle chats.";
"Settings.ShowRegDate" = "Vis Registreringsdato";
"Settings.ShowRegDate.Notice" = "Registreringsdatoen er omtrentlig.";
"Settings.SendWithReturnKey" = "Send med \"return\" tasten";
"Settings.HidePhoneInSettingsUI" = "Telefon in den Einstellungen ausblenden";
"Settings.HidePhoneInSettingsUI.Notice" = "Deine Nummer wird nur in der Benutzeroberfläche versteckt. Um sie vor anderen zu verbergen, verwende bitte die Privatsphäre-Einstellungen.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Hvis væk i 5 sekunder";
"ProxySettings.UseSystemDNS" = "Brug system DNS";
"ProxySettings.UseSystemDNS.Notice" = "Brug system DNS for at omgå timeout hvis du ikke har adgang til Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Du **behøver ikke** %@!";
"Common.RestartRequired" = "Genstart krævet";
"Common.RestartNow" = "Genstart Nu";
"Common.OpenTelegram" = "Åben Telegram";
"Common.UseTelegramForPremium" = "Bemærk venligst, at for at få Telegram Premium skal du bruge den officielle Telegram app. Når du har fået Telegram Premium, vil alle dens funktioner blive tilgængelige i Swiftgram.";
"Message.HoldToShowOrReport" = "Hold for at Vise eller Rapportere.";
"Auth.AccountBackupReminder" = "Sørg for, at du har en backup adgangsmetode. Behold et SIM til SMS eller en ekstra session logget ind for at undgå at blive låst ude.";
"Auth.UnofficialAppCodeTitle" = "Du kan kun få koden med den officielle app";
"Settings.SmallReactions" = "Små reaktioner";
"Settings.HideReactions" = "Skjul Reaktioner";
"ContextMenu.SaveToCloud" = "In Cloud speichern";
"ContextMenu.SelectFromUser" = "Vælg fra Forfatter";
"Settings.ContextMenu" = "KONTEKSTMENU";
"Settings.ContextMenu.Notice" = "Deaktiverede indgange vil være tilgængelige i \"Swiftgram\" undermenuen.";
"Settings.ChatSwipeOptions" = "Chat List Swipe Options";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Træk til Næste Ulæst Kanal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Træk for at gå til næste emne";
"Settings.GalleryCamera" = "Kamera i Galleri";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Knap";
"Settings.SnapDeletionEffect" = "Besked Sletnings Effekter";
"Settings.Stickers.Size" = "STØRRELSE";
"Settings.Stickers.Timestamp" = "Vis tidsstempel";
"Settings.RecordingButton" = "Lydoptageknap";
"Settings.DefaultEmojisFirst" = "Prioriter standard emojis";
"Settings.DefaultEmojisFirst.Notice" = "Vis standard emojis før premium i emoji-tastaturet";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "oprettet: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Tilmeldt %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registreret";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dobbelt tryk for at redigere besked";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Inhaltliche Einstellungen";
"Settings.Tabs.Header" = "Tabs";
"Settings.Tabs.HideTabBar" = "Tab-Leiste ausblenden";
"Settings.Tabs.ShowContacts" = "Kontakte Tab anzeigen";
"Settings.Tabs.ShowNames" = "Tabnamen anzeigen";
"Settings.Folders.BottomTab" = "Ordner unten";
"Settings.Folders.BottomTabStyle" = "Untere Ordner-Stil";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Verberge \"%@\"";
"Settings.Folders.RememberLast" = "Letzten Ordner öffnen";
"Settings.Folders.RememberLast.Notice" = "Swiftgram wird den zuletzt genutzten Order öffnen, wenn du den Account wechselst oder die App neustartest";
"Settings.Folders.CompactNames" = "Kleinerer Abstand";
"Settings.Folders.AllChatsTitle" = "Titel \"Alle Chats\"";
"Settings.Folders.AllChatsTitle.short" = "Kurze";
"Settings.Folders.AllChatsTitle.long" = "Lang";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Standard";
"Settings.ChatList.Header" = "CHAT LISTE";
"Settings.CompactChatList" = "Kompakte Chat-Liste";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Stories verbergen";
"Settings.Stories.WarnBeforeView" = "Vor dem Ansehen fragen";
"Settings.Stories.DisableSwipeToRecord" = "Zum aufnehmen wischen deaktivieren";
"Settings.Translation.QuickTranslateButton" = "Schnellübersetzen-Button";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Story ansehen?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ wird sehen können, dass du die Story angesehen hast.";
"Stories.Warning.NoticeStealth" = "%@ wird nicht sehen können, dass du die Story angesehen hast.";
"Settings.Photo.Quality.Notice" = "Qualität der gesendeten Fotos und Fotostorys";
"Settings.Photo.SendLarge" = "Sende große Fotos";
"Settings.Photo.SendLarge.Notice" = "Seitenlimit für komprimierte Bilder auf 2560px erhöhen";
"Settings.VideoNotes.Header" = "RUNDE VIDEOS";
"Settings.VideoNotes.StartWithRearCam" = "Starte mit umgedrehter Kamera";
"Settings.CustomColors.Header" = "ACCOUNT FARBEN";
"Settings.CustomColors.Saturation" = "SÄTTIGUNG";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Setze Sättigung auf 0%% um Kontofarben zu deaktivieren";
"Settings.UploadsBoost" = "Upload Beschleuniger";
"Settings.DownloadsBoost" = "Download Beschleuniger";
"Settings.DownloadsBoost.none" = "Deaktiviert";
"Settings.DownloadsBoost.medium" = "Mittel";
"Settings.DownloadsBoost.maximum" = "Maximum";
"Settings.ShowProfileID" = "Profil-ID anzeigen";
"Settings.ShowDC" = "Data Center anzeigen";
"Settings.ShowCreationDate" = "Chat-Erstellungsdatum anzeigen";
"Settings.ShowCreationDate.Notice" = "Das Erstellungsdatum kann für einige Chats unbekannt sein.";
"Settings.ShowRegDate" = "Anmeldedatum anzeigen";
"Settings.ShowRegDate.Notice" = "Das Registrierungsdatum ist ungefähr.";
"Settings.SendWithReturnKey" = "Mit \"Enter\" senden";
"Settings.HidePhoneInSettingsUI" = "Telefon in den Einstellungen ausblenden";
"Settings.HidePhoneInSettingsUI.Notice" = "Deine Nummer wird nur in der Benutzeroberfläche versteckt. Um sie vor anderen zu verbergen, verwende bitte die Privatsphäre-Einstellungen.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Falls 5 Sekunden inaktiv";
"ProxySettings.UseSystemDNS" = "Benutze System DNS";
"ProxySettings.UseSystemDNS.Notice" = "Benutze System DNS um Timeout zu umgehen, wenn du keinen Zugriff auf Google DNS hast";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Du brauchst %@ nicht!";
"Common.RestartRequired" = "Benötigt Neustart";
"Common.RestartNow" = "Jetzt neustarten";
"Common.OpenTelegram" = "Telegram öffnen";
"Common.UseTelegramForPremium" = "Bitte beachten Sie, dass Sie die offizielle Telegram-App verwenden müssen, um Telegram Premium zu erhalten. Sobald Sie Telegram Premium erhalten haben, werden alle Funktionen in Swiftgram verfügbar.";
"Message.HoldToShowOrReport" = "Halten, zum Ansehen oder melden.";
"Auth.AccountBackupReminder" = "Stelle sicher, dass du eine weiter Möglichkeit hast auf den Account zuzugreifen. Behalte die SIM Karte im SMS zum Login empfangen zu können oder nutze weitere Apps/Geräte mit einer aktive Sitzung deines Accounts.";
"Auth.UnofficialAppCodeTitle" = "Du kannst den Code nur mit der offiziellen App erhalten";
"Settings.SmallReactions" = "Kleine Reaktionen";
"Settings.HideReactions" = "Verberge Reaktionen";
"ContextMenu.SaveToCloud" = "In Cloud speichern";
"ContextMenu.SelectFromUser" = "Vom Autor auswählen";
"Settings.ContextMenu" = "KONTEXTMENÜ";
"Settings.ContextMenu.Notice" = "Deaktivierte Einträge sind im 'Swiftgram'-Untermenü verfügbar.";
"Settings.ChatSwipeOptions" = "Chatlisten-Wisch-Optionen";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Ziehen zum nächsten Kanal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Ziehen Sie zum nächsten Thema";
"Settings.GalleryCamera" = "Kamera in der Galerie";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Schaltfläche";
"Settings.SnapDeletionEffect" = "Nachrichtenlösch-Effekte";
"Settings.Stickers.Size" = "GRÖSSE";
"Settings.Stickers.Timestamp" = "Zeitstempel anzeigen";
"Settings.RecordingButton" = "Sprachaufnahme-Button";
"Settings.DefaultEmojisFirst" = "Priorisieren Sie Standard-Emojis";
"Settings.DefaultEmojisFirst.Notice" = "Zeigen Sie Standard-Emojis vor Premium-Emojis in der Emoji-Tastatur";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "erstellt: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Beigetreten am %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registriert";
"Settings.messageDoubleTapActionOutgoingEdit" = "Doppeltippen, um Nachricht zu bearbeiten";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Ρυθμίσεις Περιεχομένου";
"Settings.Tabs.Header" = "TABS";
"Settings.Tabs.HideTabBar" = "Απόκρυψη γραμμής καρτελών";
"Settings.Tabs.ShowContacts" = "Εμφάνιση Καρτέλας Επαφών";
"Settings.Tabs.ShowNames" = "Show Tab Names";
"Settings.Folders.BottomTab" = "Φάκελοι στο κάτω μέρος";
"Settings.Folders.BottomTabStyle" = "Ύφος Κάτω Φακέλων";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Απόκρυψη \"%@\"";
"Settings.Folders.RememberLast" = "Άνοιγμα Τελευταίου Φακέλου";
"Settings.Folders.RememberLast.Notice" = "Το Swiftgram θα ανοίξει τον τελευταίο φάκελο όταν επανεκκινήσετε την εφαρμογή ή αλλάξετε λογαριασμούς.";
"Settings.Folders.CompactNames" = "Μικρότερη απόσταση";
"Settings.Folders.AllChatsTitle" = "\"Όλες οι συνομιλίες\" τίτλος";
"Settings.Folders.AllChatsTitle.short" = "Σύντομο";
"Settings.Folders.AllChatsTitle.long" = "Εκτενές";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Προεπιλογή";
"Settings.ChatList.Header" = "ΚΑΤΑΛΟΓΟΣ ΤΥΠΟΥ";
"Settings.CompactChatList" = "Συμπαγής Λίστα Συνομιλίας";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Απόκρυψη Ιστοριών";
"Settings.Stories.WarnBeforeView" = "Ερώτηση Πριν Την Προβολή";
"Settings.Stories.DisableSwipeToRecord" = "Απενεργοποίηση ολίσθησης για εγγραφή";
"Settings.Translation.QuickTranslateButton" = "Γρήγορη μετάφραση κουμπί";
"Stories.Warning.Author" = "Συγγραφέας";
"Stories.Warning.ViewStory" = "Προβολή Ιστορίας?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ ΘΑ ΠΡΕΠΕΙ ΝΑ ΒΛΕΠΕ ότι έχετε δει την Ιστορία τους.";
"Stories.Warning.NoticeStealth" = "%@ δεν θα είναι σε θέση να δείτε ότι έχετε δει την Ιστορία τους.";
"Settings.Photo.Quality.Notice" = "Ποιότητα των ανεβασμένων φωτογραφιών και ιστοριών.";
"Settings.Photo.SendLarge" = "Αποστολή Μεγάλων Φωτογραφιών";
"Settings.Photo.SendLarge.Notice" = "Αυξήστε το πλευρικό όριο στις συμπιεσμένες εικόνες στα 2560px.";
"Settings.VideoNotes.Header" = "ΤΡΟΠΟΣ ΒΙΝΤΕΟ";
"Settings.VideoNotes.StartWithRearCam" = "Έναρξη με πίσω κάμερα";
"Settings.CustomColors.Header" = "ΧΡΩΜΑΤΑ ΛΟΓΑΡΙΑΣΜΟΥ";
"Settings.CustomColors.Saturation" = "ΑΣΦΑΛΙΣΗ";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Ορίστε σε 0%% για να απενεργοποιήσετε τα χρώματα του λογαριασμού.";
"Settings.UploadsBoost" = "Ενίσχυση Αποστολής";
"Settings.DownloadsBoost" = "Ενίσχυση Λήψης";
"Settings.DownloadsBoost.none" = "Απενεργοποιημένο";
"Settings.DownloadsBoost.medium" = "Μεσαίο";
"Settings.DownloadsBoost.maximum" = "Μέγιστο";
"Settings.ShowProfileID" = "Εμφάνιση Αναγνωριστικού Προφίλ";
"Settings.ShowDC" = "Εμφάνιση Κέντρου Δεδομένων";
"Settings.ShowCreationDate" = "Εμφάνιση Ημερομηνίας Δημιουργίας Συνομιλίας";
"Settings.ShowCreationDate.Notice" = "Η ημερομηνία δημιουργίας μπορεί να είναι άγνωστη για μερικές συνομιλίες.";
"Settings.ShowRegDate" = "Εμφάνιση Ημερομηνίας Εγγραφής";
"Settings.ShowRegDate.Notice" = "Η ημερομηνία εγγραφής είναι κατά προσέγγιση.";
"Settings.SendWithReturnKey" = "Αποστολή με κλειδί \"επιστροφή\"";
"Settings.HidePhoneInSettingsUI" = "Απόκρυψη τηλεφώνου στις ρυθμίσεις";
"Settings.HidePhoneInSettingsUI.Notice" = "Αυτό θα κρύψει μόνο τον αριθμό τηλεφώνου σας από τη διεπαφή ρυθμίσεων. Για να τον αποκρύψετε από άλλους, μεταβείτε στο Privacy and Security.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Εάν είναι μακριά για 5 δευτερόλεπτα";
"ProxySettings.UseSystemDNS" = "Χρήση συστήματος DNS";
"ProxySettings.UseSystemDNS.Notice" = "Χρησιμοποιήστε το σύστημα DNS για να παρακάμψετε το χρονικό όριο αν δεν έχετε πρόσβαση στο Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Du **brauchst kein** %@!";
"Common.RestartRequired" = "Απαιτείται επανεκκίνηση";
"Common.RestartNow" = "Επανεκκίνηση Τώρα";
"Common.OpenTelegram" = "Άνοιγμα Telegram";
"Common.UseTelegramForPremium" = "Παρακαλώ σημειώστε ότι για να πάρετε Telegram Premium, θα πρέπει να χρησιμοποιήσετε την επίσημη εφαρμογή Telegram. Μόλις λάβετε Telegram Premium, όλα τα χαρακτηριστικά του θα είναι διαθέσιμα στο Swiftgram.";
"Message.HoldToShowOrReport" = "Κρατήστε για προβολή ή αναφορά.";
"Auth.AccountBackupReminder" = "Βεβαιωθείτε ότι έχετε μια μέθοδο πρόσβασης αντιγράφων ασφαλείας. Κρατήστε μια SIM για SMS ή μια πρόσθετη συνεδρία συνδεδεμένη για να αποφύγετε να κλειδωθεί.";
"Auth.UnofficialAppCodeTitle" = "Μπορείτε να πάρετε τον κωδικό μόνο με επίσημη εφαρμογή";
"Settings.SmallReactions" = "Μικρές Αντιδράσεις";
"Settings.HideReactions" = "Απόκρυψη Αντιδράσεων";
"ContextMenu.SaveToCloud" = "Αποθήκευση στο σύννεφο";
"ContextMenu.SelectFromUser" = "Επιλέξτε από τον Συγγραφέα";
"Settings.ContextMenu" = "KONTEXTMENÜ";
"Settings.ContextMenu.Notice" = "Deaktivierte Einträge sind im 'Swiftgram'-Untermenü verfügbar.";
"Settings.ChatSwipeOptions" = "Επιλογές Συρσίματος Λίστας Συνομιλίας";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Τραβήξτε στο επόμενο μη αναγνωσμένο κανάλι";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Τραβήξτε για το Επόμενο Θέμα";
"Settings.GalleryCamera" = "Κάμερα στη Γκαλερί";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\" Κουμπί%@\"";
"Settings.SnapDeletionEffect" = "Εφέ Διαγραφής Μηνύματος";
"Settings.Stickers.Size" = "ΜΕΓΕΘΟΣ";
"Settings.Stickers.Timestamp" = "Εμφάνιση Χρονοσήμανσης";
"Settings.RecordingButton" = "Πλήκτρο Ηχογράφησης Φωνής";
"Settings.DefaultEmojisFirst" = "Δώστε προτεραιότητα στα τυπικά emojis";
"Settings.DefaultEmojisFirst.Notice" = "Εμφανίστε τυπικά emojis πριν από premium στο πληκτρολόγιο emojis";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "δημιουργήθηκε: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Εντάχθηκε στο %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Εγγεγραμμένος";
"Settings.messageDoubleTapActionOutgoingEdit" = "Διπλό Πάτημα για Επεξεργασία Μηνύματος";

View File

@ -0,0 +1,134 @@
"Settings.ContentSettings" = "Content Settings";
"Settings.Tabs.Header" = "TABS";
"Settings.Tabs.HideTabBar" = "Hide Tab bar";
"Settings.Tabs.ShowContacts" = "Show Contacts Tab";
"Settings.Tabs.ShowNames" = "Show Tab Names";
"Settings.Folders.BottomTab" = "Folders at Bottom";
"Settings.Folders.BottomTabStyle" = "Bottom Folders Style";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Hide \"%@\"";
"Settings.Folders.RememberLast" = "Open Last Folder";
"Settings.Folders.RememberLast.Notice" = "Swiftgram will open the last used folder when you restart the app or switch accounts.";
"Settings.Folders.CompactNames" = "Smaller spacing";
"Settings.Folders.AllChatsTitle" = "\"All Chats\" title";
"Settings.Folders.AllChatsTitle.short" = "Short";
"Settings.Folders.AllChatsTitle.long" = "Long";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Default";
"Settings.ChatList.Header" = "CHAT LIST";
"Settings.CompactChatList" = "Compact Chat List";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Hide Stories";
"Settings.Stories.WarnBeforeView" = "Ask Before Viewing";
"Settings.Stories.DisableSwipeToRecord" = "Disable Swipe to Record";
"Settings.Translation.QuickTranslateButton" = "Quick Translate button";
"Stories.Warning.Author" = "Author";
"Stories.Warning.ViewStory" = "View Story?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ WILL BE ABLE TO SEE that you viewed their Story.";
"Stories.Warning.NoticeStealth" = "%@ will not be able to see that you viewed their Story.";
"Settings.Photo.Quality.Notice" = "Quality of uploaded photos and stories.";
"Settings.Photo.SendLarge" = "Send Large Photos";
"Settings.Photo.SendLarge.Notice" = "Increase the side limit on compressed images to 2560px.";
"Settings.VideoNotes.Header" = "ROUND VIDEOS";
"Settings.VideoNotes.StartWithRearCam" = "Start with Rear Camera";
"Settings.CustomColors.Header" = "ACCOUNT COLORS";
"Settings.CustomColors.Saturation" = "SATURATION";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Set to 0%% to disable account colors.";
"Settings.UploadsBoost" = "Upload Boost";
"Settings.DownloadsBoost" = "Download Boost";
"Settings.DownloadsBoost.none" = "Disabled";
"Settings.DownloadsBoost.medium" = "Medium";
"Settings.DownloadsBoost.maximum" = "Maximum";
"Settings.ShowProfileID" = "Show Profile ID";
"Settings.ShowDC" = "Show Data Center";
"Settings.ShowCreationDate" = "Show Chat Creation Date";
"Settings.ShowCreationDate.Notice" = "The creation date may be unknown for some chats.";
"Settings.ShowRegDate" = "Show Registration Date";
"Settings.ShowRegDate.Notice" = "The registration date is approximate.";
"Settings.SendWithReturnKey" = "Send with \"return\" key";
"Settings.HidePhoneInSettingsUI" = "Hide Phone in Settings";
"Settings.HidePhoneInSettingsUI.Notice" = "This will only hide your phone number from the settings interface. To hide it from others, go to Privacy and Security.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "If away for 5 seconds";
"ProxySettings.UseSystemDNS" = "Use system DNS";
"ProxySettings.UseSystemDNS.Notice" = "Use system DNS to bypass timeout if you don't have access to Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "You **don't need** %@!";
"Common.RestartRequired" = "Restart required";
"Common.RestartNow" = "Restart Now";
"Common.OpenTelegram" = "Open Telegram";
"Common.UseTelegramForPremium" = "Please note that to get Telegram Premium, you must use the official Telegram app. Once you have obtained Telegram Premium, all its features will become available in Swiftgram.";
"Message.HoldToShowOrReport" = "Hold to Show or Report.";
"Auth.AccountBackupReminder" = "Make sure you have a backup access method. Keep a SIM for SMS or an additional session logged in to avoid being locked out.";
"Auth.UnofficialAppCodeTitle" = "You can get the code only with official app";
"Settings.SmallReactions" = "Small Reactions";
"Settings.HideReactions" = "Hide Reactions";
"ContextMenu.SaveToCloud" = "Save to Cloud";
"ContextMenu.SelectFromUser" = "Select from Author";
"Settings.ContextMenu" = "CONTEXT MENU";
"Settings.ContextMenu.Notice" = "Disabled entries will be available in \"Swiftgram\" sub-menu.";
"Settings.ChatSwipeOptions" = "Chat List Swipe Options";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Pull to Next Unread Channel";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Pull to Next Topic";
"Settings.GalleryCamera" = "Camera in Gallery";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Button";
"Settings.SnapDeletionEffect" = "Message Deletion Effects";
"Settings.Stickers.Size" = "SIZE";
"Settings.Stickers.Timestamp" = "Show Timestamp";
"Settings.RecordingButton" = "Voice Recording Button";
"Settings.DefaultEmojisFirst" = "Prioritize standard emojis";
"Settings.DefaultEmojisFirst.Notice" = "Show standard emojis before premium in emoji keyboard";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "created: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Joined %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registered";
"Settings.messageDoubleTapActionOutgoingEdit" = "Double-tap to edit message";
"Settings.wideChannelPosts" = "Wide posts in channels";
"Settings.ForceEmojiTab" = "Emoji keyboard by default";
"Settings.forceBuiltInMic" = "Force Device Microphone";
"Settings.forceBuiltInMic.Notice" = "If enabled, app will use only device microphone even if headphones are connected.";

View File

@ -0,0 +1,134 @@
"Settings.ContentSettings" = "Configuración de contenido";
"Settings.Tabs.Header" = "PESTAÑAS";
"Settings.Tabs.HideTabBar" = "Ocultar barra de pestaña";
"Settings.Tabs.ShowContacts" = "Mostrar pestaña de Contactos";
"Settings.Tabs.ShowNames" = "Mostrar nombres de pestañas";
"Settings.Folders.BottomTab" = "Carpetas al fondo";
"Settings.Folders.BottomTabStyle" = "Estilo de carpetas al fondo";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Ocultar \"%@\"";
"Settings.Folders.RememberLast" = "Abrir última carpeta";
"Settings.Folders.RememberLast.Notice" = "Swiftgram abrirá la última carpeta usada después de reiniciar o cambiar de cuenta";
"Settings.Folders.CompactNames" = "Espaciado más pequeño";
"Settings.Folders.AllChatsTitle" = "Título \"Todos los Chats\"";
"Settings.Folders.AllChatsTitle.short" = "Corto";
"Settings.Folders.AllChatsTitle.long" = "Largo";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Por defecto";
"Settings.ChatList.Header" = "LISTA DE CHAT";
"Settings.CompactChatList" = "Lista de Chat de Compacto";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Ocultar Historias";
"Settings.Stories.WarnBeforeView" = "Preguntar antes de ver";
"Settings.Stories.DisableSwipeToRecord" = "Desactivar deslizar para grabar";
"Settings.Translation.QuickTranslateButton" = "Botón de traducción rápida";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "¿Ver historia?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ PODRÁ VER que viste su historia.";
"Stories.Warning.NoticeStealth" = "%@ no podrá ver que viste su historia.";
"Settings.Photo.Quality.Notice" = "Calidad de las fotos y foto-historias enviadas";
"Settings.Photo.SendLarge" = "Enviar fotos grandes";
"Settings.Photo.SendLarge.Notice" = "Aumentar el límite de tamaño de las imágenes comprimidas a 2560px";
"Settings.VideoNotes.Header" = "VIDEOS REDONDOS";
"Settings.VideoNotes.StartWithRearCam" = "Comenzar con la cámara trasera";
"Settings.CustomColors.Header" = "COLORES DE LA CUENTA";
"Settings.CustomColors.Saturation" = "SATURACIÓN";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Establecer saturación en 0%% para desactivar los colores de la cuenta";
"Settings.UploadsBoost" = "Aumento de subida";
"Settings.DownloadsBoost" = "Aumento de descargas";
"Settings.DownloadsBoost.none" = "Desactivado";
"Settings.DownloadsBoost.medium" = "Medio";
"Settings.DownloadsBoost.maximum" = "Máximo";
"Settings.ShowProfileID" = "Mostrar ID del perfil";
"Settings.ShowDC" = "Mostrar Centro de Datos";
"Settings.ShowCreationDate" = "Mostrar fecha de creación del chat";
"Settings.ShowCreationDate.Notice" = "La fecha de creación puede ser desconocida para algunos chats.";
"Settings.ShowRegDate" = "Mostrar fecha de registro";
"Settings.ShowRegDate.Notice" = "La fecha de inscripción es aproximada.";
"Settings.SendWithReturnKey" = "Enviar con la tecla \"regresar\"";
"Settings.HidePhoneInSettingsUI" = "Ocultar número en Ajustes";
"Settings.HidePhoneInSettingsUI.Notice" = "Tu número estará oculto en la interfaz de ajustes solamente. Ve a la configuración de privacidad para ocultarlo a otros.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Si está ausente durante 5 segundos";
"ProxySettings.UseSystemDNS" = "Usar DNS del sistema";
"ProxySettings.UseSystemDNS.Notice" = "Usa el DNS del sistema para omitir el tiempo de espera si no tienes acceso a Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "¡**No necesitas** %@!";
"Common.RestartRequired" = "Es necesario reiniciar";
"Common.RestartNow" = "Reiniciar ahora";
"Common.OpenTelegram" = "Abrir Telegram";
"Common.UseTelegramForPremium" = "Ten en cuenta que para obtener Telegram Premium, debes usar la aplicación oficial de Telegram. Una vez que haya obtenido Telegram Premium, todas sus características estarán disponibles en Swiftgram.";
"Message.HoldToShowOrReport" = "Mantenga presionado para mostrar o reportar.";
"Auth.AccountBackupReminder" = "Asegúrate de que tienes un método de acceso de copia de seguridad. Mantenga una SIM para SMS o una sesión adicional conectada para evitar ser bloqueada.";
"Auth.UnofficialAppCodeTitle" = "Sólo puedes obtener el código con la app oficial";
"Settings.SmallReactions" = "Reacciones pequeñas";
"Settings.HideReactions" = "Ocultar Reacciones";
"ContextMenu.SaveToCloud" = "Guardar en la nube";
"ContextMenu.SelectFromUser" = "Seleccionar del autor";
"Settings.ContextMenu" = "MENÚ CONTEXTUAL";
"Settings.ContextMenu.Notice" = "Las entradas desactivadas estarán disponibles en el submenú \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "Opciones de deslizamiento de la lista de chats";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Saltar al siguiente canal no leído";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Deslizar para ir al siguiente tema";
"Settings.GalleryCamera" = "Cámara en galería";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Botón \"%@\"";
"Settings.SnapDeletionEffect" = "Efectos de eliminación de mensajes";
"Settings.Stickers.Size" = "TAMAÑO";
"Settings.Stickers.Timestamp" = "Mostrar marca de tiempo";
"Settings.RecordingButton" = "Botón de grabación de voz";
"Settings.DefaultEmojisFirst" = "Priorizar emojis estándar";
"Settings.DefaultEmojisFirst.Notice" = "Mostrar emojis estándar antes que premium en el teclado de emojis";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "creado: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Unido a %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrado";
"Settings.messageDoubleTapActionOutgoingEdit" = "Doble toque para editar mensaje";
"Settings.wideChannelPosts" = "Publicaciones amplias en canales";
"Settings.ForceEmojiTab" = "Teclado de emojis por defecto";
"Settings.forceBuiltInMic" = "Forzar micrófono del dispositivo";
"Settings.forceBuiltInMic.Notice" = "Si está habilitado, la aplicación utilizará solo el micrófono del dispositivo incluso si se conectan auriculares.";

View File

@ -0,0 +1,9 @@
"Settings.Tabs.Header" = "زبانه ها";
"Settings.Tabs.ShowContacts" = "نمایش برگه مخاطبین";
"Settings.VideoNotes.Header" = "فیلم های round";
"Settings.Tabs.ShowNames" = "نشان دادن برگه اسم ها";
"Settings.HidePhoneInSettingsUI" = "پنهان کردن شماره موبایل در تنظیمات";
"Settings.HidePhoneInSettingsUI.Notice" = "شماره شما فقط در رابط کاربری پنهان خواهد شد. برای پنهان کردن آن از دید دیگران ، لطفاً از تنظیمات حریم خصوصی استفاده کنید.";
"Settings.ShowProfileID" = "نمایش ایدی پروفایل";
"Settings.Translation.QuickTranslateButton" = "دکمه ترجمه سریع";
"ContextMenu.SaveToCloud" = "ذخیره در فضای ابری";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Sisällön Asetukset";
"Settings.Tabs.Header" = "VÄLILEHDET";
"Settings.Tabs.HideTabBar" = "Piilota Välilehtipalkki";
"Settings.Tabs.ShowContacts" = "Näytä Yhteystiedot-välilehti";
"Settings.Tabs.ShowNames" = "Näytä välilehtien nimet";
"Settings.Folders.BottomTab" = "Kansiot alhaalla";
"Settings.Folders.BottomTabStyle" = "Alhaalla olevien kansioiden tyyli";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Piilota \"%@\"";
"Settings.Folders.RememberLast" = "Avaa viimeisin kansio";
"Settings.Folders.RememberLast.Notice" = "Swiftgram avaa viimeksi käytetyn kansion uudelleenkäynnistyksen tai tilin vaihdon jälkeen.";
"Settings.Folders.CompactNames" = "Pienempi väli";
"Settings.Folders.AllChatsTitle" = "\"Kaikki chatit\" otsikko";
"Settings.Folders.AllChatsTitle.short" = "Lyhyt";
"Settings.Folders.AllChatsTitle.long" = "Pitkä";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Oletus";
"Settings.ChatList.Header" = "CHAT LIST";
"Settings.CompactChatList" = "Kompakti Keskustelulista";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Piilota Tarinat";
"Settings.Stories.WarnBeforeView" = "Kysy ennen katsomista";
"Settings.Stories.DisableSwipeToRecord" = "Poista pyyhkäisy tallennukseen käytöstä";
"Settings.Translation.QuickTranslateButton" = "Pikakäännöspainike";
"Stories.Warning.Author" = "Tekijä";
"Stories.Warning.ViewStory" = "Katso Tarina?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ NÄKEE, että olet katsonut heidän Tarinansa.";
"Stories.Warning.NoticeStealth" = "%@ ei näe, että olet katsonut heidän Tarinansa.";
"Settings.Photo.Quality.Notice" = "Lähtevien valokuvien ja valokuvatarinoiden laatu.";
"Settings.Photo.SendLarge" = "Lähetä suuria valokuvia";
"Settings.Photo.SendLarge.Notice" = "Suurenna pakattujen kuvien sivurajaa 2560px:ään.";
"Settings.VideoNotes.Header" = "PYÖREÄT VIDEOT";
"Settings.VideoNotes.StartWithRearCam" = "Aloita takakameralla";
"Settings.CustomColors.Header" = "TILIN VÄRIT";
"Settings.CustomColors.Saturation" = "KYLLÄISYYS";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Aseta kylläisyys 0%%:iin poistaaksesi tilin värit käytöstä.";
"Settings.UploadsBoost" = "Latausten tehostus";
"Settings.DownloadsBoost" = "Latausten tehostus";
"Settings.DownloadsBoost.none" = "Ei käytössä";
"Settings.DownloadsBoost.medium" = "Keskitaso";
"Settings.DownloadsBoost.maximum" = "Maksimi";
"Settings.ShowProfileID" = "Näytä profiilin ID";
"Settings.ShowDC" = "Näytä tietokeskus";
"Settings.ShowCreationDate" = "Näytä keskustelun luontipäivä";
"Settings.ShowCreationDate.Notice" = "Keskustelun luontipäivä voi olla tuntematon joillekin keskusteluille.";
"Settings.ShowRegDate" = "Näytä Rekisteröintipäivä";
"Settings.ShowRegDate.Notice" = "Rekisteröintipäivä on likimääräinen.";
"Settings.SendWithReturnKey" = "Lähetä 'paluu'-näppäimellä";
"Settings.HidePhoneInSettingsUI" = "Piilota puhelin asetuksissa";
"Settings.HidePhoneInSettingsUI.Notice" = "Tämä piilottaa puhelinnumerosi vain asetukset-käyttöliittymästä. Piilottaaksesi sen muilta, siirry kohtaan Yksityisyys ja Turvallisuus.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Jos poissa 5 sekuntia";
"ProxySettings.UseSystemDNS" = "Käytä järjestelmän DNS:ää";
"ProxySettings.UseSystemDNS.Notice" = "Käytä järjestelmän DNS:ää ohittaaksesi aikakatkaisun, jos sinulla ei ole pääsyä Google DNS:ään";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Et **tarvitse** %@!";
"Common.RestartRequired" = "Uudelleenkäynnistys vaaditaan";
"Common.RestartNow" = "Käynnistä uudelleen nyt";
"Common.OpenTelegram" = "Avaa Telegram";
"Common.UseTelegramForPremium" = "Huomioi, että saat Telegram Premiumin käyttämällä virallista Telegram-sovellusta. Kun olet hankkinut Telegram Premiumin, kaikki sen ominaisuudet ovat saatavilla Swiftgramissa.";
"Message.HoldToShowOrReport" = "Pidä esillä näyttääksesi tai ilmoittaaksesi.";
"Auth.AccountBackupReminder" = "Varmista, että sinulla on varmuuskopio pääsymenetelmästä. Pidä SIM tekstiviestejä varten tai ylimääräinen istunto kirjautuneena välttääksesi lukkiutumisen.";
"Auth.UnofficialAppCodeTitle" = "Koodin voi saada vain virallisella sovelluksella";
"Settings.SmallReactions" = "Pienet reaktiot";
"Settings.HideReactions" = "Piilota reaktiot";
"ContextMenu.SaveToCloud" = "Tallenna Pilveen";
"ContextMenu.SelectFromUser" = "Valitse Tekijältä";
"Settings.ContextMenu" = "KONTEKSTIVALIKKO";
"Settings.ContextMenu.Notice" = "Poistetut kohteet ovat saatavilla 'Swiftgram'-alavalikossa.";
"Settings.ChatSwipeOptions" = "Chat List Swipe Options";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Vetää seuraavaan lukemattomaan kanavaan";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Vedä seuraava aihe";
"Settings.GalleryCamera" = "Camera in Gallery";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Button";
"Settings.SnapDeletionEffect" = "Message Deletion Effects";
"Settings.Stickers.Size" = "SIZE";
"Settings.Stickers.Timestamp" = "Show Timestamp";
"Settings.RecordingButton" = "Voice Recording Button";
"Settings.DefaultEmojisFirst" = "Anna etusijalle vakiotunnuksia";
"Settings.DefaultEmojisFirst.Notice" = "Näytä vakiotunnukset ennen premium-tunnuksia tunnusnäppäimistössä";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "created: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Joined %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Rekisteröity";
"Settings.messageDoubleTapActionOutgoingEdit" = "Paina kahdesti muokataksesi viestiä";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Paramètres du contenu";
"Settings.Tabs.Header" = "ONGLETS";
"Settings.Tabs.HideTabBar" = "Masquer la barre d'onglets";
"Settings.Tabs.ShowContacts" = "Afficher l'onglet Contacts";
"Settings.Tabs.ShowNames" = "Afficher les noms des onglets";
"Settings.Folders.BottomTab" = "Dossiers en bas";
"Settings.Folders.BottomTabStyle" = "Style des dossiers inférieurs";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Masquer \"%@\"";
"Settings.Folders.RememberLast" = "Ouvrir le dernier dossier";
"Settings.Folders.RememberLast.Notice" = "Swiftgram ouvrira le dernier dossier utilisé après le redémarrage ou changement de compte";
"Settings.Folders.CompactNames" = "Espacement plus petit";
"Settings.Folders.AllChatsTitle" = "Titre \"Tous les Chats\"";
"Settings.Folders.AllChatsTitle.short" = "Courte";
"Settings.Folders.AllChatsTitle.long" = "Longue";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Par défaut";
"Settings.ChatList.Header" = "LISTE DE CHAT";
"Settings.CompactChatList" = "Liste de discussion compacte";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Cacher les histoires";
"Settings.Stories.WarnBeforeView" = "Demander avant de visionner";
"Settings.Stories.DisableSwipeToRecord" = "Désactiver le glissement pour enregistrer";
"Settings.Translation.QuickTranslateButton" = "Bouton de traduction rapide";
"Stories.Warning.Author" = "Auteur";
"Stories.Warning.ViewStory" = "Voir l'histoire?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ SERA autorisé à voir que vous avez vu son histoire.";
"Stories.Warning.NoticeStealth" = "%@ ne sera pas en mesure de voir que vous avez vu leur Histoire.";
"Settings.Photo.Quality.Notice" = "Qualité des photos et des récits photo sortants";
"Settings.Photo.SendLarge" = "Envoyer de grandes photos";
"Settings.Photo.SendLarge.Notice" = "Augmenter la limite latérale des images compressées à 2560px";
"Settings.VideoNotes.Header" = "VIDÉOS RONDES";
"Settings.VideoNotes.StartWithRearCam" = "Commencer avec la caméra arrière";
"Settings.CustomColors.Header" = "COULEURS DU COMPTE";
"Settings.CustomColors.Saturation" = "SATURATION";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Régler la saturation à 0%% pour désactiver les couleurs du compte";
"Settings.UploadsBoost" = "Chargements boost";
"Settings.DownloadsBoost" = "Boost de téléchargements";
"Settings.DownloadsBoost.none" = "Désactivé";
"Settings.DownloadsBoost.medium" = "Moyenne";
"Settings.DownloadsBoost.maximum" = "Maximum";
"Settings.ShowProfileID" = "Afficher l'identifiant du profil";
"Settings.ShowDC" = "Afficher le centre de données";
"Settings.ShowCreationDate" = "Afficher la date de création du chat";
"Settings.ShowCreationDate.Notice" = "La date de création peut être inconnue pour certains chats.";
"Settings.ShowRegDate" = "Afficher la date d'inscription";
"Settings.ShowRegDate.Notice" = "La date d'inscription est approximative.";
"Settings.SendWithReturnKey" = "Envoyer avec la clé \"return\"";
"Settings.HidePhoneInSettingsUI" = "Masquer le téléphone dans les paramètres";
"Settings.HidePhoneInSettingsUI.Notice" = "Votre numéro sera masqué dans l'interface utilisateur uniquement. Pour le masquer aux autres, veuillez utiliser les paramètres de confidentialité.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Si absente pendant 5 secondes";
"ProxySettings.UseSystemDNS" = "Utiliser le DNS du système";
"ProxySettings.UseSystemDNS.Notice" = "Utiliser le DNS système pour contourner le délai d'attente si vous n'avez pas accès à Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Vous **n'avez pas besoin** %@!";
"Common.RestartRequired" = "Redémarrage nécessaire";
"Common.RestartNow" = "Redémarrer maintenant";
"Common.OpenTelegram" = "Ouvrir Telegram";
"Common.UseTelegramForPremium" = "Veuillez noter que pour obtenir Telegram Premium, vous devez utiliser l'application Telegram officielle. Une fois que vous avez obtenu Telegram Premium, toutes ses fonctionnalités seront disponibles dans Swiftgram.";
"Message.HoldToShowOrReport" = "Maintenir pour afficher ou rapporter.";
"Auth.AccountBackupReminder" = "Assurez-vous d'avoir une méthode d'accès de sauvegarde. Gardez une carte SIM pour les SMS ou une session supplémentaire connectée pour éviter d'être bloquée.";
"Auth.UnofficialAppCodeTitle" = "Vous ne pouvez obtenir le code qu'avec l'application officielle";
"Settings.SmallReactions" = "Petites réactions";
"Settings.HideReactions" = "Masquer les réactions";
"ContextMenu.SaveToCloud" = "Sauvegarder dans le cloud";
"ContextMenu.SelectFromUser" = "Sélectionner de l'Auteur";
"Settings.ContextMenu" = "MENU CONTEXTUEL";
"Settings.ContextMenu.Notice" = "Les entrées désactivées seront disponibles dans le sous-menu 'Swiftgram'.";
"Settings.ChatSwipeOptions" = "Options de balayage de la liste de chat";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Tirer vers le prochain canal non lu";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Tirer pour le sujet suivant";
"Settings.GalleryCamera" = "Appareil photo dans la galerie";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Bouton \"%@\"";
"Settings.SnapDeletionEffect" = "Effets de suppression de message";
"Settings.Stickers.Size" = "TAILLE";
"Settings.Stickers.Timestamp" = "Afficher l'horodatage";
"Settings.RecordingButton" = "Bouton d'enregistrement vocal";
"Settings.DefaultEmojisFirst" = "Prioriser les emojis standard";
"Settings.DefaultEmojisFirst.Notice" = "Afficher les emojis standard avant les emojis premium dans le clavier emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "créé: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Rejoint %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Enregistré";
"Settings.messageDoubleTapActionOutgoingEdit" = "Appuyez deux fois pour modifier le message";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "הגדרות תוכן";
"Settings.Tabs.Header" = "כרטיסיות";
"Settings.Tabs.HideTabBar" = "הסתר סרגל לשוניים";
"Settings.Tabs.ShowContacts" = "הצג כרטיסיית אנשי קשר";
"Settings.Tabs.ShowNames" = "הצג שמות כרטיסיות";
"Settings.Folders.BottomTab" = "תיקיות בתחתית";
"Settings.Folders.BottomTabStyle" = "סגנון תיקיות תחתון";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "טלגרם";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "להסתיר \"%@\"";
"Settings.Folders.RememberLast" = "פתח את התיקיה האחרונה";
"Settings.Folders.RememberLast.Notice" = "Swiftgram תפתח את התיקיה שנעשה בה שימוש לאחרונה לאחר הפעלה מחדש או החלפת חשבון";
"Settings.Folders.CompactNames" = "ריווח קטן יותר";
"Settings.Folders.AllChatsTitle" = "כותרת \"כל הצ'אטים\"";
"Settings.Folders.AllChatsTitle.short" = "קצר";
"Settings.Folders.AllChatsTitle.long" = "ארוך";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "ברירת מחדל";
"Settings.ChatList.Header" = "רשימת צ'אטים";
"Settings.CompactChatList" = "רשימת צ'אטים קומפקטית";
"Settings.Profiles.Header" = "פרופילים";
"Settings.Stories.Hide" = "הסתר סיפורים";
"Settings.Stories.WarnBeforeView" = "שאל לפני צפייה";
"Settings.Stories.DisableSwipeToRecord" = "בטל החלקה להקלטה";
"Settings.Translation.QuickTranslateButton" = "כפתור תרגום מהיר";
"Stories.Warning.Author" = "מחבר";
"Stories.Warning.ViewStory" = "לצפות בסיפור?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ יוכל לראות שצפית בסיפור שלו.";
"Stories.Warning.NoticeStealth" = "%@ לא יוכל לראות שצפית בסיפור שלו.";
"Settings.Photo.Quality.Notice" = "איכות התמונות היוצאות והסיפורים בתמונות";
"Settings.Photo.SendLarge" = "שלח תמונות גדולות";
"Settings.Photo.SendLarge.Notice" = "הגדל את הגבול הצידי של תמונות מודחקות ל-2560px";
"Settings.VideoNotes.Header" = "וידאו מעוגלים";
"Settings.VideoNotes.StartWithRearCam" = "התחל עם מצלמה אחורית";
"Settings.CustomColors.Header" = "צבעי חשבון";
"Settings.CustomColors.Saturation" = "רווי";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "קבע רווי ל-0%% כדי לבטל צבעי חשבון";
"Settings.UploadsBoost" = "תוספת העלאות";
"Settings.DownloadsBoost" = "תוספת הורדות";
"Settings.DownloadsBoost.none" = "מבוטל";
"Settings.DownloadsBoost.medium" = "בינוני";
"Settings.DownloadsBoost.maximum" = "מרבי";
"Settings.ShowProfileID" = "הצג מזהה פרופיל";
"Settings.ShowDC" = "הצג מרכז מידע";
"Settings.ShowCreationDate" = "הצג תאריך יצירת צ'אט";
"Settings.ShowCreationDate.Notice" = "ייתכן שתאריך היצירה אינו ידוע עבור חלק מהצ'אטים.";
"Settings.ShowRegDate" = "הצג תאריך רישום";
"Settings.ShowRegDate.Notice" = "תאריך הרישום הוא אופציונלי.";
"Settings.SendWithReturnKey" = "שלח עם מקש \"חזור\"";
"Settings.HidePhoneInSettingsUI" = "הסתר טלפון בהגדרות";
"Settings.HidePhoneInSettingsUI.Notice" = "המספר שלך יהיה מוסתר בממשק ההגדרות בלבד. עבור להגדרות פרטיות כדי להסתיר אותו מאחרים.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "נעל אוטומטית אחרי 5 שניות";
"ProxySettings.UseSystemDNS" = "השתמש ב-DNS של המערכת";
"ProxySettings.UseSystemDNS.Notice" = "השתמש ב-DNS של המערכת כדי לעקוף זמן תגובה אם אין לך גישה ל-Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "אין **צורך** ב%@!";
"Common.RestartRequired" = "נדרש הפעלה מחדש";
"Common.RestartNow" = "הפעל מחדש עכשיו";
"Common.OpenTelegram" = "פתח טלגרם";
"Common.UseTelegramForPremium" = "שים לב כי כדי לקבל Telegram Premium, עליך להשתמש באפליקציית Telegram הרשמית. לאחר שקיבלת טלגרם פרימיום, כל התכונות שלו יהיו זמינות ב־Swiftgram.";
"Message.HoldToShowOrReport" = "החזק כדי להציג או לדווח.";
"Auth.AccountBackupReminder" = "ודא שיש לך שיטת גישה לגיבוי. שמור כרטיס SIM ל-SMS או פתח סשן נוסף כדי למנוע חסימה.";
"Auth.UnofficialAppCodeTitle" = "תוכל לקבל את הקוד רק דרך האפליקציה הרשמית";
"Settings.SmallReactions" = "תגובות קטנות";
"Settings.HideReactions" = "הסתר תגובות";
"ContextMenu.SaveToCloud" = "שמור בענן";
"ContextMenu.SelectFromUser" = "בחר מהמשתמש";
"Settings.ContextMenu" = "תפריט הקשר";
"Settings.ContextMenu.Notice" = "פריטים מבוטלים יהיו זמינים בתת-תפריט 'Swiftgram'.";
"Settings.ChatSwipeOptions" = "אפשרויות גלילה ברשימת צ'אטים";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "משוך לערוץ לא נקרא הבא";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "משוך כדי להמשיך לנושא הבא";
"Settings.GalleryCamera" = "מצלמה בגלריה";
/* "Send Message As..." button */
"Settings.SendAsButton" = "כפתור \"%@\"";
"Settings.SnapDeletionEffect" = "אפקטים של מחיקת הודעות";
"Settings.Stickers.Size" = "גודל";
"Settings.Stickers.Timestamp" = "הצג חותמת זמן";
"Settings.RecordingButton" = "כפתור הקלטת קול";
"Settings.DefaultEmojisFirst" = "העדף רמזי פנים סטנדרטיים";
"Settings.DefaultEmojisFirst.Notice" = "הצג רמזי פנים סטנדרטיים לפני פרימיום במקלדת רמזי פנים";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "נוצר: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "הצטרף/הצטרפה ב־%@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "נרשם";
"Settings.messageDoubleTapActionOutgoingEdit" = "לחץ פעמיים לעריכת הודעה";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "कंटेंट सेटिंग्स";
"Settings.Tabs.Header" = "टैब";
"Settings.Tabs.HideTabBar" = "टैब बार छिपाएं";
"Settings.Tabs.ShowContacts" = "संपर्क टैब दिखाएँ";
"Settings.Tabs.ShowNames" = "टैब नाम दिखाएं";
"Settings.Folders.BottomTab" = "निचले टैब में फोल्डर्स";
"Settings.Folders.BottomTabStyle" = "बॉटम फोल्डर स्टाइल है";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "आईओएस";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "टेलीग्राम";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "\"%@\" छिपाएं";
"Settings.Folders.RememberLast" = "आखिरी फोल्डर खोलें";
"Settings.Folders.RememberLast.Notice" = "Swiftgram पुनः आरंभ या खाता स्विच करने के बाद अंतिम प्रयुक्त फोल्डर को खोलेगा";
"Settings.Folders.CompactNames" = "कम अंतराल";
"Settings.Folders.AllChatsTitle" = "\"सभी चैट\" शीर्षक";
"Settings.Folders.AllChatsTitle.short" = "संक्षिप्त";
"Settings.Folders.AllChatsTitle.long" = "लंबा";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "डिफ़ॉल्ट";
"Settings.ChatList.Header" = "चैट सूची";
"Settings.CompactChatList" = "संक्षिप्त चैट सूची";
"Settings.Profiles.Header" = "प्रोफाइल";
"Settings.Stories.Hide" = "कहानियाँ छुपाएं";
"Settings.Stories.WarnBeforeView" = "देखने से पहले पूछें";
"Settings.Stories.DisableSwipeToRecord" = "रिकॉर्ड करने के लिए स्वाइप को अक्षम करें";
"Settings.Translation.QuickTranslateButton" = "त्वरित अनुवाद बटन";
"Stories.Warning.Author" = "लेखक";
"Stories.Warning.ViewStory" = "कहानी देखें";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ देख सकते हैं कि आपने उनकी कहानी देखी है।";
"Stories.Warning.NoticeStealth" = "%@ नहीं देख सकते कि आपने उनकी कहानी देखी है।";
"Settings.Photo.Quality.Notice" = "भेजे गए फोटो और फोटो-कहानियों की गुणवत्ता";
"Settings.Photo.SendLarge" = "बड़े फोटो भेजें";
"Settings.Photo.SendLarge.Notice" = "संकुचित छवियों पर साइड सीमा को 2560px तक बढ़ाएं";
"Settings.VideoNotes.Header" = "गोल वीडियो";
"Settings.VideoNotes.StartWithRearCam" = "रियर कैमरा के साथ शुरू करें";
"Settings.CustomColors.Header" = "खाता रंग";
"Settings.CustomColors.Saturation" = "संतृप्ति";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "खाता रंगों को निष्क्रिय करने के लिए संतृप्ति को 0%% पर सेट करें";
"Settings.UploadsBoost" = "अपलोड बूस्ट";
"Settings.DownloadsBoost" = "डाउनलोड बूस्ट";
"Settings.DownloadsBoost.none" = "निष्क्रिय";
"Settings.DownloadsBoost.medium" = "माध्यम";
"Settings.DownloadsBoost.maximum" = "अधिकतम";
"Settings.ShowProfileID" = "प्रोफ़ाइल ID दिखाएं";
"Settings.ShowDC" = "डेटा सेंटर दिखाएं";
"Settings.ShowCreationDate" = "चैट निर्माण तिथि दिखाएं";
"Settings.ShowCreationDate.Notice" = "कुछ चैट के लिए निर्माण तिथि अज्ञात हो सकती है।";
"Settings.ShowRegDate" = "पंजीकरण दिनांक दिखाएं";
"Settings.ShowRegDate.Notice" = "पंजीकरण दिनांक अनुमानित हो सकती है।";
"Settings.SendWithReturnKey" = "\"वापसी\" कुंजी के साथ भेजें";
"Settings.HidePhoneInSettingsUI" = "सेटिंग्स में फोन छिपाएं";
"Settings.HidePhoneInSettingsUI.Notice" = "आपका नंबर केवल सेटिंग्स UI में छिपा होगा। इसे दूसरों से छिपाने के लिए गोपनीयता सेटिंग्स में जाएं।";
"PasscodeSettings.AutoLock.InFiveSeconds" = "5 सेकंड के लिए दूर रहने पर";
"ProxySettings.UseSystemDNS" = "सिस्टम डीएनएस का प्रयोग करें";
"ProxySettings.UseSystemDNS.Notice" = "यदि आपके पास Google DNS तक पहुँच नहीं है तो टाइमआउट से बचने के लिए सिस्टम DNS का उपयोग करें";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "आपको %@ की **आवश्यकता नहीं** है!";
"Common.RestartRequired" = "पुनः आरंभ की आवश्यकता";
"Common.RestartNow" = "अभी रीस्टार्ट करें";
"Common.OpenTelegram" = "टेलीग्राम खोलें";
"Common.UseTelegramForPremium" = "कृपया ध्यान दें कि टेलीग्राम प्रीमियम प्राप्त करने के लिए आपको आधिकारिक टेलीग्राम ऐप का उपयोग करना होगा। एक बार जब आप टेलीग्राम प्रीमियम प्राप्त कर लेंगे, तो इसकी सभी सुविधाएं स्विफ्टग्राम में उपलब्ध हो जाएंगी।";
"Message.HoldToShowOrReport" = "दिखाने या रिपोर्ट करने के लिए दबाए रखें।";
"Auth.AccountBackupReminder" = "सुनिश्चित करें कि आपके पास बैकअप एक्सेस विधि है। एसएमएस के लिए एक सिम रखें या बाहर निकलने से बचने के लिए एक अतिरिक्त सत्र में लॉग इन करें।";
"Auth.UnofficialAppCodeTitle" = "आप केवल आधिकारिक ऐप से ही कोड प्राप्त कर सकते हैं";
"Settings.SmallReactions" = "छोटी-छोटी प्रतिक्रियाएँ";
"Settings.HideReactions" = "प्रतिक्रियाएँ छिपाएं";
"ContextMenu.SaveToCloud" = "क्लाउड में सहेजें";
"ContextMenu.SelectFromUser" = "लेखक में से चुनें";
"Settings.ContextMenu" = "संदर्भ मेनू";
"Settings.ContextMenu.Notice" = "अक्षम प्रविष्टियाँ \"स्विफ्टग्राम\" उप-मेनू में उपलब्ध होंगी।";
"Settings.ChatSwipeOptions" = "चैटलिस्ट स्वाइप विकल्प";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "अगले अपठित चैनल पर खींचें";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "अगले विषय को खींचें";
"Settings.GalleryCamera" = "गैलरी में कैमरा";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" बटन";
"Settings.SnapDeletionEffect" = "संदेश विलोपन प्रभाव";
"Settings.Stickers.Size" = "आकार";
"Settings.Stickers.Timestamp" = "टाइमस्टैंप दिखाएं";
"Settings.RecordingButton" = "वॉयस रिकॉर्डिंग बटन";
"Settings.DefaultEmojisFirst" = "मुख्यत: मानक इमोजी को प्राथमिकता दें";
"Settings.DefaultEmojisFirst.Notice" = "इमोजी कीबोर्ड में प्रीमियम से पहले मानक इमोजी दिखाएं";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "बनाया गया: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "%@ में शामिल हो गया";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "पंजीकृत";
"Settings.messageDoubleTapActionOutgoingEdit" = "संदेश संपादित करने के लिए दो बार टैप करें";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Tartalombeállítások";
"Settings.Tabs.Header" = "FÜLEK";
"Settings.Tabs.HideTabBar" = "Feliratcsík elrejtése";
"Settings.Tabs.ShowContacts" = "Kapcsolatok fül megjelenítése";
"Settings.Tabs.ShowNames" = "Feliratcsík nevek megjelenítése";
"Settings.Folders.BottomTab" = "Könyvtárak az alján";
"Settings.Folders.BottomTabStyle" = "Alsó könyvtár stílus";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Elrejtése \"%@\"";
"Settings.Folders.RememberLast" = "Utolsó mappa megnyitása";
"Settings.Folders.RememberLast.Notice" = "A Swiftgram az utoljára használt mappát fogja megnyitni, amikor újraindítja az alkalmazást vagy fiókok között vált.";
"Settings.Folders.CompactNames" = "Kisebb térköz";
"Settings.Folders.AllChatsTitle" = "\"Minden Beszélgetés\" cím";
"Settings.Folders.AllChatsTitle.short" = "Rövid";
"Settings.Folders.AllChatsTitle.long" = "Hosszú";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Alapértelmezett";
"Settings.ChatList.Header" = "BESZÉLGETÉS LISTA";
"Settings.CompactChatList" = "Kompakt Beszélgetés Lista";
"Settings.Profiles.Header" = "PROFIL";
"Settings.Stories.Hide" = "Történetek elrejtése";
"Settings.Stories.WarnBeforeView" = "Kérdezzen megtekintés előtt";
"Settings.Stories.DisableSwipeToRecord" = "Húzás letiltása felvételhez";
"Settings.Translation.QuickTranslateButton" = "Gyors Fordítás gomb";
"Stories.Warning.Author" = "Szerző";
"Stories.Warning.ViewStory" = "Történet megtekintése?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ LÁTNI FOGJA, hogy megtekintetted a történetüket.";
"Stories.Warning.NoticeStealth" = "%@ nem fogja látni, hogy megtekintetted a történetüket.";
"Settings.Photo.Quality.Notice" = "Feltöltött fényképek és történetek minősége.";
"Settings.Photo.SendLarge" = "Nagy fényképek küldése";
"Settings.Photo.SendLarge.Notice" = "Növelje a tömörített képek oldalméretének határát 2560px-re.";
"Settings.VideoNotes.Header" = "KEREK VIDEÓK";
"Settings.VideoNotes.StartWithRearCam" = "Kezdje a hátsó kamerával";
"Settings.CustomColors.Header" = "FIÓK SZÍNEI";
"Settings.CustomColors.Saturation" = "TELÍTETTSÉG";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Színértéket 0%%-ra állítva az fiókszíneket letiltja.";
"Settings.UploadsBoost" = "Feltöltés fokozása";
"Settings.DownloadsBoost" = "Letöltés fokozása";
"Settings.DownloadsBoost.none" = "Kikapcsolva";
"Settings.DownloadsBoost.medium" = "Közepes";
"Settings.DownloadsBoost.maximum" = "Maximális";
"Settings.ShowProfileID" = "Profil azonosító megjelenítése";
"Settings.ShowDC" = "Adatközpont megjelenítése";
"Settings.ShowCreationDate" = "Beszélgetés létrehozásának dátumának megjelenítése";
"Settings.ShowCreationDate.Notice" = "A beszélgetés létrehozásának dátuma ismeretlen lehet néhány csevegésnél.";
"Settings.ShowRegDate" = "Regisztrációs Dátum Megjelenítése";
"Settings.ShowRegDate.Notice" = "A regisztrációs dátum csak hozzávetőleges.";
"Settings.SendWithReturnKey" = "Küldés 'vissza' gombbal";
"Settings.HidePhoneInSettingsUI" = "Telefonszám elrejtése a beállításokban";
"Settings.HidePhoneInSettingsUI.Notice" = "Ezzel csak a telefonszámát rejti el a beállítások felületen. Ha mások számára is el akarja rejteni, menjen a Adatvédelem és biztonság menübe.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Ha 5 másodpercig távol van";
"ProxySettings.UseSystemDNS" = "Rendszer DNS használata";
"ProxySettings.UseSystemDNS.Notice" = "Használja a rendszer DNS-t, ha nem fér hozzá a Google DNS-hez";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Nem **szükséges** %@!";
"Common.RestartRequired" = "Újraindítás szükséges";
"Common.RestartNow" = "Újraindítás most";
"Common.OpenTelegram" = "Telegram megnyitása";
"Common.UseTelegramForPremium" = "Kérjük vegye figyelembe, hogy a Telegram Prémiumhoz az hivatalos Telegram appot kell használnia. Amint megkapta a Telegram Prémiumot, Swiftgram összes funkciója elérhető lesz.";
"Message.HoldToShowOrReport" = "Tartsa lenyomva a Megjelenítéshez vagy Jelentéshez.";
"Auth.AccountBackupReminder" = "Győződjön meg róla, hogy van biztonsági másolat hozzáférési módszere. Tartsa meg a SMS-hez használt SIM-et vagy egy másik bejelentkezett munkamenetet, hogy elkerülje a kizárást.";
"Auth.UnofficialAppCodeTitle" = "A kódot csak a hivatalos alkalmazással szerezheti meg";
"Settings.SmallReactions" = "Kis reakciók";
"Settings.HideReactions" = "Reakciók Elrejtése";
"ContextMenu.SaveToCloud" = "Mentés a Felhőbe";
"ContextMenu.SelectFromUser" = "Kiválasztás a Szerzőtől";
"Settings.ContextMenu" = "KONTEXTUS MENÜ";
"Settings.ContextMenu.Notice" = "A kikapcsolt bejegyzések elérhetők lesznek a 'Swiftgram' almenüjében.";
"Settings.ChatSwipeOptions" = "Csevegőlista húzás opciók";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Húzza a következő olvasatlan csatornához";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Húzza le a következő témához";
"Settings.GalleryCamera" = "Kamera a Galériában";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Gomb";
"Settings.SnapDeletionEffect" = "Üzenet törlés hatások";
"Settings.Stickers.Size" = "MÉRET";
"Settings.Stickers.Timestamp" = "Időbélyeg Megjelenítése";
"Settings.RecordingButton" = "Hangrögzítés Gomb";
"Settings.DefaultEmojisFirst" = "Prioritize standard emojis";
"Settings.DefaultEmojisFirst.Notice" = "Mutassa az alap emojisokat az emoji billentyűzet előtt a prémiumok helyett";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "létrehozva: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Csatlakozott %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Regisztrált";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dupla koppintás a üzenet szerkesztéséhez";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Pengaturan Konten";
"Settings.Tabs.Header" = "TABS";
"Settings.Tabs.HideTabBar" = "Sembunyikan Tab bar";
"Settings.Tabs.ShowContacts" = "Tampilkan Tab Kontak";
"Settings.Tabs.ShowNames" = "Tampilkan Nama Tab";
"Settings.Folders.BottomTab" = "Folder di bawah";
"Settings.Folders.BottomTabStyle" = "Gaya folder bawah";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Sembunyikan \"%@\"";
"Settings.Folders.RememberLast" = "Buka folder terakhir";
"Settings.Folders.RememberLast.Notice" = "Swiftgram akan membuka folder yang terakhir digunakan setelah restart atau pergantian akun";
"Settings.Folders.CompactNames" = "Pemisahan yang Lebih Kecil";
"Settings.Folders.AllChatsTitle" = "Judul \"Semua Obrolan\"";
"Settings.Folders.AllChatsTitle.short" = "Pendek";
"Settings.Folders.AllChatsTitle.long" = "Panjang";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Default";
"Settings.ChatList.Header" = "DAFTAR OBROLAN";
"Settings.CompactChatList" = "Daftar Obrolan Kompak";
"Settings.Profiles.Header" = "PROFIL";
"Settings.Stories.Hide" = "Sembunyikan Cerita";
"Settings.Stories.WarnBeforeView" = "Tanyakan sebelum melihat";
"Settings.Stories.DisableSwipeToRecord" = "Nonaktifkan geser untuk merekam";
"Settings.Translation.QuickTranslateButton" = "Bottone di traduzione rapida";
"Stories.Warning.Author" = "Penulis";
"Stories.Warning.ViewStory" = "Lihat Cerita?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ AKAN TAHU bahwa Anda telah melihat Cerita mereka.";
"Stories.Warning.NoticeStealth" = "%@ tidak akan tahu bahwa Anda telah melihat Cerita mereka.";
"Settings.Photo.Quality.Notice" = "Kualitas foto keluar dan cerita foto";
"Settings.Photo.SendLarge" = "Kirim foto berukuran besar";
"Settings.Photo.SendLarge.Notice" = "Tingkatkan batas sisi pada gambar terkompresi menjadi 2560px";
"Settings.VideoNotes.Header" = "VIDEO BULAT";
"Settings.VideoNotes.StartWithRearCam" = "Mulai dengan kamera belakang";
"Settings.CustomColors.Header" = "WARNA AKUN";
"Settings.CustomColors.Saturation" = "SATURASI";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Setel saturasi menjadi 0%% untuk menonaktifkan warna akun";
"Settings.UploadsBoost" = "Peningkatan Unggahan";
"Settings.DownloadsBoost" = "Peningkatan Unduhan";
"Settings.DownloadsBoost.none" = "Nonaktif";
"Settings.DownloadsBoost.medium" = "Sedang";
"Settings.DownloadsBoost.maximum" = "Maksimal";
"Settings.ShowProfileID" = "Tampilkan ID Profil";
"Settings.ShowDC" = "Tampilkan Pusat Data";
"Settings.ShowCreationDate" = "Tampilkan Tanggal Pembuatan Obrolan";
"Settings.ShowCreationDate.Notice" = "Tanggal pembuatan mungkin tidak diketahui untuk beberapa obrolan.";
"Settings.ShowRegDate" = "Tampilkan Tanggal Pendaftaran";
"Settings.ShowRegDate.Notice" = "Tanggal pendaftaran adalah perkiraan.";
"Settings.SendWithReturnKey" = "Kirim dengan kunci \"kembali\"";
"Settings.HidePhoneInSettingsUI" = "Sembunyikan nomor telepon di pengaturan";
"Settings.HidePhoneInSettingsUI.Notice" = "Nomor Anda akan disembunyikan hanya di UI Pengaturan. Kunjungi Pengaturan Privasi untuk menyembunyikannya dari orang lain.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Jika menjauh selama 5 detik";
"ProxySettings.UseSystemDNS" = "Gunakan DNS sistem";
"ProxySettings.UseSystemDNS.Notice" = "Gunakan DNS sistem untuk menghindari timeout jika Anda tidak memiliki akses ke Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Anda **tidak memerlukan** %@!";
"Common.RestartRequired" = "Diperlukan restart";
"Common.RestartNow" = "Restart Sekarang";
"Common.OpenTelegram" = "Buka Telegram";
"Common.UseTelegramForPremium" = "Harap dicatat bahwa untuk mendapatkan Telegram Premium, Anda harus menggunakan aplikasi Telegram resmi. Setelah Anda mendapatkan Telegram Premium, semua fiturnya akan tersedia di Swiftgram.";
"Message.HoldToShowOrReport" = "Tahan untuk Menampilkan atau Melaporkan.";
"Auth.AccountBackupReminder" = "Pastikan Anda memiliki metode akses cadangan. Simpan SIM untuk SMS atau sesi tambahan yang masuk untuk menghindari terkunci.";
"Auth.UnofficialAppCodeTitle" = "Anda hanya dapat mendapatkan kode dengan aplikasi resmi";
"Settings.SmallReactions" = "Reaksi kecil";
"Settings.HideReactions" = "Sembunyikan Reaksi";
"ContextMenu.SaveToCloud" = "Simpan ke Cloud";
"ContextMenu.SelectFromUser" = "Pilih dari Penulis";
"Settings.ContextMenu" = "MENU KONTEKS";
"Settings.ContextMenu.Notice" = "Entri yang dinonaktifkan akan tersedia di sub-menu \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "Opsi gesek daftar obrolan";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Tarik untuk obrolan berikutnya";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Tarik ke Topik Berikutnya";
"Settings.GalleryCamera" = "Kamera di galeri";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Tombol \"%@\"";
"Settings.SnapDeletionEffect" = "Efek penghapusan pesan";
"Settings.Stickers.Size" = "UKURAN";
"Settings.Stickers.Timestamp" = "Tampilkan Timestamp";
"Settings.RecordingButton" = "Tombol Perekaman Suara";
"Settings.DefaultEmojisFirst" = "Berikan prioritas pada emoji standar";
"Settings.DefaultEmojisFirst.Notice" = "Tampilkan emoji standar sebelum emoji premium di papan tombol emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "dibuat: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Bergabung %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Terdaftar";
"Settings.messageDoubleTapActionOutgoingEdit" = "Ketuk dua kali untuk mengedit pesan";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Impostazioni Contenuto";
"Settings.Tabs.Header" = "TAB";
"Settings.Tabs.HideTabBar" = "Nascondi barra della tab";
"Settings.Tabs.ShowContacts" = "Mostra tab contatti";
"Settings.Tabs.ShowNames" = "Mostra nomi tab";
"Settings.Folders.BottomTab" = "Cartelle in basso";
"Settings.Folders.BottomTabStyle" = "Stile cartelle in basso";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Nascondi \"%@\"";
"Settings.Folders.RememberLast" = "Apri l'ultima cartella";
"Settings.Folders.RememberLast.Notice" = "Swiftgram aprirà l'ultima cartella utilizzata dopo il riavvio o il cambio account";
"Settings.Folders.CompactNames" = "Spaziatura minore";
"Settings.Folders.AllChatsTitle" = "Titolo \"Tutte le chat\"";
"Settings.Folders.AllChatsTitle.short" = "Breve";
"Settings.Folders.AllChatsTitle.long" = "Lungo";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Predefinito";
"Settings.ChatList.Header" = "ELENCO CHAT";
"Settings.CompactChatList" = "Lista chat compatta";
"Settings.Profiles.Header" = "PROFILI";
"Settings.Stories.Hide" = "Nascondi Storie";
"Settings.Stories.WarnBeforeView" = "Chiedi prima di visualizzare";
"Settings.Stories.DisableSwipeToRecord" = "Disabilita lo scorrimento per registrare";
"Settings.Translation.QuickTranslateButton" = "Pulsante traduzione rapida";
"Stories.Warning.Author" = "Autore";
"Stories.Warning.ViewStory" = "Visualizzare la storia?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ SAPRÀ CHE HAI VISTO la storia.";
"Stories.Warning.NoticeStealth" = "%@ non saprà che hai visto la storia.";
"Settings.Photo.Quality.Notice" = "Qualità delle foto inviate e foto nelle storie";
"Settings.Photo.SendLarge" = "Invia foto di grandi dimensioni";
"Settings.Photo.SendLarge.Notice" = "Aumenta il limite sulla compressione delle foto a 2560px";
"Settings.VideoNotes.Header" = "Videomessaggi";
"Settings.VideoNotes.StartWithRearCam" = "Inizia con la camera posteriore";
"Settings.CustomColors.Header" = "COLORI ACCOUNT";
"Settings.CustomColors.Saturation" = "SATURAZIONE";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Imposta la saturazione a 0%% per disabilitare i colori dell'account";
"Settings.UploadsBoost" = "Potenziamento del caricamento";
"Settings.DownloadsBoost" = "Potenziamento dello scaricamento";
"Settings.DownloadsBoost.none" = "Disabilitato";
"Settings.DownloadsBoost.medium" = "Intermedio";
"Settings.DownloadsBoost.maximum" = "Massimo";
"Settings.ShowProfileID" = "Mostra l'ID del profilo";
"Settings.ShowDC" = "Mostra Data Center";
"Settings.ShowCreationDate" = "Mostra data di creazione della chat";
"Settings.ShowCreationDate.Notice" = "La data di creazione potrebbe essere sconosciuta per alcune chat.";
"Settings.ShowRegDate" = "Mostra data di registrazione";
"Settings.ShowRegDate.Notice" = "La data di registrazione è approssimativa.";
"Settings.SendWithReturnKey" = "Pulsante \"Invia\" per inviare";
"Settings.HidePhoneInSettingsUI" = "Nascondi il numero di telefono nelle impostazioni";
"Settings.HidePhoneInSettingsUI.Notice" = "Il tuo numero verrà nascosto solo nell'interfaccia. Per nasconderlo dagli altri, apri le impostazioni della Privacy.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Se assente per 5 secondi";
"ProxySettings.UseSystemDNS" = "Usa DNS di sistema";
"ProxySettings.UseSystemDNS.Notice" = "Usa DNS di sistema per bypassare il timeout se non hai accesso al DNS di Google";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "**Non hai bisogno** di %@!";
"Common.RestartRequired" = "Riavvio richiesto";
"Common.RestartNow" = "Riavvia Adesso";
"Common.OpenTelegram" = "Apri Telegram";
"Common.UseTelegramForPremium" = "Si prega di notare che per ottenere Telegram Premium, è necessario utilizzare l'app ufficiale Telegram. Una volta ottenuto Telegram Premium, tutte le sue funzionalità saranno disponibili su Swiftgram.";
"Message.HoldToShowOrReport" = "Tieni premuto per mostrare o segnalare.";
"Auth.AccountBackupReminder" = "Assicurati di avere un metodo di accesso di backup. Tieni una SIM per gli SMS o delle sessioni aperte su altri dispositivi per evitare di essere bloccato fuori.";
"Auth.UnofficialAppCodeTitle" = "Puoi ottenere il codice solo con l'applicazione ufficiale";
"Settings.SmallReactions" = "Reazioni piccole";
"Settings.HideReactions" = "Nascondi Reazioni";
"ContextMenu.SaveToCloud" = "Salva sul cloud";
"ContextMenu.SelectFromUser" = "Seleziona dall'autore";
"Settings.ContextMenu" = "MENU CONTESTUALE";
"Settings.ContextMenu.Notice" = "Le voci disabilitate saranno disponibili nel sottomenu \"Swiftgram\".";
"Settings.ChatSwipeOptions" = "Opzioni scorrimento nella lista delle chat";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Tira per il prossimo canale non letto";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Scorri per il prossimo topic";
"Settings.GalleryCamera" = "Fotocamera nella galleria";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Pulsante \"%@\"";
"Settings.SnapDeletionEffect" = "Effetti eliminazione messaggi";
"Settings.Stickers.Size" = "DIMENSIONE";
"Settings.Stickers.Timestamp" = "Mostra timestamp";
"Settings.RecordingButton" = "Pulsante per la registrazione vocale";
"Settings.DefaultEmojisFirst" = "Dare priorità agli emoji standard";
"Settings.DefaultEmojisFirst.Notice" = "Mostra gli emoji standard prima dei premium nella tastiera degli emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "creato il: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Sì è unito a %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrato";
"Settings.messageDoubleTapActionOutgoingEdit" = "Doppio tap per modificare il messaggio";

View File

@ -0,0 +1,129 @@
"Settings.ContentSettings" = "コンテンツの設定";
"Settings.Tabs.Header" = "タブ";
"Settings.Tabs.HideTabBar" = "タブバーを非表示にする";
"Settings.Tabs.ShowContacts" = "連絡先のタブを表示";
"Settings.Tabs.ShowNames" = "タブの名前を隠す";
"Settings.Folders.BottomTab" = "フォルダーを下に表示";
"Settings.Folders.BottomTabStyle" = "チャットフォルダーのスタイル";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "\"%@\"を非表示";
"Settings.Folders.RememberLast" = "最後に開いたフォルダを開く";
"Settings.Folders.RememberLast.Notice" = "Swiftgramは再起動またはアカウント切替後に最後に使用したフォルダを開きます";
"Settings.Folders.CompactNames" = "より小さい間隔";
"Settings.Folders.AllChatsTitle" = "「すべてのチャット」タイトル";
"Settings.Folders.AllChatsTitle.short" = "Short";
"Settings.Folders.AllChatsTitle.long" = "長い順";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "デフォルト";
"Settings.ChatList.Header" = "チャットリスト";
"Settings.CompactChatList" = "コンパクトなチャットリスト";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "ストーリーを隠す";
"Settings.Stories.WarnBeforeView" = "視聴前に確認";
"Settings.Stories.DisableSwipeToRecord" = "スワイプで録画を無効にする";
"Settings.Translation.QuickTranslateButton" = "クイック翻訳ボタン";
"Stories.Warning.Author" = "投稿者";
"Stories.Warning.ViewStory" = "ストーリーを表示?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@はあなたがそのストーリーを見たことを確認できます。";
"Stories.Warning.NoticeStealth" = "%@はあなたがそのストーリーを見たことを確認できません。";
"Settings.Photo.Quality.Notice" = "送信する写真とフォトストーリーの品質";
"Settings.Photo.SendLarge" = "大きな写真を送信";
"Settings.Photo.SendLarge.Notice" = "圧縮画像のサイド制限を2560pxに増加";
"Settings.VideoNotes.Header" = "丸いビデオ";
"Settings.VideoNotes.StartWithRearCam" = "リアカメラで開始";
"Settings.CustomColors.Header" = "アカウントの色";
"Settings.CustomColors.Saturation" = "彩度";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "彩度を0%%に設定してアカウントの色を無効にする";
"Settings.UploadsBoost" = "アップロードブースト";
"Settings.DownloadsBoost" = "ダウンロードブースト";
"Settings.DownloadsBoost.none" = "無効";
"Settings.DownloadsBoost.medium" = "中程度";
"Settings.DownloadsBoost.maximum" = "最大";
"Settings.ShowProfileID" = "プロフィールIDを表示";
"Settings.ShowDC" = "データセンターを表示";
"Settings.ShowCreationDate" = "チャットの作成日を表示";
"Settings.ShowCreationDate.Notice" = "作成日が不明なチャットがあります。";
"Settings.ShowRegDate" = "登録日を表示";
"Settings.ShowRegDate.Notice" = "登録日はおおよその日です。";
"Settings.SendWithReturnKey" = "\"return\" キーで送信";
"Settings.HidePhoneInSettingsUI" = "設定で電話番号を隠す";
"Settings.HidePhoneInSettingsUI.Notice" = "あなたの番号は設定UIでのみ隠されます。他の人から隠すにはプライバシー設定に移動してください。";
"PasscodeSettings.AutoLock.InFiveSeconds" = "5秒間離れると自動ロック";
"ProxySettings.UseSystemDNS" = "システムDNSを使用";
"ProxySettings.UseSystemDNS.Notice" = "Google DNSにアクセスできない場合はシステムDNSを使用してタイムアウトを回避";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "** %@は必要ありません**";
"Common.RestartRequired" = "再起動が必要です";
"Common.RestartNow" = "今すぐ再実行";
"Common.OpenTelegram" = "Telegram を開く";
"Common.UseTelegramForPremium" = "Telegram Premiumを登録するには、公式のTelegramアプリが必要です。
登録すると、Swiftgram等の非公式アプリ含め、Telegram Premiumをサポートする全てのアプリでプレミアムメソッドを利用できます。";
"Message.HoldToShowOrReport" = "表示または報告するために押し続ける。";
"Auth.AccountBackupReminder" = "バックアップアクセス方法があることを確認してください。SMS用のSIMを保持するか、追加のセッションにログインしてロックアウトを避けてください。";
"Auth.UnofficialAppCodeTitle" = "テレグラムの公式アプリでのみログインコードを取得できます";
"Settings.SmallReactions" = "小さいリアクション";
"Settings.HideReactions" = "リアクションを非表示";
"ContextMenu.SaveToCloud" = "メッセージを保存";
"ContextMenu.SelectFromUser" = "全て選択";
"Settings.ContextMenu" = "コンテキスト メニュー";
"Settings.ContextMenu.Notice" = "無効化されたエントリは、「Swiftgram」サブメニューから利用できます。";
"Settings.ChatSwipeOptions" = "チャットリストのスワイプ設定";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "次の未読チャンネルまでプルする";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "次のトピックに移動する";
"Settings.GalleryCamera" = "ギャラリーのカメラを隠す";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" ボタン";
"Settings.SnapDeletionEffect" = "メッセージ削除のエフェクト";
"Settings.Stickers.Size" = "サイズ";
"Settings.Stickers.Timestamp" = "タイムスタンプを表示";
"Settings.RecordingButton" = "音声録音ボタン";
"Settings.DefaultEmojisFirst" = "標準エモジを優先";
"Settings.DefaultEmojisFirst.Notice" = "絵文字キーボードでプレミアムより前に標準エモジを表示";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "作成済み: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "%@ に参加しました";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "登録済み";
"Settings.messageDoubleTapActionOutgoingEdit" = "メッセージを編集するにはタップをダブルタップ";

View File

@ -0,0 +1,8 @@
"Settings.Tabs.Header" = "ថេប";
"Settings.Tabs.ShowContacts" = "បង្ហាញថេបទំនាក់ទំនង";
"Settings.VideoNotes.Header" = "រង្វង់វីដេអូ";
"Settings.VideoNotes.StartWithRearCam" = "ចាប់ផ្ដើមជាមួយកាមេរ៉ាក្រោយ";
"Settings.Tabs.ShowNames" = "បង្ហាញឈ្មោះថេប";
"Settings.HidePhoneInSettingsUI" = "លាក់លេខទូរសព្ទក្នុងការកំណត់";
"Settings.Folders.BottomTab" = "ថតឯបាត";
"ContextMenu.SaveToCloud" = "រក្សាទុកទៅពពក";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "콘텐츠 설정";
"Settings.Tabs.Header" = "탭";
"Settings.Tabs.HideTabBar" = "탭바숨기기";
"Settings.Tabs.ShowContacts" = "연락처 탭 보이기";
"Settings.Tabs.ShowNames" = "탭 이름 표시";
"Settings.Folders.BottomTab" = "폴더를 하단에 표시";
"Settings.Folders.BottomTabStyle" = "탭위치아래";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "\"%@\" 숨기기";
"Settings.Folders.RememberLast" = "마지막 폴더 열기";
"Settings.Folders.RememberLast.Notice" = "Swiftgram은 재시작하거나 계정을 전환한 후 마지막으로 사용한 폴더를 엽니다";
"Settings.Folders.CompactNames" = "간격 작게";
"Settings.Folders.AllChatsTitle" = "\"모든 채팅\" 제목";
"Settings.Folders.AllChatsTitle.short" = "단축";
"Settings.Folders.AllChatsTitle.long" = "긴";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "기본";
"Settings.ChatList.Header" = "채팅 목록";
"Settings.CompactChatList" = "간략한 채팅 목록";
"Settings.Profiles.Header" = "프로필";
"Settings.Stories.Hide" = "스토리 숨기기";
"Settings.Stories.WarnBeforeView" = "보기 전에 묻기";
"Settings.Stories.DisableSwipeToRecord" = "녹화를 위한 스와이프 비활성화";
"Settings.Translation.QuickTranslateButton" = "빠른 번역 버튼";
"Stories.Warning.Author" = "작성자";
"Stories.Warning.ViewStory" = "스토리 보기?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@님은 당신이 그들의 스토리를 봤는지 알 수 있습니다.";
"Stories.Warning.NoticeStealth" = "%@님은 당신이 그들의 스토리를 봤는지 알 수 없습니다.";
"Settings.Photo.Quality.Notice" = "보낸 사진과 포토스토리의 품질";
"Settings.Photo.SendLarge" = "큰 사진 보내기";
"Settings.Photo.SendLarge.Notice" = "압축 이미지의 크기 제한을 2560px로 증가";
"Settings.VideoNotes.Header" = "라운드 비디오";
"Settings.VideoNotes.StartWithRearCam" = "후면 카메라로 시작";
"Settings.CustomColors.Header" = "계정 색상";
"Settings.CustomColors.Saturation" = "채도";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "계정 색상을 비활성화하려면 채도를 0%%로 설정하세요";
"Settings.UploadsBoost" = "업로드 향상";
"Settings.DownloadsBoost" = "다운로드 향상";
"Settings.DownloadsBoost.none" = "비활성화";
"Settings.DownloadsBoost.medium" = "중간";
"Settings.DownloadsBoost.maximum" = "최대";
"Settings.ShowProfileID" = "프로필 ID 표시";
"Settings.ShowDC" = "데이터센터보기";
"Settings.ShowCreationDate" = "채팅 생성 날짜 표시";
"Settings.ShowCreationDate.Notice" = "몇몇 채팅에 대해서는 생성 날짜를 알 수 없을 수 있습니다.";
"Settings.ShowRegDate" = "가입 날짜 표시";
"Settings.ShowRegDate.Notice" = "가입 날짜는 대략적입니다.";
"Settings.SendWithReturnKey" = "\"리턴\" 키로 보내기";
"Settings.HidePhoneInSettingsUI" = "설정에서 전화번호 숨기기";
"Settings.HidePhoneInSettingsUI.Notice" = "전화 번호는 UI에서만 숨겨집니다. 다른 사람에게 숨기려면 개인 정보 설정을 사용하세요.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "5초 동안 떨어져 있으면";
"ProxySettings.UseSystemDNS" = "시스템 DNS 사용";
"ProxySettings.UseSystemDNS.Notice" = "Google DNS에 접근할 수 없는 경우 시스템 DNS를 사용하여 타임아웃 우회";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "%@이(가) **필요하지 않습니다**!";
"Common.RestartRequired" = "재시작 필요";
"Common.RestartNow" = "지금 재시작";
"Common.OpenTelegram" = "텔레그램 열기";
"Common.UseTelegramForPremium" = "텔레그램 프리미엄을 받으려면 공식 텔레그램 앱을 사용해야 합니다. 텔레그램 프리미엄을 획득하면 모든 기능이 Swiftgram에서 사용 가능해집니다.";
"Message.HoldToShowOrReport" = "보여주거나 신고하기 위해 길게 누르세요.";
"Auth.AccountBackupReminder" = "백업 접근 방법을 확보하세요. SMS용 SIM 카드를 보관하거나 추가 세션에 로그인하여 잠금을 피하세요.";
"Auth.UnofficialAppCodeTitle" = "코드는 공식 앱으로만 받을 수 있습니다";
"Settings.SmallReactions" = "작은 반응들";
"Settings.HideReactions" = "반응 숨기기";
"ContextMenu.SaveToCloud" = "클라우드에 저장";
"ContextMenu.SelectFromUser" = "사용자에서 선택";
"Settings.ContextMenu" = "컨텍스트 메뉴";
"Settings.ContextMenu.Notice" = "'Swiftgram' 하위 메뉴에서 비활성화된 항목을 사용할 수 있습니다.";
"Settings.ChatSwipeOptions" = "채팅 목록 스와이프 옵션";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "다음 읽지 않은 채널까지 당겨서 보기";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "다음 주제로 끌어당기기";
"Settings.GalleryCamera" = "갤러리 내 카메라";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" 버튼";
"Settings.SnapDeletionEffect" = "메시지 삭제 효과";
"Settings.Stickers.Size" = "크기";
"Settings.Stickers.Timestamp" = "시간 표시 표시";
"Settings.RecordingButton" = "음성 녹음 버튼";
"Settings.DefaultEmojisFirst" = "표준 이모지 우선순위 설정";
"Settings.DefaultEmojisFirst.Notice" = "이모지 키보드에서 프리미엄 이모지보다 표준 이모지 우선 표시";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "생성됨: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "%@에 가입함";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "가입함";
"Settings.messageDoubleTapActionOutgoingEdit" = "메시지 수정을 위해 두 번 탭";

View File

@ -0,0 +1,10 @@
"Settings.Tabs.Header" = "تابەکان";
"Settings.Tabs.ShowContacts" = "نیشاندانی تابی کۆنتاکتەکان";
"Settings.VideoNotes.Header" = "ڤیدیۆ بازنەییەکان";
"Settings.VideoNotes.StartWithRearCam" = "دەستپێکردن بە کامێرای پشتەوە";
"Settings.Tabs.ShowNames" = "نیشاندانی ناوی تابەکان";
"Settings.HidePhoneInSettingsUI" = "شاردنەوەی تەلەفۆن لە ڕێکخستنەکان";
"Settings.HidePhoneInSettingsUI.Notice" = "ژمارەکەت تەنها لە ڕووکارەکە دەرناکەوێت. بۆ ئەوەی لە ئەوانەی دیکەی بشاریتەوە، تکایە ڕێکخستنەکانی پارێزراوی بەکاربێنە.";
"Settings.Translation.QuickTranslateButton" = "دوگمەی وەرگێڕانی خێرا";
"Settings.Folders.BottomTab" = "بوخچەکان لە خوارەوە";
"ContextMenu.SaveToCloud" = "هەڵگرتن لە کڵاود";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Inhoudsinstellingen";
"Settings.Tabs.Header" = "TABS";
"Settings.Tabs.HideTabBar" = "Tabbladbalk verbergen";
"Settings.Tabs.ShowContacts" = "Toon Contacten Tab";
"Settings.Tabs.ShowNames" = "Show Tab Names";
"Settings.Folders.BottomTab" = "Mappen onderaan";
"Settings.Folders.BottomTabStyle" = "Onderste mappenstijl";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Verberg \"%@\"";
"Settings.Folders.RememberLast" = "Laatste map openen";
"Settings.Folders.RememberLast.Notice" = "Swiftgram zal de laatst gebruikte map openen wanneer u de app herstart of van account wisselt.";
"Settings.Folders.CompactNames" = "Kleinere afstand";
"Settings.Folders.AllChatsTitle" = "\"Alle Chats\" titel";
"Settings.Folders.AllChatsTitle.short" = "Kort";
"Settings.Folders.AllChatsTitle.long" = "Lang";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Standaard";
"Settings.ChatList.Header" = "CHAT LIJST";
"Settings.CompactChatList" = "Compacte Chat Lijst";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Verberg Verhalen";
"Settings.Stories.WarnBeforeView" = "Vragen voor bekijken";
"Settings.Stories.DisableSwipeToRecord" = "Swipe om op te nemen uitschakelen";
"Settings.Translation.QuickTranslateButton" = "Snelle Vertaalknop";
"Stories.Warning.Author" = "Auteur";
"Stories.Warning.ViewStory" = "Bekijk Verhaal?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ ZAL KUNNEN ZIEN dat je hun Verhaal hebt bekeken.";
"Stories.Warning.NoticeStealth" = "%@ zal niet kunnen zien dat je hun Verhaal hebt bekeken.";
"Settings.Photo.Quality.Notice" = "Kwaliteit van geüploade foto's en verhalen.";
"Settings.Photo.SendLarge" = "Verstuur grote foto's";
"Settings.Photo.SendLarge.Notice" = "Verhoog de zijlimiet bij gecomprimeerde afbeeldingen naar 2560px.";
"Settings.VideoNotes.Header" = "RONDE VIDEO'S";
"Settings.VideoNotes.StartWithRearCam" = "Start met achtercamera";
"Settings.CustomColors.Header" = "ACCOUNTKLEUREN";
"Settings.CustomColors.Saturation" = "VERZADIGING";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Zet op 0%% om accountkleuren uit te schakelen.";
"Settings.UploadsBoost" = "Upload Boost";
"Settings.DownloadsBoost" = "Download Boost";
"Settings.DownloadsBoost.none" = "Uitgeschakeld";
"Settings.DownloadsBoost.medium" = "Gemiddeld";
"Settings.DownloadsBoost.maximum" = "Maximaal";
"Settings.ShowProfileID" = "Toon profiel ID";
"Settings.ShowDC" = "Toon datacentrum";
"Settings.ShowCreationDate" = "Toon Chat Aanmaakdatum";
"Settings.ShowCreationDate.Notice" = "De aanmaakdatum kan onbekend zijn voor sommige chatten.";
"Settings.ShowRegDate" = "Toon registratiedatum";
"Settings.ShowRegDate.Notice" = "De registratiedatum is ongeveer hetzelfde.";
"Settings.SendWithReturnKey" = "Verstuur met 'return'-toets";
"Settings.HidePhoneInSettingsUI" = "Verberg telefoon in Instellingen";
"Settings.HidePhoneInSettingsUI.Notice" = "Dit verbergt alleen je telefoonnummer in de instellingen interface. Ga naar Privacy en Beveiliging om het voor anderen te verbergen.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Automatisch vergrendelen na 5 seconden";
"ProxySettings.UseSystemDNS" = "Gebruik systeem DNS";
"ProxySettings.UseSystemDNS.Notice" = "Gebruik systeem DNS om time-out te omzeilen als je geen toegang hebt tot Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Je hebt **geen %@ nodig**!";
"Common.RestartRequired" = "Herstart vereist";
"Common.RestartNow" = "Nu herstarten";
"Common.OpenTelegram" = "Open Telegram";
"Common.UseTelegramForPremium" = "Om Telegram Premium te krijgen moet je de officiële Telegram app gebruiken. Zodra je Telegram Premium hebt ontvangen, zullen alle functies ervan beschikbaar komen in Swiftgram.";
"Message.HoldToShowOrReport" = "Houd vast om te Tonen of te Rapporteren.";
"Auth.AccountBackupReminder" = "Zorg ervoor dat je een back-up toegangsmethode hebt. Houd een SIM voor SMS of een extra sessie ingelogd om buitensluiting te voorkomen.";
"Auth.UnofficialAppCodeTitle" = "Je kunt de code alleen krijgen met de officiële app";
"Settings.SmallReactions" = "Kleine reacties";
"Settings.HideReactions" = "Verberg Reacties";
"ContextMenu.SaveToCloud" = "Opslaan in de Cloud";
"ContextMenu.SelectFromUser" = "Selecteer van Auteur";
"Settings.ContextMenu" = "CONTEXTMENU";
"Settings.ContextMenu.Notice" = "Uitgeschakelde items zijn beschikbaar in het 'Swiftgram'-submenu.";
"Settings.ChatSwipeOptions" = "Veegopties voor chatlijst";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Trek naar het volgende ongelezen kanaal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Trek naar Volgend Onderwerp";
"Settings.GalleryCamera" = "Camera in Galerij";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" knop";
"Settings.SnapDeletionEffect" = "Verwijderde Berichten Effecten";
"Settings.Stickers.Size" = "GROOTTE";
"Settings.Stickers.Timestamp" = "Tijdstempel weergeven";
"Settings.RecordingButton" = "Spraakopname knop";
"Settings.DefaultEmojisFirst" = "Standaardemoji's prioriteren";
"Settings.DefaultEmojisFirst.Notice" = "Toon standaardemoji's vóór premium in emoji-toetsenbord";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "aangemaakt: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Lid geworden %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Geregistreerd";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dubbelklik om bericht te bewerken";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Innholdsinnstillinger";
"Settings.Tabs.Header" = "FANER";
"Settings.Tabs.HideTabBar" = "Skjul fanelinjen";
"Settings.Tabs.ShowContacts" = "Vis kontakter-fane";
"Settings.Tabs.ShowNames" = "Show Tab Names";
"Settings.Folders.BottomTab" = "Mapper på bunnen";
"Settings.Folders.BottomTabStyle" = "Stil for nedre mapper";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Skjul \"%@\"";
"Settings.Folders.RememberLast" = "Åpne siste mappe";
"Settings.Folders.RememberLast.Notice" = "Swiftgram vil åpne den sist brukte mappen når du starter appen på nytt eller bytter kontoer.";
"Settings.Folders.CompactNames" = "Mindre avstand";
"Settings.Folders.AllChatsTitle" = "\"Alle chater\" tittel";
"Settings.Folders.AllChatsTitle.short" = "Kort";
"Settings.Folders.AllChatsTitle.long" = "Lang";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Standard";
"Settings.ChatList.Header" = "CHAT LIST";
"Settings.CompactChatList" = "Kompakt liste";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Skjul Historier";
"Settings.Stories.WarnBeforeView" = "Spør før visning";
"Settings.Stories.DisableSwipeToRecord" = "Deaktiver sveip for å ta opp";
"Settings.Translation.QuickTranslateButton" = "Hurtigoversettelsesknapp";
"Stories.Warning.Author" = "Forfatter";
"Stories.Warning.ViewStory" = "Se Historie?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ VIL SE at du har sett deres Historie.";
"Stories.Warning.NoticeStealth" = "%@ vil ikke kunne se at du har sett deres Historie.";
"Settings.Photo.Quality.Notice" = "Kvalitet på opplastede bilder og historier.";
"Settings.Photo.SendLarge" = "Send store bilder";
"Settings.Photo.SendLarge.Notice" = "Øk grensen for komprimerte bilder til 2560 piksler.";
"Settings.VideoNotes.Header" = "RUNDE VIDEOER";
"Settings.VideoNotes.StartWithRearCam" = "Start med bakkamera";
"Settings.CustomColors.Header" = "KONTOFARGER";
"Settings.CustomColors.Saturation" = "METNING";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Satt til 0%% for å deaktivere kontofarger.";
"Settings.UploadsBoost" = "Ã k opplastingshastighet";
"Settings.DownloadsBoost" = "Last ned boost";
"Settings.DownloadsBoost.none" = "Deaktivert";
"Settings.DownloadsBoost.medium" = "Middels";
"Settings.DownloadsBoost.maximum" = "Maksimum";
"Settings.ShowProfileID" = "Vis profil-ID";
"Settings.ShowDC" = "Vis datasenter";
"Settings.ShowCreationDate" = "Vis chat opprettet dato";
"Settings.ShowCreationDate.Notice" = "Opprettelsesdatoen kan være ukjent for noen chat.";
"Settings.ShowRegDate" = "Vis registreringsdato";
"Settings.ShowRegDate.Notice" = "Registreringsdatoen er ca.";
"Settings.SendWithReturnKey" = "Send med 'retur'-tasten";
"Settings.HidePhoneInSettingsUI" = "Skjul telefonen i innstillinger";
"Settings.HidePhoneInSettingsUI.Notice" = "Dette vil bare skjule ditt telefonnummer for instillinger. For å skjule det for andre, gå til Personvern og Sikkerhet.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Hvis borte i 5 sekunder";
"ProxySettings.UseSystemDNS" = "Bruk system DNS";
"ProxySettings.UseSystemDNS.Notice" = "Bruk system DNS for å omgå timeout hvis du ikke har tilgang til Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Du **trenger ikke** %@!";
"Common.RestartRequired" = "Omstart kreves";
"Common.RestartNow" = "Omstart Nå";
"Common.OpenTelegram" = "Åpne Telegram";
"Common.UseTelegramForPremium" = "Vær oppmerksom på at for å få Telegram Premium, må du bruke den offisielle Telegram-appen. Når du har tatt Telegram Premium, vil alle funksjonene bli tilgjengelige i Swiftgram.";
"Message.HoldToShowOrReport" = "Hold for å vise eller rapportere.";
"Auth.AccountBackupReminder" = "Sørg for at du har en sikkerhetskopiert tilgangsmetode. Oppretthold en SIM for SMS eller en ekstra økt logget inn for å unngå å bli låst ute.";
"Auth.UnofficialAppCodeTitle" = "Du kan bare få koden med den offisielle appen";
"Settings.SmallReactions" = "Liten Reaksjon";
"Settings.HideReactions" = "Skjul Reaksjoner";
"ContextMenu.SaveToCloud" = "Lagre til skyen";
"ContextMenu.SelectFromUser" = "Velg fra forfatter";
"Settings.ContextMenu" = "KONTEKSTMENY";
"Settings.ContextMenu.Notice" = "Deaktiverte oppføringer vil være tilgjengelige i 'Swiftgram'-undermenyen.";
"Settings.ChatSwipeOptions" = "Chat liste sveip alternativer";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Dra til neste uleste kanal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Dra til neste emne";
"Settings.GalleryCamera" = "Kamera i galleri";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" knapp";
"Settings.SnapDeletionEffect" = "Sletting av melding effekter";
"Settings.Stickers.Size" = "STØRRELSE";
"Settings.Stickers.Timestamp" = "Vis tidsstempel";
"Settings.RecordingButton" = "Tale opptaksknapp";
"Settings.DefaultEmojisFirst" = "Prioriter standard emojis";
"Settings.DefaultEmojisFirst.Notice" = "Vis standard emojis før premium på emoji-tastaturet";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "opprettet: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Ble med %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrert";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dobbelttrykk for å redigere meldingen";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Ustawienia zawartości";
"Settings.Tabs.Header" = "ZAKŁADKI";
"Settings.Tabs.HideTabBar" = "Ukryj pasek zakładek";
"Settings.Tabs.ShowContacts" = "Pokaż zakładkę kontakty";
"Settings.Tabs.ShowNames" = "Pokaż nazwy zakładek";
"Settings.Folders.BottomTab" = "Foldery na dole";
"Settings.Folders.BottomTabStyle" = "Styl folderów na dole";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Ukryj \"%@\"";
"Settings.Folders.RememberLast" = "Otwórz ostatni folder";
"Settings.Folders.RememberLast.Notice" = "Swiftgram otworzy ostatnio używany folder po ponownym uruchomieniu lub zmianie konta";
"Settings.Folders.CompactNames" = "Mniejszy odstęp";
"Settings.Folders.AllChatsTitle" = "Tytuł \"Wszystkie czaty\"";
"Settings.Folders.AllChatsTitle.short" = "Krótki";
"Settings.Folders.AllChatsTitle.long" = "Długie";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Domyślny";
"Settings.ChatList.Header" = "LISTA CZATU";
"Settings.CompactChatList" = "Kompaktowa lista czatów";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Ukryj relacje";
"Settings.Stories.WarnBeforeView" = "Pytaj przed wyświetleniem";
"Settings.Stories.DisableSwipeToRecord" = "Wyłącz przeciągnij, aby nagrać";
"Settings.Translation.QuickTranslateButton" = "Przycisk Szybkie tłumaczenie";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Zobaczyć relację?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ BĘDZIE WIEDZIAŁ, że obejrzano jego relację.";
"Stories.Warning.NoticeStealth" = "%@ nie będzie wiedział, że obejrzano jego relację.";
"Settings.Photo.Quality.Notice" = "Jakość wysyłanych zdjęć i fotorelacji";
"Settings.Photo.SendLarge" = "Wyślij duże zdjęcia";
"Settings.Photo.SendLarge.Notice" = "Zwiększ limit rozmiaru skompresowanych obrazów do 2560px";
"Settings.VideoNotes.Header" = "OKRĄGŁE WIDEO";
"Settings.VideoNotes.StartWithRearCam" = "Uruchom z tylną kamerą";
"Settings.CustomColors.Header" = "KOLORY KONTA";
"Settings.CustomColors.Saturation" = "NASYCENIE";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Ustaw nasycenie na 0%%, aby wyłączyć kolory konta";
"Settings.UploadsBoost" = "Przyśpieszenie wysyłania";
"Settings.DownloadsBoost" = "Przyśpieszenie pobierania";
"Settings.DownloadsBoost.none" = "Wyłączone";
"Settings.DownloadsBoost.medium" = "Średnie";
"Settings.DownloadsBoost.maximum" = "Maksymalne";
"Settings.ShowProfileID" = "Pokaż ID";
"Settings.ShowDC" = "Pokaż centrum danych";
"Settings.ShowCreationDate" = "Pokaż datę utworzenia czatu";
"Settings.ShowCreationDate.Notice" = "Data utworzenia może być nieznana dla niektórych czatów.";
"Settings.ShowRegDate" = "Pokaż datę rejestracji";
"Settings.ShowRegDate.Notice" = "Data rejestracji jest przybliżona.";
"Settings.SendWithReturnKey" = "Wyślij klawiszem „return”";
"Settings.HidePhoneInSettingsUI" = "Ukryj numer telefonu w ustawieniach";
"Settings.HidePhoneInSettingsUI.Notice" = "Twój numer zostanie ukryty tylko w interfejsie użytkownika. Aby ukryć go przed innymi, użyj ustawień prywatności.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Jeśli nieobecny przez 5 sekund";
"ProxySettings.UseSystemDNS" = "Użyj systemowego DNS";
"ProxySettings.UseSystemDNS.Notice" = "Użyj systemowego DNS, aby ominąć limit czasu, jeśli nie masz dostępu do Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Nie **potrzebujesz** %@!";
"Common.RestartRequired" = "Wymagany restart";
"Common.RestartNow" = "Uruchom teraz ponownie";
"Common.OpenTelegram" = "Otwórz Telegram";
"Common.UseTelegramForPremium" = "Pamiętaj, że aby otrzymać Telegram Premium, musisz skorzystać z oficjalnej aplikacji Telegram. Po uzyskaniu Telegram Premium wszystkie jego funkcje staną się dostępne w Swiftgram.";
"Message.HoldToShowOrReport" = "Przytrzymaj, aby Pokazać lub Zgłosić.";
"Auth.AccountBackupReminder" = "Upewnij się, że masz zapasową metodę dostępu. Zachowaj SIM do SMS-ów lub zalogowaną dodatkową sesję, aby uniknąć zablokowania.";
"Auth.UnofficialAppCodeTitle" = "Kod można uzyskać tylko za pomocą oficjalnej aplikacji";
"Settings.SmallReactions" = "Małe reakcje";
"Settings.HideReactions" = "Ukryj Reakcje";
"ContextMenu.SaveToCloud" = "Zapisz w chmurze";
"ContextMenu.SelectFromUser" = "Zaznacz od autora";
"Settings.ContextMenu" = "MENU KONTEKSTOWE";
"Settings.ContextMenu.Notice" = "Wyłączone wpisy będą dostępne w podmenu „Swiftgram”.";
"Settings.ChatSwipeOptions" = "Opcje przesuwania listy czatów";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Pociągnij ➝ następny kanał";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Przeciągnij, aby przejść do następnego tematu";
"Settings.GalleryCamera" = "Aparat w galerii";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Przycisk „%@”";
"Settings.SnapDeletionEffect" = "Efekty usuwania wiadomości";
"Settings.Stickers.Size" = "WIELKOŚĆ";
"Settings.Stickers.Timestamp" = "Pokaż znak czasu";
"Settings.RecordingButton" = "Przycisk głośności nagrywania";
"Settings.DefaultEmojisFirst" = "Wybierz standardowe emotikony";
"Settings.DefaultEmojisFirst.Notice" = "Pokaż standardowe emotikony przed premium na klawiaturze emotikonów";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "utworzony: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Dołączył %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Zarejestrowane";
"Settings.messageDoubleTapActionOutgoingEdit" = "Podwójne stuknięcie, aby edytować wiadomość";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Configurações de Conteúdo";
"Settings.Tabs.Header" = "ABAS";
"Settings.Tabs.HideTabBar" = "Ocultar Abas de Guias";
"Settings.Tabs.ShowContacts" = "Mostrar Aba dos Contatos";
"Settings.Tabs.ShowNames" = "Mostrar nomes das abas";
"Settings.Folders.BottomTab" = "Pastas embaixo";
"Settings.Folders.BottomTabStyle" = "Estilos de Pastas Inferiores";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Ocultar \"%@\"";
"Settings.Folders.RememberLast" = "Abrir última pasta";
"Settings.Folders.RememberLast.Notice" = "O Swiftgram abrirá a última pasta usada após reiniciar ou trocar de conta";
"Settings.Folders.CompactNames" = "Espaçamento Menor";
"Settings.Folders.AllChatsTitle" = "Título \"Todos os bate-papos\"";
"Settings.Folders.AllChatsTitle.short" = "Curto";
"Settings.Folders.AllChatsTitle.long" = "Longas";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Padrão";
"Settings.ChatList.Header" = "LISTA DE CHAT";
"Settings.CompactChatList" = "Lista de Bate-Papo Compacta";
"Settings.Profiles.Header" = "Perfis";
"Settings.Stories.Hide" = "Ocultar Stories";
"Settings.Stories.WarnBeforeView" = "Perguntar antes de visualizar";
"Settings.Stories.DisableSwipeToRecord" = "Desativar deslize para gravar";
"Settings.Translation.QuickTranslateButton" = "Botão de Tradução Rápida";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Ver Story?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ SABERÁ que você viu a Story dele.";
"Stories.Warning.NoticeStealth" = "%@ não saberá que você viu a Story dele.";
"Settings.Photo.Quality.Notice" = "Qualidade de fotos enviadas e photo-stories";
"Settings.Photo.SendLarge" = "Enviar fotos grandes";
"Settings.Photo.SendLarge.Notice" = "Aumentar o limite de tamanho de imagens comprimidas para 2560px";
"Settings.VideoNotes.Header" = "VÍDEOS REDONDOS";
"Settings.VideoNotes.StartWithRearCam" = "Iniciar com a câmera traseira";
"Settings.CustomColors.Header" = "CORES DA CONTA";
"Settings.CustomColors.Saturation" = "SATURAÇÃO";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Defina a saturação para 0%% para desativar as cores da conta";
"Settings.UploadsBoost" = "Aceleração de Uploads";
"Settings.DownloadsBoost" = "Aceleração de Downloads";
"Settings.DownloadsBoost.none" = "Desativado";
"Settings.DownloadsBoost.medium" = "Médio";
"Settings.DownloadsBoost.maximum" = "Máximo";
"Settings.ShowProfileID" = "Mostrar perfil";
"Settings.ShowDC" = "Mostrar Centro de Dados";
"Settings.ShowCreationDate" = "Mostrar data de criação do chat";
"Settings.ShowCreationDate.Notice" = "A data de criação pode ser desconhecida para alguns chats.";
"Settings.ShowRegDate" = "Mostrar data de registro";
"Settings.ShowRegDate.Notice" = "A data de registo é aproximada.";
"Settings.SendWithReturnKey" = "Enviar com a tecla \"retorno\"";
"Settings.HidePhoneInSettingsUI" = "Ocultar telefone nas configurações";
"Settings.HidePhoneInSettingsUI.Notice" = "Seu número ficará oculto apenas na interface do usuário. Para ocultá-lo de outras pessoas, use as configurações de privacidade.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Se ausente por 5 segundos";
"ProxySettings.UseSystemDNS" = "Usar DNS do sistema";
"ProxySettings.UseSystemDNS.Notice" = "Use o DNS do sistema para evitar tempo limite se você não tiver acesso ao DNS do Google";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Você **não precisa** de %@!";
"Common.RestartRequired" = "Reinício necessário";
"Common.RestartNow" = "Reiniciar agora";
"Common.OpenTelegram" = "Abrir Telegram";
"Common.UseTelegramForPremium" = "Observe que para obter o Telegram Premium, você precisa usar o aplicativo oficial do Telegram. Depois de obter o Telegram Premium, todos os seus recursos ficarão disponíveis no Swiftgram.";
"Message.HoldToShowOrReport" = "Segure para Mostrar ou Denunciar.";
"Auth.AccountBackupReminder" = "Certifique-se de ter um método de acesso de backup. Mantenha um SIM para SMS ou uma sessão adicional logada para evitar ser bloqueado.";
"Auth.UnofficialAppCodeTitle" = "Você só pode obter o código com o aplicativo oficial";
"Settings.SmallReactions" = "Pequenas reações";
"Settings.HideReactions" = "Esconder Reações";
"ContextMenu.SaveToCloud" = "Salvar na Nuvem";
"ContextMenu.SelectFromUser" = "Selecionar do Autor";
"Settings.ContextMenu" = "MENU DE CONTEXTO";
"Settings.ContextMenu.Notice" = "Entradas desativadas estarão disponíveis no sub-menu 'Swiftgram'.";
"Settings.ChatSwipeOptions" = "Opções de deslizar Lista de Chat";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Puxe para o próximo canal não lido";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Arraste para o Próximo Tópico";
"Settings.GalleryCamera" = "Câmera na Galeria";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Botão \"%@\"";
"Settings.SnapDeletionEffect" = "Efeitos de exclusão de mensagens";
"Settings.Stickers.Size" = "TAMANHO";
"Settings.Stickers.Timestamp" = "Mostrar Data/Hora";
"Settings.RecordingButton" = "Botão de gravação de voz";
"Settings.DefaultEmojisFirst" = "Priorizar emojis padrão";
"Settings.DefaultEmojisFirst.Notice" = "Mostrar emojis padrão antes dos premium no teclado de emojis";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "criado: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Entrou em %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrado";
"Settings.messageDoubleTapActionOutgoingEdit" = "Toque duplo para editar mensagem";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Setări Conținut";
"Settings.Tabs.Header" = "FERESTRE";
"Settings.Tabs.HideTabBar" = "Ascunde bara de filă";
"Settings.Tabs.ShowContacts" = "Vizualizare contacte";
"Settings.Tabs.ShowNames" = "Arată Fereastra cu Numele";
"Settings.Folders.BottomTab" = "Dosare de jos";
"Settings.Folders.BottomTabStyle" = "Stil directoare de jos";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegramă";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Ascundeți „%@\"";
"Settings.Folders.RememberLast" = "Deschideți ultimul dosar";
"Settings.Folders.RememberLast.Notice" = "Swiftgram va deschide ultimul folder utilizat atunci când reporniți aplicația sau schimbați conturile.";
"Settings.Folders.CompactNames" = "Spațiere mai mică";
"Settings.Folders.AllChatsTitle" = "Titlul \"Toate conversațiile\"";
"Settings.Folders.AllChatsTitle.short" = "Scurt";
"Settings.Folders.AllChatsTitle.long" = "Lungă";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Implicit";
"Settings.ChatList.Header" = "LISTA CHAT";
"Settings.CompactChatList" = "Lista compactă de Chat";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Ascunde povestiri";
"Settings.Stories.WarnBeforeView" = "Întreabă înainte de vizualizare";
"Settings.Stories.DisableSwipeToRecord" = "Dezactivează glisarea pentru înregistrare";
"Settings.Translation.QuickTranslateButton" = "Butonul Traducere Rapidă";
"Stories.Warning.Author" = "Autor";
"Stories.Warning.ViewStory" = "Vezi povestirea?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ VOR FI ACĂ SĂ VEDEȚI că le-ați văzut povestea lor.";
"Stories.Warning.NoticeStealth" = "%@ nu va putea vedea povestea lor.";
"Settings.Photo.Quality.Notice" = "Calitatea fotografiilor și povestirilor încărcate.";
"Settings.Photo.SendLarge" = "Trimite fotografii mari";
"Settings.Photo.SendLarge.Notice" = "Crește limita laterală a imaginilor comprimate la 2560px.";
"Settings.VideoNotes.Header" = "VIDEO ROTUND";
"Settings.VideoNotes.StartWithRearCam" = "Începe cu camera posterioară";
"Settings.CustomColors.Header" = "COLORTURI DE CONT";
"Settings.CustomColors.Saturation" = "SATURARE";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Setați la 0%% pentru a dezactiva culorile contului.";
"Settings.UploadsBoost" = "Accelerare Încărcare";
"Settings.DownloadsBoost" = "Impuls descărcare";
"Settings.DownloadsBoost.none" = "Dezactivat";
"Settings.DownloadsBoost.medium" = "Medie";
"Settings.DownloadsBoost.maximum" = "Maxim";
"Settings.ShowProfileID" = "Arată ID-ul profilului";
"Settings.ShowDC" = "Arată Centrul de date";
"Settings.ShowCreationDate" = "Arată data creării chat-ului";
"Settings.ShowCreationDate.Notice" = "Data creării poate fi necunoscută pentru unele conversații.";
"Settings.ShowRegDate" = "Arată data înregistrării";
"Settings.ShowRegDate.Notice" = "Data înregistrării este aproximativă.";
"Settings.SendWithReturnKey" = "Trimite cu cheia \"Returnare\"";
"Settings.HidePhoneInSettingsUI" = "Ascunde telefonul din setări";
"Settings.HidePhoneInSettingsUI.Notice" = "Acest lucru va ascunde numărul de telefon din interfața de setări. Pentru a-l ascunde de alții, mergi la confidențialitate și securitate.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Dacă este plecat timp de 5 secunde";
"ProxySettings.UseSystemDNS" = "Utilizați DNS sistem";
"ProxySettings.UseSystemDNS.Notice" = "Utilizați DNS pentru a ocoli timeout-ul dacă nu aveți acces la Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Nu ai nevoie de ** %@!";
"Common.RestartRequired" = "Repornire necesară";
"Common.RestartNow" = "Repornește acum";
"Common.OpenTelegram" = "Deschide telegrama";
"Common.UseTelegramForPremium" = "Vă rugăm să reţineţi că, pentru a obţine Telegram Premium, trebuie să utilizaţi aplicaţia oficială Telegram. Odată ce ai obţinut Telegram Premium, toate caracteristicile sale vor deveni disponibile în Swiftgram.";
"Message.HoldToShowOrReport" = "Țineți apăsat pentru a afișa sau raporta.";
"Auth.AccountBackupReminder" = "Asigurați-vă că aveți o metodă de acces de rezervă. Păstrați un SIM pentru SMS sau o sesiune adițională conectată pentru a evita blocarea.";
"Auth.UnofficialAppCodeTitle" = "Poți obține codul doar cu aplicația oficială";
"Settings.SmallReactions" = "Reacţii mici";
"Settings.HideReactions" = "Ascunde Reacțiile";
"ContextMenu.SaveToCloud" = "Salvează în Cloud";
"ContextMenu.SelectFromUser" = "Selectați din autor";
"Settings.ContextMenu" = "MENIU CONTEXTUAL";
"Settings.ContextMenu.Notice" = "Intrările dezactivate vor fi disponibile în submeniul 'Swiftgram'.";
"Settings.ChatSwipeOptions" = "Opțiuni de glisare a chatului";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Trageţi pentru următorul canal necitit";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Trageți către Următorul Subiect";
"Settings.GalleryCamera" = "Cameră foto în Galerie";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Butonul \"%@\"";
"Settings.SnapDeletionEffect" = "Efecte ștergere mesaj";
"Settings.Stickers.Size" = "MISIUNE";
"Settings.Stickers.Timestamp" = "Arată Ora";
"Settings.RecordingButton" = "Butonul Înregistrare Voce";
"Settings.DefaultEmojisFirst" = "Prioritize emoticoanele standard";
"Settings.DefaultEmojisFirst.Notice" = "Afișați emoticoanele standard înainte de cele premium în tastatura emoji";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "creat: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "S-a alăturat %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Înregistrat";
"Settings.messageDoubleTapActionOutgoingEdit" = "Apăsați de două ori pentru a edita mesajul";

View File

@ -0,0 +1,134 @@
"Settings.ContentSettings" = "Настройки контента";
"Settings.Tabs.Header" = "ВКЛАДКИ";
"Settings.Tabs.HideTabBar" = "Скрыть панель вкладок";
"Settings.Tabs.ShowContacts" = "Вкладка «Контакты»";
"Settings.Tabs.ShowNames" = "Имена вкладок";
"Settings.Folders.BottomTab" = "Папки снизу";
"Settings.Folders.BottomTabStyle" = "Стиль папок внизу";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Скрыть \"%@\"";
"Settings.Folders.RememberLast" = "Открывать последнюю папку";
"Settings.Folders.RememberLast.Notice" = "Swiftgram откроет последнюю использованную папку после перезапуска или переключения учетной записи";
"Settings.Folders.CompactNames" = "Уменьшенные расстояния";
"Settings.Folders.AllChatsTitle" = "Название \"Все чаты\"";
"Settings.Folders.AllChatsTitle.short" = "Короткое";
"Settings.Folders.AllChatsTitle.long" = "Длинное";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "По умолчанию";
"Settings.ChatList.Header" = "СПИСОК ЧАТОВ";
"Settings.CompactChatList" = "Компактный список чатов";
"Settings.Profiles.Header" = "ПРОФИЛИ";
"Settings.Stories.Hide" = "Скрыть истории";
"Settings.Stories.WarnBeforeView" = "Спросить перед просмотром";
"Settings.Stories.DisableSwipeToRecord" = "Отключить свайп для записи";
"Settings.Translation.QuickTranslateButton" = "Кнопка быстрого перевода";
"Stories.Warning.Author" = "Автор";
"Stories.Warning.ViewStory" = "Просмотреть историю?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ СМОЖЕТ УВИДЕТЬ, что вы просмотрели историю.";
"Stories.Warning.NoticeStealth" = "%@ не сможет увидеть, что вы просмотрели историю.";
"Settings.Photo.Quality.Notice" = "Качество исходящих фото и фото-историй";
"Settings.Photo.SendLarge" = "Отправлять большие фото";
"Settings.Photo.SendLarge.Notice" = "Увеличить лимит сторон для сжатых фото до 2560пкс";
"Settings.VideoNotes.Header" = "КРУГЛЫЕ ВИДЕО";
"Settings.VideoNotes.StartWithRearCam" = "На заднюю камеру";
"Settings.CustomColors.Header" = "ПЕРСОНАЛЬНЫЕ ЦВЕТА";
"Settings.CustomColors.Saturation" = "НАСЫЩЕННОСТЬ";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Установите насыщенность на 0%%, чтобы отключить персональные цвета";
"Settings.UploadsBoost" = "Ускорение загрузки";
"Settings.DownloadsBoost" = "Ускорение скачивания";
"Settings.DownloadsBoost.none" = "Выключено";
"Settings.DownloadsBoost.medium" = "Средне";
"Settings.DownloadsBoost.maximum" = "Максимум";
"Settings.ShowProfileID" = "ID профилей";
"Settings.ShowDC" = "Показать дата-центр (DC)";
"Settings.ShowCreationDate" = "Показать дату создания чата";
"Settings.ShowCreationDate.Notice" = "Дата создания может быть неизвестна для некоторых чатов.";
"Settings.ShowRegDate" = "Показать дату регистрации";
"Settings.ShowRegDate.Notice" = "Дата регистрации приблизительная.";
"Settings.SendWithReturnKey" = "Отправка кнопкой \"Ввод\"";
"Settings.HidePhoneInSettingsUI" = "Скрыть номер";
"Settings.HidePhoneInSettingsUI.Notice" = "Ваш номер будет скрыт только в интерфейсе настроек. Используйте настройки Конфиденциальности, чтобы скрыть его от других.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Через 5 секунд";
"ProxySettings.UseSystemDNS" = "Системный DNS";
"ProxySettings.UseSystemDNS.Notice" = "Используйте системный DNS, чтобы избежать задержки, если у вас нет доступа к DNS Google";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Вам **не нужен** %@!";
"Common.RestartRequired" = "Необходим перезапуск";
"Common.RestartNow" = "Перезапустить Сейчас";
"Common.OpenTelegram" = "Открыть Telegram";
"Common.UseTelegramForPremium" = "Обратите внимание, что для получения Telegram Premium, вы должны использовать официальное приложение Telegram. Как только вы получите Telegram Premium, все его функции станут доступны в Swiftgram.";
"Message.HoldToShowOrReport" = "Удерживайте для Показа или Жалобы.";
"Auth.AccountBackupReminder" = "Убедитесь, что у вас есть запасной вариант входа: Активная SIM-карта или дополнительная сессия, чтобы не потерять доступ к аккаунту.";
"Auth.UnofficialAppCodeTitle" = "Вы можете получить код только в официальном приложении";
"Settings.SmallReactions" = "Маленькие реакции";
"Settings.HideReactions" = "Скрыть реакции";
"ContextMenu.SaveToCloud" = "Сохранить в Избранное";
"ContextMenu.SelectFromUser" = "Выбрать от Автора";
"Settings.ContextMenu" = "КОНТЕКСТНОЕ МЕНЮ";
"Settings.ContextMenu.Notice" = "Выключенные пункты будут доступны в подменю «Swiftgram».";
"Settings.ChatSwipeOptions" = "Опции чатов при свайпе";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Потянуть для перехода в канал";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Потянуть для перехода к след. теме";
"Settings.GalleryCamera" = "Камера в галерее";
/* "Send Message As..." button */
"Settings.SendAsButton" = "Кнопка \"%@\"";
"Settings.SnapDeletionEffect" = "Эффекты удаления сообщений";
"Settings.Stickers.Size" = "РАЗМЕР";
"Settings.Stickers.Timestamp" = "Показывать время";
"Settings.RecordingButton" = "Кнопка записи голоса";
"Settings.DefaultEmojisFirst" = "Приоритизировать стандартные эмодзи";
"Settings.DefaultEmojisFirst.Notice" = "Показывать стандартные эмодзи перед Premium в эмодзи-клавиатуре";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "создан: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Присоединился к %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Дата регистрации";
"Settings.messageDoubleTapActionOutgoingEdit" = "Редактирование двойным тапом";
"Settings.wideChannelPosts" = "Широкие посты в каналах";
"Settings.ForceEmojiTab" = "Клавиатура с эмодзи по умолчанию";
"Settings.forceBuiltInMic" = "Всегда использовать микрофон устройства";
"Settings.forceBuiltInMic.Notice" = "Если включено, то приложение будет использовать только встроенный микрофон устройства, даже если подключены наушники.";

View File

@ -0,0 +1,2 @@
"Settings.Tabs.Header" = "පටිති";
"ContextMenu.SaveToCloud" = "මේඝයට සුරකින්න";

View File

@ -0,0 +1,4 @@
"Settings.Tabs.Header" = "ZÁLOŽKY";
"Settings.Tabs.ShowContacts" = "Zobraziť kontakty";
"Settings.Tabs.ShowNames" = "Zobraziť názvy záložiek";
"ContextMenu.SaveToCloud" = "Uložiť na Cloud";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Подешавања садржаја";
"Settings.Tabs.Header" = "ТАБОВИ";
"Settings.Tabs.HideTabBar" = "Сакриј Таб бар";
"Settings.Tabs.ShowContacts" = "Прикажи таб Контакти";
"Settings.Tabs.ShowNames" = "Прикажи имена табова";
"Settings.Folders.BottomTab" = "Фасцикле у дну";
"Settings.Folders.BottomTabStyle" = "Стил фасцикли у дну";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Телеграм";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Сакриј \"%@\"";
"Settings.Folders.RememberLast" = "Отвори последњу фасциклу";
"Settings.Folders.RememberLast.Notice" = "Свифтграм ће отворити последње коришћену фасциклу када поново покренете апликацију или измените налоге.";
"Settings.Folders.CompactNames" = "Мањи размак";
"Settings.Folders.AllChatsTitle" = "Наслов \"Сви Четови\"";
"Settings.Folders.AllChatsTitle.short" = "Кратко";
"Settings.Folders.AllChatsTitle.long" = "Дуго";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Подразумевано";
"Settings.ChatList.Header" = "ЛИСТА ЧЕТОВА";
"Settings.CompactChatList" = "Компактна листа чета";
"Settings.Profiles.Header" = "ПРОФИЛИ";
"Settings.Stories.Hide" = "Сакриј приче";
"Settings.Stories.WarnBeforeView" = "Питај пре прегледања";
"Settings.Stories.DisableSwipeToRecord" = "Онемогући превлачење за снимање";
"Settings.Translation.QuickTranslateButton" = "Дугме за брзо превођење";
"Stories.Warning.Author" = "Аутор";
"Stories.Warning.ViewStory" = "Погледај причу?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ ЋЕ ВИДЕТИ да сте видели њихову причу.";
"Stories.Warning.NoticeStealth" = "%@ неће моћи видети да сте видели њихову причу.";
"Settings.Photo.Quality.Notice" = "Квалитет постављених фотографија и приказа.";
"Settings.Photo.SendLarge" = "Пошаљи велике фотографије";
"Settings.Photo.SendLarge.Notice" = "Повећај лимит величине за компресоване слике на 2560пкс.";
"Settings.VideoNotes.Header" = "КРУГ ВИДЕО";
"Settings.VideoNotes.StartWithRearCam" = "Почни са задњом камером";
"Settings.CustomColors.Header" = "БОЈЕ НАЛОГА";
"Settings.CustomColors.Saturation" = "ЗАСИЋЕЊЕ";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Поставите на 0%% да онемогућите боје налога.";
"Settings.UploadsBoost" = "Појачај поставке поставки";
"Settings.DownloadsBoost" = "Преузми појачање";
"Settings.DownloadsBoost.none" = "Онемогућено";
"Settings.DownloadsBoost.medium" = "Средње";
"Settings.DownloadsBoost.maximum" = "Максимално";
"Settings.ShowProfileID" = "Прикажи идентификациони број профила";
"Settings.ShowDC" = "Прикажи центар података";
"Settings.ShowCreationDate" = "Прикажи датум креирања чата";
"Settings.ShowCreationDate.Notice" = "Можда није познат датум креирања за неке разговоре.";
"Settings.ShowRegDate" = "Прикажи датум регистрације";
"Settings.ShowRegDate.Notice" = "Датум регистрације је приближан.";
"Settings.SendWithReturnKey" = "Пошаљи са 'повратак' тастером";
"Settings.HidePhoneInSettingsUI" = "Сакриј телефон у поставкама";
"Settings.HidePhoneInSettingsUI.Notice" = "Ово само ће скрити ваш број телефона из интерфејса поставки. Да бисте га скрили од других, идите на Приватност и безбедност.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Ако је одсутан 5 секунди";
"ProxySettings.UseSystemDNS" = "Користи системски DNS";
"ProxySettings.UseSystemDNS.Notice" = "Користи системски DNS да заобиђеш временски лимит ако немаш приступ Google DNS-у";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Не треба вам **%@**!";
"Common.RestartRequired" = "Потребно поновно покретање";
"Common.RestartNow" = "Поново покрени сада";
"Common.OpenTelegram" = "Отвори Телеграм";
"Common.UseTelegramForPremium" = "Обратите пажњу да бисте добили Телеграм Премијум, морате користити официјалну Телеграм апликацију. Након што стечете Телеграм Премијум, све његове функције ће бити доступне у Свифтграму.";
"Message.HoldToShowOrReport" = "Држи да би показао или пријавио.";
"Auth.AccountBackupReminder" = "Обезбеди да имаш методу приступа за резерву. Задржи СИМ за СМС или додатну сесију пријављену да избегнеш блокирање.";
"Auth.UnofficialAppCodeTitle" = "Код можете добити само са званичном апликацијом";
"Settings.SmallReactions" = "Мале реакције";
"Settings.HideReactions" = "Сакриј реакције";
"ContextMenu.SaveToCloud" = "Сачувај у облак";
"ContextMenu.SelectFromUser" = "Изабери од аутора";
"Settings.ContextMenu" = "КОНТЕКСТ МЕНИ";
"Settings.ContextMenu.Notice" = "Онемогућени уноси ће бити доступни у 'Swiftgram' подменују.";
"Settings.ChatSwipeOptions" = "Опције превлачења списка разговора";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Повуци на следећи непрочитан канал";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Повуци на следећу тему";
"Settings.GalleryCamera" = "Камера у галерији";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Дугме";
"Settings.SnapDeletionEffect" = "Ефекти брисања поруке";
"Settings.Stickers.Size" = "ВЕЛИЧИНА";
"Settings.Stickers.Timestamp" = "Прикажи временски линку";
"Settings.RecordingButton" = "Дугме за гласовно снимање";
"Settings.DefaultEmojisFirst" = "Приоритизовати стандардне емотиконе";
"Settings.DefaultEmojisFirst.Notice" = "Прикажи стандардне емотиконе пре премијумских на тастатури емотикона";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "креирано: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Придружен: %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Регистрован";
"Settings.messageDoubleTapActionOutgoingEdit" = "Двоструки додир за уређивање поруке";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "Innehållsinställningar";
"Settings.Tabs.Header" = "Flikar";
"Settings.Tabs.HideTabBar" = "Dölj flikfält";
"Settings.Tabs.ShowContacts" = "Visa Kontakter-flik";
"Settings.Tabs.ShowNames" = "Show Tab Names";
"Settings.Folders.BottomTab" = "Mappar längst ner";
"Settings.Folders.BottomTabStyle" = "Stil på nedre mappar";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "Dölj \"%@\"";
"Settings.Folders.RememberLast" = "Öppna senaste mapp";
"Settings.Folders.RememberLast.Notice" = "Swiftgram öppnar den senast använda mappen när du startar om appen eller byter konton.";
"Settings.Folders.CompactNames" = "Mindre avstånd";
"Settings.Folders.AllChatsTitle" = "\"Alla chattar\" titel";
"Settings.Folders.AllChatsTitle.short" = "Kort";
"Settings.Folders.AllChatsTitle.long" = "Lång";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Standard";
"Settings.ChatList.Header" = "CHATT LISTA";
"Settings.CompactChatList" = "Kompakt chattlista";
"Settings.Profiles.Header" = "PROFILES";
"Settings.Stories.Hide" = "Dölj Berättelser";
"Settings.Stories.WarnBeforeView" = "Fråga innan du tittar";
"Settings.Stories.DisableSwipeToRecord" = "Inaktivera svep för att spela in";
"Settings.Translation.QuickTranslateButton" = "Snabböversättningsknapp";
"Stories.Warning.Author" = "Författare";
"Stories.Warning.ViewStory" = "Visa Berättelse?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@ KOMMER ATT SE att du har sett deras Berättelse.";
"Stories.Warning.NoticeStealth" = "%@ kommer inte att se att du har sett deras Berättelse.";
"Settings.Photo.Quality.Notice" = "Kvaliteten på uppladdade bilder och berättelser.";
"Settings.Photo.SendLarge" = "Skicka stora foton";
"Settings.Photo.SendLarge.Notice" = "Öka sidogränsen för komprimerade bilder till 2560px.";
"Settings.VideoNotes.Header" = "RUND VIDEO";
"Settings.VideoNotes.StartWithRearCam" = "Börja med bakre kamera";
"Settings.CustomColors.Header" = "KONTOFÄRGER";
"Settings.CustomColors.Saturation" = "MÄTTNING";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Sätt till 0%% för att inaktivera kontofärger.";
"Settings.UploadsBoost" = "Uppladdningshastighet";
"Settings.DownloadsBoost" = "Ladda ner Boost";
"Settings.DownloadsBoost.none" = "Inaktiverad";
"Settings.DownloadsBoost.medium" = "Medium";
"Settings.DownloadsBoost.maximum" = "Maximal";
"Settings.ShowProfileID" = "Visa profil-ID";
"Settings.ShowDC" = "Visa datacenter";
"Settings.ShowCreationDate" = "Visa datum för att skapa chatt";
"Settings.ShowCreationDate.Notice" = "Skapandedatumet kan vara okänt för vissa chattar.";
"Settings.ShowRegDate" = "Visa registreringsdatum";
"Settings.ShowRegDate.Notice" = "Registreringsdatumet är ungefärligt.";
"Settings.SendWithReturnKey" = "Skicka med 'retur'-tangenten";
"Settings.HidePhoneInSettingsUI" = "Dölj telefon i inställningar";
"Settings.HidePhoneInSettingsUI.Notice" = "Detta döljer endast ditt telefonnummer från inställningsgränssnittet. För att dölja det från andra, gå till Sekretess och säkerhet.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "Om borta i 5 sekunder";
"ProxySettings.UseSystemDNS" = "Använd system-DNS";
"ProxySettings.UseSystemDNS.Notice" = "Använd system-DNS för att kringgå timeout om du inte har tillgång till Google DNS";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "Du **behöver inte** %@!";
"Common.RestartRequired" = "Omstart krävs";
"Common.RestartNow" = "Starta om Nu";
"Common.OpenTelegram" = "Öppna Telegram";
"Common.UseTelegramForPremium" = "Observera att för att få Telegram Premium måste du använda den officiella Telegram-appen. När du har fått Telegram Premium, kommer alla dess funktioner att bli tillgängliga i Swiftgram.";
"Message.HoldToShowOrReport" = "Håll in för att Visa eller Rapportera.";
"Auth.AccountBackupReminder" = "Se till att du har en backup-åtkomstmetod. Behåll ett SIM för SMS eller en extra session inloggad för att undvika att bli utelåst.";
"Auth.UnofficialAppCodeTitle" = "Du kan endast få koden med den officiella appen";
"Settings.SmallReactions" = "Små reaktioner";
"Settings.HideReactions" = "Dölj Reaktioner";
"ContextMenu.SaveToCloud" = "Spara till Molnet";
"ContextMenu.SelectFromUser" = "Välj från Författaren";
"Settings.ContextMenu" = "KONTEXTMENY";
"Settings.ContextMenu.Notice" = "Inaktiverade poster kommer att vara tillgängliga i 'Swiftgram'-undermenyn.";
"Settings.ChatSwipeOptions" = "Svepalternativ för chattlistan";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Dra till nästa olästa kanal";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Dra till Nästa Ämne";
"Settings.GalleryCamera" = "Kamera i galleriet";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" Knapp";
"Settings.SnapDeletionEffect" = "Effekter på meddelandet";
"Settings.Stickers.Size" = "SIZE";
"Settings.Stickers.Timestamp" = "Visa tidsstämpel";
"Settings.RecordingButton" = "Röstinspelningsknapp";
"Settings.DefaultEmojisFirst" = "Prioritera standardemojis";
"Settings.DefaultEmojisFirst.Notice" = "Visa standardemojis innan premium i emoji-tangentbordet";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "skapad: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Gick med %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Registrerad";
"Settings.messageDoubleTapActionOutgoingEdit" = "Dubbeltryck för att redigera meddelandet";

View File

@ -0,0 +1,128 @@
"Settings.ContentSettings" = "İçerik Ayarları";
"Settings.Tabs.Header" = "SEKMELER";
"Settings.Tabs.HideTabBar" = "Sekme çubuğunu gizle";
"Settings.Tabs.ShowContacts" = "Kişiler Sekmesini Göster";
"Settings.Tabs.ShowNames" = "Sekme isimlerini göster";
"Settings.Folders.BottomTab" = "Altta klasörler";
"Settings.Folders.BottomTabStyle" = "Alt klasör stili";
/* Do not translate */
"Settings.Folders.BottomTabStyle.ios" = "iOS";
/* Do not translate */
"Settings.Folders.BottomTabStyle.telegram" = "Telegram";
/* Example: Hide "All Chats" */
"Settings.Folders.AllChatsHidden" = "\"%@\" Gizle";
"Settings.Folders.RememberLast" = "Son klasörü aç";
"Settings.Folders.RememberLast.Notice" = "Swiftgram, yeniden başlatıldıktan ya da hesap değişiminden sonra son kullanılan klasörü açacaktır";
"Settings.Folders.CompactNames" = "Daha küçük aralık";
"Settings.Folders.AllChatsTitle" = "\"Tüm Sohbetler\" başlığı";
"Settings.Folders.AllChatsTitle.short" = "Kısa";
"Settings.Folders.AllChatsTitle.long" = "Uzun";
/* Default behaviour for All Chats Folder Title. "All Chats" title: Default */
"Settings.Folders.AllChatsTitle.none" = "Varsayılan";
"Settings.ChatList.Header" = "SOHBET LİSTESİ";
"Settings.CompactChatList" = "Kompakt Sohbet Listesi";
"Settings.Profiles.Header" = "PROFİLLER";
"Settings.Stories.Hide" = "Hikayeleri Gizle";
"Settings.Stories.WarnBeforeView" = "Görüntülemeden önce sor";
"Settings.Stories.DisableSwipeToRecord" = "Kaydetmek için kaydırmayı devre dışı bırak";
"Settings.Translation.QuickTranslateButton" = "Hızlı Çeviri butonu";
"Stories.Warning.Author" = "Yazar";
"Stories.Warning.ViewStory" = "Hikayeyi Görüntüle?";
/* Author will be able to see that you viewed their Story */
"Stories.Warning.Notice" = "%@, Hikayesini görüntülediğinizi GÖREBİLECEK.";
"Stories.Warning.NoticeStealth" = "%@, hikayesini görüntülediğinizi göremeyecek.";
"Settings.Photo.Quality.Notice" = "Gönderilen fotoğrafların ve foto-hikayelerin kalitesi";
"Settings.Photo.SendLarge" = "Büyük fotoğraflar gönder";
"Settings.Photo.SendLarge.Notice" = "Sıkıştırılmış resimlerdeki kenar sınırını 2560 piksele çıkar";
"Settings.VideoNotes.Header" = "YUVARLAK VİDEOLAR";
"Settings.VideoNotes.StartWithRearCam" = "Arka kamerayla başlat";
"Settings.CustomColors.Header" = "HESAP RENKLERİ";
"Settings.CustomColors.Saturation" = "DOYUM";
/* Make sure to escape Percentage sign % */
"Settings.CustomColors.Saturation.Notice" = "Hesap renklerini devre dışı bırakmak için doyumu 0%%'a ayarlayın";
"Settings.UploadsBoost" = "Karşıya yüklemeleri hızlandır";
"Settings.DownloadsBoost" = "İndirmeleri hızlandır";
"Settings.DownloadsBoost.none" = "Devre dışı";
"Settings.DownloadsBoost.medium" = "Orta";
"Settings.DownloadsBoost.maximum" = "En fazla";
"Settings.ShowProfileID" = "Profil ID'sini Göster";
"Settings.ShowDC" = "Veri Merkezini Göster";
"Settings.ShowCreationDate" = "Sohbet Oluşturma Tarihini Göster";
"Settings.ShowCreationDate.Notice" = "Bazı sohbetler için oluşturma tarihi bilinmeyebilir.";
"Settings.ShowRegDate" = "Kaydolma Tarihini Göster";
"Settings.ShowRegDate.Notice" = "Kaydolma tarihi yaklaşık olarak belirtilmiştir.";
"Settings.SendWithReturnKey" = "\"enter\" tuşu ile gönder";
"Settings.HidePhoneInSettingsUI" = "Ayarlarda numarayı gizle";
"Settings.HidePhoneInSettingsUI.Notice" = "Numaranız sadece arayüzde gizlenecek. Diğerlerinden gizlemek için, lütfen Gizlilik ayarlarını kullanın.";
"PasscodeSettings.AutoLock.InFiveSeconds" = "5 saniye uzakta kalırsanız";
"ProxySettings.UseSystemDNS" = "Sistem DNS'sini kullan";
"ProxySettings.UseSystemDNS.Notice" = "Google DNS'ye erişiminiz yoksa, zaman aşımını aşmak için sistem DNS'sini kullanın";
/* Preserve markdown asterisks! Example: You **don't** need Telegram Premium! */
"Common.NoTelegramPremiumNeeded" = "%@ **gerekmez**!";
"Common.RestartRequired" = "Yeniden başlatma gerekli";
"Common.RestartNow" = "Şimdi Yeniden Başlat";
"Common.OpenTelegram" = "Telegram'ı Aç";
"Common.UseTelegramForPremium" = "Unutmayın ki Telegram Premium'u edinmek için resmî Telegram uygulamasını kullanmanız gerekmektedir. Telegram Premium sahibi olduktan sonra onun tüm özellikleri Swiftgram'da mevcut olacaktır.";
"Message.HoldToShowOrReport" = "Göstermek veya Bildirmek için Basılı Tutun.";
"Auth.AccountBackupReminder" = "Yedek erişim yönteminiz olduğundan emin olun. Kilitlenmeden kaçınmak için bir SIM kartı saklayın veya ek bir oturum açın.";
"Auth.UnofficialAppCodeTitle" = "Kodu yalnızca resmi uygulamadan edinebilirsiniz";
"Settings.SmallReactions" = "Küçük tepkiler";
"Settings.HideReactions" = "Tepkileri Gizle";
"ContextMenu.SaveToCloud" = "Buluta Kaydet";
"ContextMenu.SelectFromUser" = "Yazardan Seç";
"Settings.ContextMenu" = "BAĞLAM MENÜSÜ";
"Settings.ContextMenu.Notice" = "Devre dışı bırakılmış girişler \"Swiftgram\" alt menüsünde mevcut olacaktır.";
"Settings.ChatSwipeOptions" = "Sohbet listesi kaydırma seçenekleri";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextChannelSameLocationSwipeProgress */
"Settings.PullToNextChannel" = "Sonraki okunmamış kanal için çekin";
/* Re-word like this string on offical app https://translations.telegram.org/en/ios/groups_and_channels/Chat.NextUnreadTopicSwipeProgress */
"Settings.PullToNextTopic" = "Bir Sonraki Konuya Çek";
"Settings.GalleryCamera" = "Galeride kamera";
/* "Send Message As..." button */
"Settings.SendAsButton" = "\"%@\" butonu";
"Settings.SnapDeletionEffect" = "Mesaj silme efektleri";
"Settings.Stickers.Size" = "BOYUT";
"Settings.Stickers.Timestamp" = "Zaman Damgasını Göster";
"Settings.RecordingButton" = "Ses Kaydı Düğmesi";
"Settings.DefaultEmojisFirst" = "Standart emojileri önceliklendirin";
"Settings.DefaultEmojisFirst.Notice" = "Emoji klavyesinde premiumdan önce standart emojileri göster";
/* Date when chat was created. "created: 24 May 2016" */
"Chat.Created" = "oluşturuldu: %@";
/* Date when user joined the chat. "Joined Swiftgram Chat" */
"Chat.JoinedDateTitle" = "Katıldı: %@";
/* Date when user registered in Telegram. Will be shown like "Registered\n24 May 2016" */
"Chat.RegDate" = "Kayıtlı";
"Settings.messageDoubleTapActionOutgoingEdit" = "Mesajı düzenlemek için çift dokunun";

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