diff --git a/Cryptomator.xcodeproj/project.pbxproj b/Cryptomator.xcodeproj/project.pbxproj index 67b464602..e9cfa0612 100644 --- a/Cryptomator.xcodeproj/project.pbxproj +++ b/Cryptomator.xcodeproj/project.pbxproj @@ -3320,7 +3320,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.6.3; + MARKETING_VERSION = 2.6.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -3382,7 +3382,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 2.6.3; + MARKETING_VERSION = 2.6.4; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=200 -Xfrontend -warn-long-function-bodies=200"; diff --git a/Cryptomator/MainCoordinator.swift b/Cryptomator/MainCoordinator.swift index ee2bcace6..f7f5bf63a 100644 --- a/Cryptomator/MainCoordinator.swift +++ b/Cryptomator/MainCoordinator.swift @@ -8,6 +8,7 @@ import CryptomatorCommonCore import Promises +import StoreKit import UIKit class MainCoordinator: NSObject, Coordinator, UINavigationControllerDelegate { @@ -77,6 +78,15 @@ class MainCoordinator: NSObject, Coordinator, UINavigationControllerDelegate { rootViewController.showDetailViewController(detailNavigationController, sender: nil) } + // Temporarily added for December 2024 Sale + func showPurchase() { + let modalNavigationController = BaseNavigationController() + let child = PurchaseCoordinator(navigationController: modalNavigationController) + childCoordinators.append(child) + navigationController.topViewController?.present(modalNavigationController, animated: true) + child.start() + } + // MARK: - UINavigationControllerDelegate func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { @@ -114,6 +124,8 @@ extension MainCoordinator: StoreObserverDelegate { switch transaction { case .fullVersion, .yearlySubscription: showFullVersionAlert() + // Temporarily added for December 2024 Sale + NotificationCenter.default.post(name: .purchasedFullVersionNotification, object: nil) case let .freeTrial(expiresOn): showTrialAlert(expirationDate: expiresOn) case .unknown: @@ -126,7 +138,11 @@ extension MainCoordinator: StoreObserverDelegate { guard let navigationController = self?.navigationController else { return } - _ = PurchaseAlert.showForFullVersion(title: LocalizedString.getValue("purchase.unlockedFullVersion.title"), on: navigationController) + PurchaseAlert.showForFullVersion(title: LocalizedString.getValue("purchase.unlockedFullVersion.title"), on: navigationController).then { + if let windowScene = navigationController.view.window?.windowScene { + SKStoreReviewController.requestReview(in: windowScene) + } + } } } diff --git a/Cryptomator/Purchase/Cells/PurchaseCell.swift b/Cryptomator/Purchase/Cells/PurchaseCell.swift index 0e1548ce3..44b85bbb7 100644 --- a/Cryptomator/Purchase/Cells/PurchaseCell.swift +++ b/Cryptomator/Purchase/Cells/PurchaseCell.swift @@ -12,6 +12,7 @@ import UIKit struct PurchaseCellViewModel: Hashable { let productName: String + let productDetail: String? let price: String let purchaseDetail: String? let purchaseButtonViewModel = PurchaseButtonViewModel() @@ -36,6 +37,7 @@ class PurchaseCell: IAPCell { func configure(with viewModel: PurchaseCellViewModel) { productTitleLabel.text = viewModel.productName + productDetailLabel.text = viewModel.productDetail accessory.button.setTitle(viewModel.price, for: .normal) accessory.detailLabel.text = viewModel.purchaseDetail accessory.configure(with: viewModel.purchaseButtonViewModel) diff --git a/Cryptomator/Purchase/PurchaseCoordinator.swift b/Cryptomator/Purchase/PurchaseCoordinator.swift index 306abdf5d..7982d311b 100644 --- a/Cryptomator/Purchase/PurchaseCoordinator.swift +++ b/Cryptomator/Purchase/PurchaseCoordinator.swift @@ -49,8 +49,13 @@ class PurchaseCoordinator: Coordinator { func fullVersionPurchased() { PurchaseAlert.showForFullVersion(title: LocalizedString.getValue("purchase.unlockedFullVersion.title"), on: navigationController).then { + if let windowScene = self.navigationController.view.window?.windowScene { + SKStoreReviewController.requestReview(in: windowScene) + } self.unlockedPro() } + // Temporarily added for December 2024 Sale + NotificationCenter.default.post(name: .purchasedFullVersionNotification, object: nil) } func handleRestoreResult(_ result: RestoreTransactionsResult) { diff --git a/Cryptomator/Purchase/PurchaseViewModel.swift b/Cryptomator/Purchase/PurchaseViewModel.swift index 017200381..a84692187 100644 --- a/Cryptomator/Purchase/PurchaseViewModel.swift +++ b/Cryptomator/Purchase/PurchaseViewModel.swift @@ -33,6 +33,23 @@ class PurchaseViewModel: BaseIAPViewModel, ProductFetching { return LocalizedString.getValue("purchase.title") } + // Temporarily added for December 2024 Sale + override var infoText: NSAttributedString? { + let currentYear = Calendar.current.component(.year, from: Date()) + let currentMonth = Calendar.current.component(.month, from: Date()) + if currentYear == 2024 && currentMonth == 12 { + return NSAttributedString( + string: "*Note: The discount amount may vary by region.", + attributes: [ + .font: UIFont.preferredFont(forTextStyle: .footnote), + .foregroundColor: UIColor.secondaryLabel + ] + ) + } else { + return nil + } + } + private let cryptomatorSettings: CryptomatorSettings init(storeManager: IAPStore = StoreManager.shared, iapManager: IAPManager = StoreObserver.shared, cryptomatorSettings: CryptomatorSettings = CryptomatorUserDefaults.shared, minimumDisplayTime: TimeInterval = 1.0) { @@ -56,6 +73,7 @@ class PurchaseViewModel: BaseIAPViewModel, ProductFetching { cells.append(.trialCell(TrialCellViewModel(expirationDate: trialExpirationDate))) } else { cells.append(.purchaseCell(PurchaseCellViewModel(productName: LocalizedString.getValue("purchase.product.trial"), + productDetail: nil, price: LocalizedString.getValue("purchase.product.pricing.free"), purchaseDetail: LocalizedString.getValue("purchase.product.trial.duration"), productIdentifier: .thirtyDayTrial))) @@ -65,6 +83,7 @@ class PurchaseViewModel: BaseIAPViewModel, ProductFetching { private func addSubscriptionItem() { if let product = products[.yearlySubscription], let localizedPrice = product.localizedPrice { let viewModel = PurchaseCellViewModel(productName: LocalizedString.getValue("purchase.product.yearlySubscription"), + productDetail: nil, price: localizedPrice, purchaseDetail: LocalizedString.getValue("purchase.product.yearlySubscription.duration"), productIdentifier: .yearlySubscription) @@ -75,6 +94,7 @@ class PurchaseViewModel: BaseIAPViewModel, ProductFetching { private func addLifetimeLicenseItem() { if let product = products[.fullVersion], let localizedPrice = product.localizedPrice { let viewModel = PurchaseCellViewModel(productName: LocalizedString.getValue("purchase.product.lifetimeLicense"), + productDetail: "🎁 33%* off in December", price: localizedPrice, purchaseDetail: LocalizedString.getValue("purchase.product.lifetimeLicense.duration"), productIdentifier: .fullVersion) diff --git a/Cryptomator/Purchase/UpgradeViewModel.swift b/Cryptomator/Purchase/UpgradeViewModel.swift index f31614017..9bb43dc16 100644 --- a/Cryptomator/Purchase/UpgradeViewModel.swift +++ b/Cryptomator/Purchase/UpgradeViewModel.swift @@ -34,6 +34,7 @@ class UpgradeViewModel: BaseIAPViewModel, ProductFetching { func addFreeUpgradeItem() { guard products[.freeUpgrade] != nil else { return } let viewModel = PurchaseCellViewModel(productName: LocalizedString.getValue("purchase.product.freeUpgrade"), + productDetail: nil, price: LocalizedString.getValue("purchase.product.pricing.free"), purchaseDetail: nil, productIdentifier: .freeUpgrade) @@ -43,6 +44,7 @@ class UpgradeViewModel: BaseIAPViewModel, ProductFetching { func addPaidUpgradeItem() { if let product = products[.paidUpgrade], let localizedPrice = product.localizedPrice { let viewModel = PurchaseCellViewModel(productName: LocalizedString.getValue("purchase.product.donateAndUpgrade"), + productDetail: nil, price: localizedPrice, purchaseDetail: LocalizedString.getValue("purchase.product.lifetimeLicense.duration"), productIdentifier: .paidUpgrade) diff --git a/Cryptomator/VaultList/VaultListViewController.swift b/Cryptomator/VaultList/VaultListViewController.swift index 010251d14..e3fa0c0a4 100644 --- a/Cryptomator/VaultList/VaultListViewController.swift +++ b/Cryptomator/VaultList/VaultListViewController.swift @@ -17,8 +17,14 @@ class VaultListViewController: ListViewController { weak var coordinator: MainCoordinator? private let viewModel: VaultListViewModelProtocol - private var observer: NSObjectProtocol? + private var willEnterForegroundObserver: NSObjectProtocol? @Dependency(\.fullVersionChecker) private var fullVersionChecker + @Dependency(\.cryptomatorSettings) private var cryptomatorSettings + + #if !ALWAYS_PREMIUM + private var bannerView: UIView? + private var fullVersionPurchasedObserver: NSObjectProtocol? + #endif init(with viewModel: VaultListViewModelProtocol) { self.viewModel = viewModel @@ -44,11 +50,18 @@ class VaultListViewController: ListViewController { let addNewVaulButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewVault)) navigationItem.rightBarButtonItem = addNewVaulButton - observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [weak self] _ in + willEnterForegroundObserver = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [weak self] _ in self?.viewModel.refreshVaultLockStates().catch { error in DDLogError("Refresh vault lock states failed with error: \(error)") } } + + #if !ALWAYS_PREMIUM + fullVersionPurchasedObserver = NotificationCenter.default.addObserver(forName: .purchasedFullVersionNotification, object: nil, queue: .main) { [weak self] _ in + self?.dismissBanner() + } + checkAndShowBanner() + #endif } override func viewWillAppear(_ animated: Bool) { @@ -108,4 +121,94 @@ class VaultListViewController: ListViewController { coordinator?.showVaultDetail(for: vaultCellViewModel.vault) } } + + // MARK: - Discount Banner + + #if !ALWAYS_PREMIUM + private func checkAndShowBanner() { + let currentYear = Calendar.current.component(.year, from: Date()) + let currentMonth = Calendar.current.component(.month, from: Date()) + if currentYear == 2024, currentMonth == 12, !(cryptomatorSettings.fullVersionUnlocked || cryptomatorSettings.hasRunningSubscription), !cryptomatorSettings.december2024BannerDismissed { + showBanner() + } + } + + private func showBanner() { + let banner = UIView() + banner.backgroundColor = UIColor.cryptomatorPrimary + banner.translatesAutoresizingMaskIntoConstraints = false + banner.layer.cornerRadius = 12 + banner.layer.masksToBounds = true + + let emojiLabel = UILabel() + emojiLabel.text = "🎁" + emojiLabel.translatesAutoresizingMaskIntoConstraints = false + emojiLabel.setContentHuggingPriority(.required, for: .horizontal) + emojiLabel.setContentCompressionResistancePriority(.required, for: .horizontal) + + let textLabel = UILabel() + textLabel.text = "Lifetime License is 33%* off in December!" + textLabel.textColor = .white + textLabel.font = UIFont.preferredFont(forTextStyle: .footnote) + textLabel.adjustsFontSizeToFitWidth = true + textLabel.minimumScaleFactor = 0.5 + textLabel.numberOfLines = 2 + textLabel.translatesAutoresizingMaskIntoConstraints = false + + let dismissButton = UIButton(type: .close) + dismissButton.addTarget(self, action: #selector(dismissBanner), for: .touchUpInside) + dismissButton.translatesAutoresizingMaskIntoConstraints = false + dismissButton.setContentHuggingPriority(.required, for: .horizontal) + dismissButton.setContentCompressionResistancePriority(.required, for: .horizontal) + + banner.addSubview(emojiLabel) + banner.addSubview(textLabel) + banner.addSubview(dismissButton) + + NSLayoutConstraint.activate([ + emojiLabel.leadingAnchor.constraint(equalTo: banner.leadingAnchor, constant: 16), + emojiLabel.centerYAnchor.constraint(equalTo: banner.centerYAnchor), + + textLabel.leadingAnchor.constraint(equalTo: emojiLabel.trailingAnchor, constant: 8), + textLabel.centerYAnchor.constraint(equalTo: banner.centerYAnchor), + + dismissButton.leadingAnchor.constraint(equalTo: textLabel.trailingAnchor, constant: 8), + dismissButton.trailingAnchor.constraint(equalTo: banner.trailingAnchor, constant: -16), + dismissButton.centerYAnchor.constraint(equalTo: banner.centerYAnchor) + ]) + + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(bannerTapped)) + banner.addGestureRecognizer(tapGestureRecognizer) + + view.addSubview(banner) + + NSLayoutConstraint.activate([ + banner.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), + banner.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), + banner.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16), + banner.centerXAnchor.constraint(equalTo: view.centerXAnchor), + banner.heightAnchor.constraint(equalToConstant: 50) + ]) + + bannerView = banner + } + + @objc private func dismissBanner() { + UIView.animate(withDuration: 0.3, animations: { + self.bannerView?.alpha = 0 + }, completion: { _ in + self.bannerView?.removeFromSuperview() + self.bannerView = nil + }) + CryptomatorUserDefaults.shared.december2024BannerDismissed = true + } + + @objc private func bannerTapped() { + coordinator?.showPurchase() + } + #endif +} + +extension Notification.Name { + static let purchasedFullVersionNotification = Notification.Name("PurchasedFullVersionNotification") } diff --git a/CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorUserDefaults.swift b/CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorUserDefaults.swift index cb8b81081..27729b740 100644 --- a/CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorUserDefaults.swift +++ b/CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorUserDefaults.swift @@ -15,6 +15,9 @@ public protocol CryptomatorSettings { var trialExpirationDate: Date? { get set } var fullVersionUnlocked: Bool { get set } var hasRunningSubscription: Bool { get set } + #if !ALWAYS_PREMIUM + var december2024BannerDismissed: Bool { get set } + #endif } private enum CryptomatorSettingsKey: DependencyKey { @@ -108,4 +111,11 @@ extension CryptomatorUserDefaults: CryptomatorSettings { get { read() ?? false } set { write(value: newValue) } } + + #if !ALWAYS_PREMIUM + public var december2024BannerDismissed: Bool { + get { read() ?? false } + set { write(value: newValue) } + } + #endif } diff --git a/CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CryptomatorSettingsMock.swift b/CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CryptomatorSettingsMock.swift index 4d0d9d049..46b63600b 100644 --- a/CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CryptomatorSettingsMock.swift +++ b/CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CryptomatorSettingsMock.swift @@ -14,5 +14,8 @@ class CryptomatorSettingsMock: CryptomatorSettings { var debugModeEnabled: Bool = false var fullVersionUnlocked: Bool = false var hasRunningSubscription: Bool = false + #if !ALWAYS_PREMIUM + var december2024BannerDismissed: Bool = false + #endif } #endif diff --git a/CryptomatorTests/Purchase/PurchaseViewModelTests.swift b/CryptomatorTests/Purchase/PurchaseViewModelTests.swift index 7177aa911..d3e07bc8e 100644 --- a/CryptomatorTests/Purchase/PurchaseViewModelTests.swift +++ b/CryptomatorTests/Purchase/PurchaseViewModelTests.swift @@ -153,6 +153,7 @@ class PurchaseViewModelTests: IAPViewModelTestCase { private var purchaseTrialCell: Item { return .purchaseCell(.init(productName: LocalizedString.getValue("purchase.product.trial"), + productDetail: nil, price: LocalizedString.getValue("purchase.product.pricing.free"), purchaseDetail: LocalizedString.getValue("purchase.product.trial.duration"), productIdentifier: .thirtyDayTrial)) @@ -160,6 +161,7 @@ class PurchaseViewModelTests: IAPViewModelTestCase { private var yearlySubscriptionCell: Item { return .purchaseCell(.init(productName: LocalizedString.getValue("purchase.product.yearlySubscription"), + productDetail: nil, price: "$5.99", purchaseDetail: LocalizedString.getValue("purchase.product.yearlySubscription.duration"), productIdentifier: .yearlySubscription)) @@ -167,6 +169,7 @@ class PurchaseViewModelTests: IAPViewModelTestCase { private var lifetimeLicenseCell: Item { return .purchaseCell(.init(productName: LocalizedString.getValue("purchase.product.lifetimeLicense"), + productDetail: "🎁 33%* off in December", price: "$11.99", purchaseDetail: LocalizedString.getValue("purchase.product.lifetimeLicense.duration"), productIdentifier: .fullVersion)) diff --git a/CryptomatorTests/Purchase/UpgradeViewModelTests.swift b/CryptomatorTests/Purchase/UpgradeViewModelTests.swift index f791d737a..8f6323b18 100644 --- a/CryptomatorTests/Purchase/UpgradeViewModelTests.swift +++ b/CryptomatorTests/Purchase/UpgradeViewModelTests.swift @@ -77,6 +77,7 @@ class UpgradeViewModelTests: IAPViewModelTestCase { private var freeUpgradeCell: Item { return .purchaseCell(.init(productName: LocalizedString.getValue("purchase.product.freeUpgrade"), + productDetail: nil, price: LocalizedString.getValue("purchase.product.pricing.free"), purchaseDetail: nil, productIdentifier: .freeUpgrade)) @@ -84,6 +85,7 @@ class UpgradeViewModelTests: IAPViewModelTestCase { private var paidUpgradeCell: Item { return .purchaseCell(.init(productName: LocalizedString.getValue("purchase.product.donateAndUpgrade"), + productDetail: nil, price: "$1.99", purchaseDetail: LocalizedString.getValue("purchase.product.lifetimeLicense.duration"), productIdentifier: .paidUpgrade)) diff --git a/Gemfile.lock b/Gemfile.lock index b241c5328..72b627aba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,20 +10,20 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.974.0) - aws-sdk-core (3.205.0) + aws-partitions (1.1014.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.91.0) - aws-sdk-core (~> 3, >= 3.205.0) + aws-sdk-kms (1.96.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.162.0) - aws-sdk-core (~> 3, >= 3.205.0) + aws-sdk-s3 (1.174.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -38,8 +38,8 @@ GEM domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.111.0) - faraday (1.10.3) + excon (0.112.0) + faraday (1.10.4) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -65,10 +65,10 @@ GEM faraday-patron (1.0.0) faraday-rack (1.0.0) faraday-retry (1.0.3) - faraday_middleware (1.2.0) + faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.222.0) + fastlane (2.225.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -84,6 +84,7 @@ GEM faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) @@ -109,6 +110,8 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) @@ -151,17 +154,17 @@ GEM domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) - json (2.7.2) - jwt (2.8.2) + json (2.8.2) + jwt (2.9.3) base64 mini_magick (4.13.2) mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) - nanaimo (0.3.0) + nanaimo (0.4.0) naturally (2.2.1) nkf (0.2.0) - optparse (0.5.0) + optparse (0.6.0) os (1.1.4) plist (3.7.1) public_suffix (6.0.1) @@ -171,7 +174,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.7) + rexml (3.3.9) rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) @@ -184,6 +187,7 @@ GEM simctl (1.6.10) CFPropertyList naturally + sysrandom (1.0.5) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -193,15 +197,15 @@ GEM tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) word_wrap (1.0.0) - xcodeproj (1.25.0) + xcodeproj (1.27.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (>= 3.3.2, < 4.0) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) xcpretty (0.3.0) rouge (~> 2.0.7) xcpretty-travis-formatter (1.0.1) diff --git a/SharedResources/fi.lproj/Localizable.strings b/SharedResources/fi.lproj/Localizable.strings index b483434b9..0d35d69aa 100644 --- a/SharedResources/fi.lproj/Localizable.strings +++ b/SharedResources/fi.lproj/Localizable.strings @@ -1,14 +1,69 @@ +/* + Localizable.strings + Cryptomator + + Copyright © 2021 Skymatic GmbH. All rights reserved. +*/ + +"common.alert.error.title" = "Virhe"; +"common.alert.attention.title" = "Huomio"; "common.button.cancel" = "Peruuta"; -"common.button.change" = "Muuta"; +"common.button.change" = "Vaihda"; +"common.button.choose" = "Valitse"; +"common.button.clear" = "Tyhjennä"; "common.button.close" = "Sulje"; +"common.button.confirm" = "Vahvista"; +"common.button.create" = "Luo"; +"common.button.createFolder" = "Luo kansio"; "common.button.done" = "Valmis"; +"common.button.download" = "Lataa"; +"common.button.edit" = "Muokkaa"; +"common.button.enable" = "Hyväksy"; "common.button.next" = "Seuraava"; +"common.button.ok" = "OK"; +"common.button.refresh" = "Päivitä"; +"common.button.remove" = "Poista"; +"common.button.retry" = "Yritä uudelleen"; +"common.button.signOut" = "Kirjaudu ulos"; +"common.button.verify" = "Vahvista"; +"common.cells.password" = "Salasana"; +"common.cells.url" = "URL"; +"common.cells.username" = "Käyttäjätunnus"; +"common.footer.learnMore" = "Lue Lisää."; +"accountList.emptyList.message" = "Napauta tästä lisätäksesi tili"; +"accountList.signOut.alert.title" = "Poista liitetyt holvit?"; +"accountList.signOut.alert.message" = "Kirjautuessasi ulos kaikki liitetyt holvit poistetaan holvilistasta. Salattua dataa ei poisteta. Voit kirjautua sisään ja lisätä holvit myöhemmin uudelleen."; -"addVault.title" = "Lisää Vault"; +"addVault.title" = "Lisää holvi"; "addVault.createNewVault.title" = "Luo Uusi Vault"; -"addVault.createNewVault.setVaultName.cells.name" = "Vault Nimi"; -"addVault.createNewVault.chooseCloud.header" = "Missä pitäisi Cryptomator tallentaa salattuja tiedostoja Vault?"; +"addVault.createNewVault.setVaultName.cells.name" = "Holvin nimi"; +"addVault.createNewVault.chooseCloud.header" = "Missä Cryptomatorin tulisi säilyttää holvisi salattuja tiedostoja?"; +"addVault.createNewVault.password.enterPassword.header" = "Syötä uusi salasana."; +"addVault.createNewVault.password.confirmPassword.header" = "Vahvista uusi salasana."; +"addVault.createNewVault.password.confirmPassword.alert.title" = "Vahvista salasana?"; +"addVault.createNewVault.password.confirmPassword.alert.message" = "TÄRKEÄÄ: Jos unohdat salasanasi, tietojasi ei voida palauttaa."; +"addVault.createNewVault.password.error.emptyPassword" = "Salasana ei voi olla tyhjä."; +"addVault.createNewVault.password.error.nonMatchingPasswords" = "Salasanat eivät täsmää."; +"addVault.createNewVault.password.error.tooShortPassword" = "Salasanassa pitää olla vähintää 8 merkkiä."; +"addVault.createNewVault.progress" = "Luodaan holvia…"; "addVault.openExistingVault.title" = "Avaa Olemassaoleva Vault"; +"addVault.openExistingVault.chooseCloud.header" = "Missä holvi sijaitsee?"; +"addVault.openExistingVault.detectedMasterkey.add" = "Lisää tämä holvi"; +"addVault.openExistingVault.downloadVault.progress" = "Ladataan holvia…"; +"addVault.openExistingVault.password.footer" = "Syötä holvin \"%@\" salasana."; +"addVault.openExistingVault.progress" = "Lisätään holvia…"; + +"biometryType.faceID" = "Face ID"; +"biometryType.touchID" = "Touch ID"; +"changePassword.header.newPassword.title" = "Syötä uusi salasana."; +"changePassword.header.newPasswordConfirmation.title" = "Vahvista uusi salasana."; + +"cloudProvider.error.itemNotFound" = "\"%@\" ei löytynyt."; +"cloudProvider.error.itemAlreadyExists" = "\"%@\" on jo olemassa."; + +"fileProvider.onboarding.title" = "Tervetuloa"; +"fileProvider.onboarding.button.openCryptomator" = "Avaa Cryptomator"; +"fileProvider.error.biometricalAuthCanceled.title" = "Avaus peruutettu"; "fileProvider.error.unlockButton" = "Avaa"; "hubAuthentication.accessNotGranted" = "Laitteellasi ei ole pääsyvaltuutusta tähän holviin. Pyydä holvin omistajaa lisäämän valtuutus laitteellesi."; "hubAuthentication.licenseExceeded" = "Cryptomator Hub:illasi ei ole voimassa olevaa lisenssiä. Ole hyvä ja ilmoita Hubin järjestelmänvalvojalle lisenssin päivittämiseksi tai sen uusimiseksi."; @@ -16,5 +71,8 @@ "hubAuthentication.deviceRegistration.needsAuthorization.alert.message" = "Käyttääksesi holvia, holvin omistajan on valtuutettava laitteesi."; "unlockVault.button.unlock" = "Avaa"; +"unlockVault.password.footer" = "Syötä holvin \"%@\" salasana."; "vaultDetail.button.changeVaultPassword" = "Vaihda salasana"; +"vaultDetail.button.moveVault" = "Siirrä"; +"vaultDetail.button.renameVault" = "Nimeä uudelleen"; diff --git a/SharedResources/id.lproj/Localizable.strings b/SharedResources/id.lproj/Localizable.strings index 87eb92ee9..e4c92412f 100644 --- a/SharedResources/id.lproj/Localizable.strings +++ b/SharedResources/id.lproj/Localizable.strings @@ -101,6 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "Kata sandi yang tersimpan untuk %@ salah. Silahkan coba lagi dan masukkan kata sandi Anda untuk mengaktifkan kembali %@."; "fileProvider.error.defaultLock.title" = "Kunci Perlu Dibuka"; "fileProvider.error.defaultLock.message" = "Kunci perlu dibuka untuk mengakses dan menunjukkan isi vault Anda."; +"fileprovider.error.unauthorized.text" = "Akses ke brankas Anda '%@' ditolak. Buka aplikasi utama untuk memeriksa sambungan dan masuk kembali jika diperlukan."; "fileProvider.error.unlockButton" = "Buka Kunci"; "fileProvider.clearFileFromCache.title" = "Hapus File dari Cache"; "fileProvider.clearFileFromCache.message" = "Ini hanya akan menghapus file lokal di perangkat Anda dan tidak akan menghapus file yang ada di cloud."; diff --git a/SharedResources/pa.lproj/Localizable.strings b/SharedResources/pa.lproj/Localizable.strings index 51e55de05..a5612972f 100644 --- a/SharedResources/pa.lproj/Localizable.strings +++ b/SharedResources/pa.lproj/Localizable.strings @@ -22,6 +22,7 @@ "common.button.next" = "ਅੱਗੇ"; "common.button.ok" = "ਠੀਕ ਹੈ"; "common.button.refresh" = "ਤਾਜ਼ਾ ਕਰੋ"; +"common.button.register" = "ਰਜਿਸਟਰ ਕਰੋ"; "common.button.remove" = "ਹਟਾਓ"; "common.button.retry" = "ਮੁੜ-ਕੋਸ਼ਿਸ਼"; "common.button.signOut" = "ਸਾਈਨ ਆਉਟ"; @@ -59,6 +60,7 @@ "addVault.openExistingVault.chooseCloud.header" = "ਵਾਲਟ ਕਿੱਥੇ ਮੌਜੂਦ ਹੈ?"; "addVault.openExistingVault.detectedMasterkey.text" = "Cryptomator ਨੂੰ \"%@\" ਵਾਲਟ ਖੋਜਿਆ ਗਿਆ ਹੈ।\nਕੀ ਤੁਸੀ ਇਹ ਵਾਲਟ ਜੋੜਨਾ ਚਾਹੁੰਦੇ ਹੋ?"; "addVault.openExistingVault.detectedMasterkey.add" = "ਇਹ ਵਾਲਟ ਜੋੜੋ"; +"addVault.openExistingVault.downloadVault.progress" = "ਵਾਲਟ ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"; "addVault.openExistingVault.password.footer" = "\"%@\" ਲਈ ਪਾਸਵਰਡ ਦਿਓ।"; "addVault.openExistingVault.progress" = "…ਵਾਲਟ ਜੋੜਿਆ ਜਾ ਰਿਹਾ ਹੈ"; "addVault.success.info" = "\"%@\" ਵਾਲਟ ਨੂੰ ਕਾਮਯਾਬੀ ਨਾਲ ਜੋੜਿਆ ਗਿਆ ਹੈ।\nਇਸ ਵਾਲਟ ਨੂੰ Files ਐਪ ਰਾਹੀਂ ਵਰਤੋਂ।"; @@ -142,6 +144,9 @@ "purchase.product.yearlySubscription" = "ਸਾਲਨਾ ਮੈਂਬਰੀ"; "purchase.product.yearlySubscription.duration" = "ਸਾਲਨਾ"; "purchase.readOnlyMode.alert.title" = "ਕੇਵਲ ਪੜ੍ਹਨ ਲਈ ਢੰਗ"; +"purchase.restorePurchase.button" = "ਖਰੀਦਦਾਰੀ ਨੂੰ ਬਹਾਲ ਕਰੋ"; +"purchase.restorePurchase.fullVersionFound.alert.title" = "ਬਹਾਲ ਕਰਨਾ ਕਾਮਯਾਬ ਰਿਹਾ"; +"purchase.restorePurchase.fullVersionNotFound.alert.title" = "ਪੂਰਾ ਵਰਜ਼ਨ ਨਹੀਂ ਹੈ"; "purchase.retry.button" = "ਮੁੜ-ਕੋਸ਼ਿਸ਼"; "purchase.title" = "ਪੂਰਾ ਵਰਜ਼ਨ ਅਣ-ਲਾਕ ਕਰੋ"; "purchase.unlockedFullVersion.title" = "ਤੁਹਾਡਾ ਧੰਨਵਾਦ"; @@ -192,6 +197,9 @@ "vaultDetail.button.moveVault" = "ਭੇਜੋ"; "vaultDetail.button.removeVault" = "ਵਾਲਟ ਸੂਚੀ ਵਿੱਚੋਂ ਹਟਾਓ"; "vaultDetail.button.renameVault" = "ਨਾਂ ਬਦਲੋ"; +"vaultDetail.info.footer.accountInfo" = "%@ ਰਾਹੀਂ %@ ਵਜੋਂ ਲਾਗਇਨ ਕੀਤਾ।"; +"vaultDetail.keepUnlocked.title" = "ਅਣ-ਲਾਕ ਦਾ ਅੰਤਰਾਲ"; +"vaultDetail.locked.footer" = "ਤੁਹਾਡਾ ਵਾਲਟ ਇਸ ਵੇਲੇ ਅਣ-ਲਾਕ ਹੈ।"; "vaultDetail.moveVault.progress" = "…ਭੇਜਿਆ ਜਾ ਰਿਹਾ ਹੈ"; "vaultDetail.renameVault.progress" = "…ਨਾਂ ਬਦਲਿਆ ਜਾ ਰਿਹਾ ਹੈ"; diff --git a/SharedResources/pt-BR.lproj/Localizable.strings b/SharedResources/pt-BR.lproj/Localizable.strings index dbf479c11..500f34a0c 100644 --- a/SharedResources/pt-BR.lproj/Localizable.strings +++ b/SharedResources/pt-BR.lproj/Localizable.strings @@ -101,6 +101,7 @@ "fileProvider.error.biometricalAuthWrongPassword.message" = "A senha que foi salva para %@ está incorreta. Por favor, tente novamente e digite sua senha para reativar %@."; "fileProvider.error.defaultLock.title" = "Desbloqueio necessário"; "fileProvider.error.defaultLock.message" = "Para acessar e mostrar o conteúdo do seu cofre, ele precisa ser desbloqueado."; +"fileprovider.error.unauthorized.text" = "O acesso ao seu cofre \"%@\" foi negado. Abra o aplicativo principal para verificar sua conexão e re-autenticar, se necessário."; "fileProvider.error.unlockButton" = "Desbloquear"; "fileProvider.clearFileFromCache.title" = "Limpar Arquivos Temporários"; "fileProvider.clearFileFromCache.message" = "Isso apenas remove o arquivo do seu dispositivo local e não o exclui da nuvem."; diff --git a/SharedResources/tr.lproj/Localizable.strings b/SharedResources/tr.lproj/Localizable.strings index 7e627aaf6..e5f9c4ea8 100644 --- a/SharedResources/tr.lproj/Localizable.strings +++ b/SharedResources/tr.lproj/Localizable.strings @@ -28,13 +28,13 @@ "common.button.signOut" = "Çıkış Yap"; "common.button.verify" = "Doğrula"; "common.cells.openInFilesApp" = "Dosyalar Uygulamasında Aç"; -"common.cells.password" = "Şifre"; +"common.cells.password" = "Parola"; "common.cells.url" = "URL"; "common.cells.username" = "Kullanıcı adı"; "common.footer.learnMore" = "Daha fazla bilgi edin."; "common.hud.authenticating" = "Kimlik doğrulanıyor…"; -"accountList.header.title" = "Kimlik Doğrulaması"; +"accountList.header.title" = "Kimlikler"; "accountList.emptyList.message" = "Hesap eklemek için buraya dokunun"; "accountList.signOut.alert.title" = "İlişkili Kasalar Kaldırılsın mı?"; "accountList.signOut.alert.message" = "Oturumu kapattığınızda, ilişkili tüm kasalar kasa listesinden kaldırılacaktır. Şifrelenmiş hiçbir veri silinmeyecektir. Tekrar oturum açabilir ve kasaları daha sonra yeniden ekleyebilirsiniz."; @@ -48,20 +48,20 @@ "addVault.createNewVault.chooseCloud.header" = "Cryptomator kasanızın şifreli dosyalarını nerede depolasın?"; "addVault.createNewVault.chooseFolder.error.vaultNameCollision" = "\"%@\" bu konumda mevcut. Farklı bir kasa adı veya konum seçin."; "addVault.createNewVault.detectedMasterkey.text" = "Cryptomator bu konumda mevcut bir kasa tespit etti.\nYeni bir kasa oluşturmak için lütfen geri dönün ve farklı bir klasör seçin."; -"addVault.createNewVault.password.enterPassword.header" = "Yeni bir şifre girin."; -"addVault.createNewVault.password.confirmPassword.header" = "Yeni şifreyi onaylayın."; -"addVault.createNewVault.password.confirmPassword.alert.title" = "Şifreyi onaylıyor musunuz?"; +"addVault.createNewVault.password.enterPassword.header" = "Yeni bir parola girin."; +"addVault.createNewVault.password.confirmPassword.header" = "Yeni parolayı onaylayın."; +"addVault.createNewVault.password.confirmPassword.alert.title" = "Parolayı onaylıyor musunuz?"; "addVault.createNewVault.password.confirmPassword.alert.message" = "ÖNEMLİ UYARI: Parolanızı unutursanız, verilerinizi kurtarmanın herhangi bir yolu yoktur."; -"addVault.createNewVault.password.error.emptyPassword" = "Şifre boş bırakılamaz."; -"addVault.createNewVault.password.error.nonMatchingPasswords" = "Şifreler eşleşmiyor."; -"addVault.createNewVault.password.error.tooShortPassword" = "Şifre en az 8 karakter içermelidir."; +"addVault.createNewVault.password.error.emptyPassword" = "Parola boş bırakılamaz."; +"addVault.createNewVault.password.error.nonMatchingPasswords" = "Parolalar eşleşmiyor."; +"addVault.createNewVault.password.error.tooShortPassword" = "Parola en az 8 karakter içermelidir."; "addVault.createNewVault.progress" = "Kasa oluşturuluyor…"; -"addVault.openExistingVault.title" = "Varolan Kasayı Aç"; +"addVault.openExistingVault.title" = "Var Olan Kasayı Aç"; "addVault.openExistingVault.chooseCloud.header" = "Kasa nerede bulunuyor?"; "addVault.openExistingVault.detectedMasterkey.text" = "Cryptomator \"%@\" kasasını algıladı.\nBu kasayı eklemek ister misiniz?"; "addVault.openExistingVault.detectedMasterkey.add" = "Bu Kasayı Ekle"; "addVault.openExistingVault.downloadVault.progress" = "Kasa indiriliyor…"; -"addVault.openExistingVault.password.footer" = "\"%@\" için şifre girin."; +"addVault.openExistingVault.password.footer" = "\"%@\" için parola girin."; "addVault.openExistingVault.progress" = "Kasa ekleniyor…"; "addVault.success.info" = "\"%@\" kasası başarıyla eklendi.\nDosyalar uygulamasından bu kasaya erişebilirsiniz."; "addVault.success.footer" = "Henüz yapmadıysanız, Dosyalar uygulamasında Cryptomator'ı etkinleştirin."; @@ -69,17 +69,17 @@ "biometryType.faceID" = "Yüz kimliği"; "biometryType.touchID" = "Dokunmatik kimlik"; -"changePassword.error.invalidOldPassword" = "Mevcut şifre yanlış. Lütfen tekrar deneyin."; -"changePassword.header.currentPassword.title" = "Mevcut şifreyi girin."; -"changePassword.header.newPassword.title" = "Yeni bir şifre girin."; -"changePassword.header.newPasswordConfirmation.title" = "Yeni şifreyi onaylayın."; -"changePassword.progress" = "Şifre değiştiriliyor…"; +"changePassword.error.invalidOldPassword" = "Mevcut parola yanlış. Lütfen tekrar deneyin."; +"changePassword.header.currentPassword.title" = "Mevcut parolayı girin."; +"changePassword.header.newPassword.title" = "Yeni bir parola girin."; +"changePassword.header.newPasswordConfirmation.title" = "Yeni parolayı onaylayın."; +"changePassword.progress" = "Parola değiştiriliyor…"; "chooseFolder.emptyFolder.footer" = "Klasör Boş"; "chooseFolder.createNewFolder.header.title" = "Klasör için bir ad seçin."; "chooseFolder.createNewFolder.cells.name" = "Klasör Adı"; "chooseFolder.createNewFolder.error.emptyFolderName" = "Klasör adı boş olamaz."; -"chooseFolder.createNewFolder.progress" = "Klasör oluşturuluyor…"; +"chooseFolder.createNewFolder.progress" = "Klasör Oluşturuluyor…"; "cloudProvider.error.itemNotFound" = "\"%@\" bulunamadı."; "cloudProvider.error.itemAlreadyExists" = "\"%@\" zaten mevcut."; @@ -87,27 +87,28 @@ "cloudProvider.error.parentFolderDoesNotExist" = "\"%@\" ana klasörü mevcut değil."; "cloudProvider.error.pageTokenInvalid" = "Dizin içeriğini alma işlemine devam edilemedi."; "cloudProvider.error.quotaInsufficient" = "Depolama alanınız yetersiz."; -"cloudProvider.error.unauthorized" = "İşlem, yetkisiz gerçekleştirilemiyor."; +"cloudProvider.error.unauthorized" = "Yetkisiz işlem gerçekleştirilemiyor."; "cloudProvider.error.noInternetConnection" = "Bu işlem için İnternet bağlantısı gerekiyor."; "cloudProviderType.localFileSystem" = "Diğer Dosya Sağlayıcı"; "fileProvider.onboarding.title" = "Hoş geldiniz"; "fileProvider.onboarding.info" = "Dosyalarınızı korumak için Cryptomator'ı seçtiğiniz için teşekkür ederiz. Başlamak için uygulamaya gidin ve bir kasa ekleyin."; -"fileProvider.onboarding.button.openCryptomator" = "Cryptomator'ı aç"; -"fileProvider.error.biometricalAuthCanceled.title" = "Kilidi açma iptal edildi"; +"fileProvider.onboarding.button.openCryptomator" = "Cryptomator'ı Aç"; +"fileProvider.error.biometricalAuthCanceled.title" = "Kilit açma iptal edildi"; "fileProvider.error.biometricalAuthCanceled.message" = "%@ yoluyla kilit açma işlemi başarılı olmadı. Lütfen tekrar deneyin."; -"fileProvider.error.biometricalAuthWrongPassword.title" = "Yanlış şifre"; -"fileProvider.error.biometricalAuthWrongPassword.message" = "%@ için kaydedilen parola yanlış. Lütfen tekrar deneyin ve %@'ı yeniden etkinleştirmek için şifrenizi girin."; -"fileProvider.error.defaultLock.title" = "Kilit açma gerekli"; +"fileProvider.error.biometricalAuthWrongPassword.title" = "Yanlış Parola"; +"fileProvider.error.biometricalAuthWrongPassword.message" = "%@ için kaydedilen parola yanlış. Lütfen tekrar deneyin ve %@'ı yeniden etkinleştirmek için parolanızı girin."; +"fileProvider.error.defaultLock.title" = "Kilit Açma Gerekli"; "fileProvider.error.defaultLock.message" = "Kasanızın içeriğine erişmek ve göstermek için kilidinin açılması gerekir."; +"fileprovider.error.unauthorized.text" = "\"%@\" kasanıza erişim reddedildi. Bağlantınızı kontrol etmek ve gerekirse yeniden kimlik doğrulaması yapmak için uygulamayı açın."; "fileProvider.error.unlockButton" = "Kilidi Aç"; "fileProvider.clearFileFromCache.title" = "Dosyayı Önbellekten Temizle"; "fileProvider.clearFileFromCache.message" = "Bu yalnızca cihazınızdan yerel dosyayı kaldırır ve bulut içindeki dosyayı silmez."; "fileProvider.fileImporting.error.missingPremium" = "Kasalarınıza yazma erişimi elde etmek için Cryptomator uygulamasında tam sürümün kilidini açın."; "fileProvider.uploadProgress.connecting" = "Bağlanıyor…"; "fileProvider.uploadProgress.message" = "Mevcut Süreç: %@\n\nYükleme sürecinin takıldığını fark ederseniz, yeniden yüklemeyi deneyebilirsiniz."; -"fileProvider.uploadProgress.missing" = "İlerleme saptanamadı. Hala arka planda çalışıyor olabilir."; +"fileProvider.uploadProgress.missing" = "İlerleme durumu tespit edilemedi. Hala arka planda çalışıyor olabilir."; "fileProvider.uploadProgress.title" = "Yükleniyor…"; "fileProvider.uploadProgress.missingDomainError" = "Alan adı bulunamadı."; @@ -115,8 +116,8 @@ "getFolderIntent.error.noVaultSelected" = "Herhangi bir kasa seçili değil."; "hubAuthentication.title" = "Hub Kasası"; -"hubAuthentication.accessNotGranted" = "Cihazınıza henüz bu kasaya erişim yetkisi verilmedi. Kasa sahibinden yetkilendirmesini isteyin."; -"hubAuthentication.licenseExceeded" = "Cryptomator Hub örneğinizde geçersiz bir lisans var. Lisansı yükseltmesi veya yenilemesi için lütfen bir Hub yöneticisini bilgilendirin."; +"hubAuthentication.accessNotGranted" = "Cihazınız henüz bu kasaya erişim için yetkilendirilmedi. Kasa sahibinden yetkilendirmesini isteyin."; +"hubAuthentication.licenseExceeded" = "Cryptomator Hub örneğinizin geçersiz bir lisansı var. Lütfen lisansı yükseltmek veya yenilemek için bir Hub yöneticisini bilgilendirin."; "hubAuthentication.deviceRegistration.deviceName.cells.name" = "Cihaz Adı"; "hubAuthentication.deviceRegistration.deviceName.footer.title" = "Bu cihazdan ilk Hub erişimi gibi görünüyor. Erişim yetkilendirmesini tanımlamak için bu cihazı isimlendirmeniz gerekir."; "hubAuthentication.deviceRegistration.accountKey.footer.title" = "Yeni uygulamalardan veya tarayıcılardan giriş yapmak için Hesap Anahtarınız gereklidir. Profilinizde bulunabilir."; @@ -177,7 +178,7 @@ "purchase.product.trial.duration" = "30 gün boyunca"; "purchase.product.yearlySubscription" = "Yıllık Abonelik"; "purchase.product.yearlySubscription.duration" = "yıllık"; -"purchase.readOnlyMode.alert.title" = "Yalnızca okuma modu"; +"purchase.readOnlyMode.alert.title" = "Sadece Okuma Modu"; "purchase.readOnlyMode.alert.message" = "Cryptomator'ın tam sürümünün kilidini daha sonra ayarlardan açabilir ve şimdilik sadece okuma modunda kullanabilirsiniz."; "purchase.restorePurchase.button" = "Satın Almayı Geri Yükle"; "purchase.restorePurchase.validTrialFound.alert.title" = "Deneme süresi devam ediyor"; @@ -198,19 +199,19 @@ "settings.aboutCryptomator" = "Cryptomator Hakkında"; "settings.aboutCryptomator.title" = "Sürüm %@ (%@)"; "settings.cacheSize" = "Önbellek Boyutu"; -"settings.clearCache" = "Önbelleği temizle"; +"settings.clearCache" = "Önbelleği Temizle"; "settings.cloudServices" = "Bulut Servisleri"; "settings.contact" = "İletişim"; -"settings.debugMode" = "Hata ayıklama Modu"; -"settings.debugMode.alert.message" = "Bu modda, hassas veriler cihazınızdaki bir günlük dosyasına (örn. Dosya adları ve yolları) yazılabilir. Şifreler, tanımlama vb. bilgiler hariç tutulmuştur.\n\nHata ayıklama modunu mümkün olan en kısa sürede devre dışı bırakmayı unutmayın."; +"settings.debugMode" = "Hata Ayıklama Modu"; +"settings.debugMode.alert.message" = "Bu modda, hassas veriler cihazınızdaki bir günlük dosyasına (örn. dosya adları ve yolları) yazılabilir. Parolalar, tanımlama vb. bilgiler hariç tutulmuştur.\n\nHata ayıklama modunu mümkün olan en kısa sürede devre dışı bırakmayı unutmayın."; "settings.manageSubscriptions" = "Aboneliği Yönet"; "settings.rateApp" = "Uygulamayı Değerlendir"; "settings.sendLogFile" = "Günlük Dosyasını Gönder"; "settings.shortcutsGuide" = "Kısayol Kılavuzu"; "settings.unlockFullVersion" = "Tam Sürümün Kilidini Aç"; -"snapshots.fileprovider.file1" = "/Sayıları.hesaplıyor"; -"snapshots.fileprovider.file2" = "/Son Sunum.anahtarı"; +"snapshots.fileprovider.file1" = "/Muhasebe.numbers"; +"snapshots.fileprovider.file2" = "/Son Sunum.key"; "snapshots.fileprovider.file3" = "/Ürün Deneme.mov"; "snapshots.fileprovider.file4" = "/Teklif.docx"; "snapshots.fileprovider.file5" = "/Rapor.pdf"; @@ -220,7 +221,7 @@ "snapshots.main.vault1" = "/İş"; "snapshots.main.vault2" = "/Aile"; "snapshots.main.vault3" = "/Belgeler"; -"snapshots.main.vault4" = "/Kaliforniya gezisi"; +"snapshots.main.vault4" = "/Kaliforniya Gezisi"; "s3Authentication.displayName" = "Görünen Ad"; "s3Authentication.accessKey" = "Erişim Anahtarı"; @@ -236,9 +237,9 @@ "unlockVault.button.unlock" = "Kilidi Aç"; "unlockVault.button.unlockVia" = "Kilidi %@ ile aç"; -"unlockVault.password.footer" = "\"%@\" için şifre girin."; +"unlockVault.password.footer" = "\"%@\" için parola girin."; "unlockVault.enableBiometricalUnlock.switch" = "%@ etkinleştir"; -"unlockVault.enableBiometricalUnlock.footer" = "Kasanızın kilidini şifrenizle açmak yerine, %@ ile açabilirsiniz."; +"unlockVault.enableBiometricalUnlock.footer" = "Kasanızın kilidini parolanızla açmak yerine, %@ ile açabilirsiniz."; "unlockVault.evaluatePolicy.reason" = "Kasanızın kilidini açın"; "unlockVault.progress" = "Kilit açılıyor…"; @@ -263,12 +264,12 @@ "vaultAccountManager.error.vaultAccountAlreadyExists" = "Bu kasayı zaten eklediniz."; -"vaultDetail.button.changeVaultPassword" = "Şifreyi Değiştir"; +"vaultDetail.button.changeVaultPassword" = "Parolayı Değiştir"; "vaultDetail.button.lock" = "Şimdi Kilitle"; "vaultDetail.button.moveVault" = "Taşı"; "vaultDetail.button.removeVault" = "Kasa Listesinden Kaldır"; -"vaultDetail.button.renameVault" = "Yeniden adlandır"; -"vaultDetail.changePassword.footer" = "Kasanız için sadece sizi bildiğiniz ve güvenli bir yerde sakladığınız güçlü bir şifre seçin."; +"vaultDetail.button.renameVault" = "Yeniden Adlandır"; +"vaultDetail.changePassword.footer" = "Kasanız için sadece sizi bildiğiniz ve güvenli bir yerde sakladığınız güçlü bir parola seçin."; "vaultDetail.disabledBiometricalUnlock.footer" = "%@'yi etkinleştirirseniz kasa parolanız iOS anahtar zincirinde saklanır."; "vaultDetail.enabledBiometricalUnlock.footer" = "Kasa parolanız yalnızca %@ kimlik doğrulaması başarısız olursa gerekli olacaktır."; "vaultDetail.info.footer.accessVault" = "Dosyalar uygulaması aracılığıyla kasaya erişin."; diff --git a/fastlane/changelog.txt b/fastlane/changelog.txt index e3fdadb74..d0e0406b0 100644 --- a/fastlane/changelog.txt +++ b/fastlane/changelog.txt @@ -1,3 +1 @@ -- Added app icon variants for dark mode and tinted mode (#385). -- Introduced a clearer error screen when access to a vault is denied and a re-authentication is required (#18, #384). -- Fixed missing lock icon in the vaults list (#346, #386). \ No newline at end of file +Small adjustments to provide you with timely and relevant updates. We hope you enjoy the app! \ No newline at end of file diff --git a/fastlane/config/freemium/metadata/de-DE/release_notes.txt b/fastlane/config/freemium/metadata/de-DE/release_notes.txt index da0c1b2d3..fa4fe2bff 100644 --- a/fastlane/config/freemium/metadata/de-DE/release_notes.txt +++ b/fastlane/config/freemium/metadata/de-DE/release_notes.txt @@ -1,3 +1 @@ -- Varianten von App-Icons für den dunklen und den eingefärbten Modus hinzugefügt (#385). -- Verständlicheren Fehlerdialog eingeführt, wenn der Zugriff auf einen Tresor verweigert wird und eine erneute Authentifizierung erforderlich ist (#18, #384). -- Fehlendes Schloss-Symbol in der Tresorliste behoben (#346, #386). \ No newline at end of file +Kleine Anpassungen, um zeitnahe und relevante Updates zu bieten. Wir wünschen viel Spaß mit der App! \ No newline at end of file diff --git a/fastlane/config/freemium/metadata/en-US/release_notes.txt b/fastlane/config/freemium/metadata/en-US/release_notes.txt index e3fdadb74..d0e0406b0 100644 --- a/fastlane/config/freemium/metadata/en-US/release_notes.txt +++ b/fastlane/config/freemium/metadata/en-US/release_notes.txt @@ -1,3 +1 @@ -- Added app icon variants for dark mode and tinted mode (#385). -- Introduced a clearer error screen when access to a vault is denied and a re-authentication is required (#18, #384). -- Fixed missing lock icon in the vaults list (#346, #386). \ No newline at end of file +Small adjustments to provide you with timely and relevant updates. We hope you enjoy the app! \ No newline at end of file