diff --git a/NearbyShare/Connection/InboundNearbyConnection.swift b/NearbyShare/Connection/InboundNearbyConnection.swift index 6cc9ffa..55d4c3f 100644 --- a/NearbyShare/Connection/InboundNearbyConnection.swift +++ b/NearbyShare/Connection/InboundNearbyConnection.swift @@ -547,9 +547,8 @@ class InboundNearbyConnection: NearbyConnection { func submitUserConsent(accepted: Bool, trustDevice: Bool, storeInTemp: Bool = false) { - - if trustDevice, let peerCertificate = peerCertificate { - TrustStore.shared.addTrusted(certificate: peerCertificate) + if trustDevice, let peerCertificate = peerCertificate, let remoteDeviceInfo = remoteDeviceInfo { + TrustStore.shared.addTrusted(certificate: peerCertificate, device: remoteDeviceInfo) } DispatchQueue.global(qos: .utility).async { diff --git a/NearbyShare/Model/DataModel.swift b/NearbyShare/Model/DataModel.swift index 5ef367b..5677b54 100644 --- a/NearbyShare/Model/DataModel.swift +++ b/NearbyShare/Model/DataModel.swift @@ -46,10 +46,10 @@ public protocol OutboundAppDelegate: AnyObject { } -public struct RemoteDeviceInfo: Identifiable, Equatable { +public struct RemoteDeviceInfo: Codable, Identifiable, Equatable { public let name: String? public let type: DeviceType - public let qrCodeData:Data? + public let qrCodeData: Data? public var id: String? init(name: String, type: DeviceType, id: String? = nil) { @@ -67,7 +67,7 @@ public struct RemoteDeviceInfo: Identifiable, Equatable { } - public enum DeviceType: Int32 { + public enum DeviceType: Int32, Codable { case unknown = 0 case phone case tablet diff --git a/NearbyShare/Util/TrustStore.swift b/NearbyShare/Util/TrustStore.swift index e09f5f8..87e5f99 100644 --- a/NearbyShare/Util/TrustStore.swift +++ b/NearbyShare/Util/TrustStore.swift @@ -8,26 +8,80 @@ import Foundation -class TrustStore { + +class TrustStore: ObservableObject { static let shared = TrustStore() + + @Published private(set) var trustedCertificates: [String: TrustedCertificate] = [:] + private let trustedKeysKey = "com.leonboettger.quickdrop.identity.trustedKeys" - - - private func getTrustedKeys() -> [String: Data] { - return AppGroup.appGroupUD.dictionary(forKey: trustedKeysKey) as? [String: Data] ?? [:] + + private init() { + loadTrustedCertificates() } - + + // MARK: - Persistence + + private func loadTrustedCertificates() { + guard let dict = AppGroup.appGroupUD.dictionary(forKey: trustedKeysKey) as? [String: Data] else { + trustedCertificates = [:] + return + } + + var decoded: [String: TrustedCertificate] = [:] + for (key, data) in dict { + if let cert = try? JSONDecoder().decode(TrustedCertificate.self, from: data) { + decoded[key] = cert + } + } + trustedCertificates = decoded + } + + + private func saveTrustedCertificates() { + var dict: [String: Data] = [:] + for (key, cert) in trustedCertificates { + if let data = try? JSONEncoder().encode(cert) { + dict[key] = data + } + } + AppGroup.appGroupUD.set(dict, forKey: trustedKeysKey) + } + + + // MARK: - Public API + func findTrustedKey(for secretIdHash: Data) -> Data? { - return getTrustedKeys()[secretIdHash.hex] + trustedCertificates[secretIdHash.hex]?.certificateData } - - func addTrusted(certificate: Sharing_Nearby_PublicCertificate) { + + func addTrusted(certificate: Sharing_Nearby_PublicCertificate, device: RemoteDeviceInfo) { guard let publicKeyData = try? certificate.serializedData() else { return } - var keys = getTrustedKeys() - keys[certificate.secretID.hex] = publicKeyData - AppGroup.appGroupUD.set(keys, forKey: trustedKeysKey) + + trustedCertificates[certificate.secretID.hex] = TrustedCertificate( + device: device, + creationDate: Date(), + certificateData: publicKeyData + ) + + saveTrustedCertificates() + } + + + func removeTrusted(secretIdHex: String) { + trustedCertificates.removeValue(forKey: secretIdHex) + saveTrustedCertificates() + } + + + struct TrustedCertificate: Codable, Equatable { + + // warning: do not rename for persistence + let device: RemoteDeviceInfo + let creationDate: Date + let certificateData: Data } } diff --git a/QuickDrop.xcodeproj/project.pbxproj b/QuickDrop.xcodeproj/project.pbxproj index 081ec29..4cf0de6 100644 --- a/QuickDrop.xcodeproj/project.pbxproj +++ b/QuickDrop.xcodeproj/project.pbxproj @@ -14,6 +14,9 @@ 699DEBAE2AB0573200115D22 /* QuickDropShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 699DEBA12AB0573200115D22 /* QuickDropShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A1129E0BF5100A442DA /* AppDelegate.swift */; }; 69DA9A1429E0BF5200A442DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DA9A1329E0BF5200A442DA /* Assets.xcassets */; }; + EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; + EB05DFBF2E59FD0A00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; + EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; EB16B6122E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; EB16B6132E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; EB16B6142E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; @@ -299,6 +302,7 @@ 69DA9A2B29E18CB500A442DA /* offline_wire_formats.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = offline_wire_formats.pb.swift; sourceTree = ""; }; 69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securegcm.pb.swift; sourceTree = ""; }; 69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securemessage.pb.swift; sourceTree = ""; }; + EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedDevicesView.swift; sourceTree = ""; }; EB16B6112E58B4B9007D9792 /* IdentityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityManager.swift; sourceTree = ""; }; EB16B6162E58B4C8007D9792 /* TrustStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustStore.swift; sourceTree = ""; }; EB16B7762E59BA9F007D9792 /* AppGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroup.swift; sourceTree = ""; }; @@ -590,6 +594,7 @@ EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */, EB7F54112D78E95C00989564 /* TutorialView.swift */, EB7F54132D78E9E400989564 /* LicenseWindow.swift */, + EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */, EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */, EBC05C812E33B58300EECC18 /* IssueViews */, ); @@ -928,6 +933,7 @@ EB5C37B82E377A6F0052EFD7 /* SleepManager.swift in Sources */, EB5C37B92E377A6F0052EFD7 /* SaveFilesManager.swift in Sources */, EB5C37BA2E377A6F0052EFD7 /* Helpers.swift in Sources */, + EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */, EB16B6182E58B4C8007D9792 /* TrustStore.swift in Sources */, EBC05C5B2E33937200EECC18 /* ErrorAlertHandler.swift in Sources */, EBC05C712E33B57D00EECC18 /* Converter.swift in Sources */, @@ -974,6 +980,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + EB05DFBF2E59FD0A00EF567A /* TrustedDevicesView.swift in Sources */, EB5C37F12E377CE70052EFD7 /* ukey.pb.swift in Sources */, EB5C37F22E377CE70052EFD7 /* NearbyConnection.swift in Sources */, EB5C37F32E377CE70052EFD7 /* SaveFilesManager.swift in Sources */, @@ -1034,6 +1041,7 @@ EB950B512E520436002D68FA /* securemessage.pb.swift in Sources */, EB950B522E520436002D68FA /* NearbyConnectionManager.swift in Sources */, EB950B532E520436002D68FA /* ukey.pb.swift in Sources */, + EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */, EB950B542E520436002D68FA /* HKDF.swift in Sources */, EB950B552E520436002D68FA /* SaveFilesManager.swift in Sources */, EB950B562E520436002D68FA /* DataModel.swift in Sources */, diff --git a/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme index 7f2fb73..e493fbd 100644 --- a/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme +++ b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme @@ -34,7 +34,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "en" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/QuickDrop/Localizable.xcstrings b/QuickDrop/Localizable.xcstrings index 8349680..a8c0f4f 100644 --- a/QuickDrop/Localizable.xcstrings +++ b/QuickDrop/Localizable.xcstrings @@ -2138,108 +2138,110 @@ } } }, - "ConnectWithQuickDropApp" : { + "Connecting" : { + "comment" : "Share Extension", + "extractionState" : "manual", "localizations" : { "ar" : { "stringUnit" : { "state" : "translated", - "value" : "الاتصال بتطبيق QuickDrop" + "value" : "جارٍ الاتصال..." } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "Mit QuickDrop-App verbinden" + "value" : "Verbinden..." } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "Connect with QuickDrop App" + "value" : "Connecting..." } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "Conectar con la aplicación QuickDrop" + "value" : "Conectando..." } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Se connecter avec l'app QuickDrop" + "value" : "Connexion en cours..." } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "Csatlakozás a QuickDrop alkalmazással" + "value" : "Csatlakozás..." } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "Connetti con l'app QuickDrop" + "value" : "Connessione in corso..." } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "QuickDropアプリで接続" + "value" : "接続中..." } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "QuickDrop 앱으로 연결" + "value" : "연결 중..." } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "Verbind met de QuickDrop-app" + "value" : "Verbinden..." } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Conectar com o aplicativo QuickDrop" + "value" : "Conectando..." } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Ligar com a app QuickDrop" + "value" : "A ligar..." } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Conectează-te cu aplicația QuickDrop" + "value" : "Se conectează..." } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Подключиться с помощью приложения QuickDrop" + "value" : "Подключение..." } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "เชื่อมต่อด้วยแอป QuickDrop" + "value" : "กำลังเชื่อมต่อ..." } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "Підключитися за допомогою додатка QuickDrop" + "value" : "Підключення..." } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "使用 QuickDrop 应用连接" + "value" : "正在连接..." } } } @@ -2350,110 +2352,108 @@ } } }, - "Connecting" : { - "comment" : "Share Extension", - "extractionState" : "manual", + "ConnectWithQuickDropApp" : { "localizations" : { "ar" : { "stringUnit" : { "state" : "translated", - "value" : "جارٍ الاتصال..." + "value" : "الاتصال بتطبيق QuickDrop" } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "Verbinden..." + "value" : "Mit QuickDrop-App verbinden" } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "Connecting..." + "value" : "Connect with QuickDrop App" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "Conectando..." + "value" : "Conectar con la aplicación QuickDrop" } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Connexion en cours..." + "value" : "Se connecter avec l'app QuickDrop" } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "Csatlakozás..." + "value" : "Csatlakozás a QuickDrop alkalmazással" } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "Connessione in corso..." + "value" : "Connetti con l'app QuickDrop" } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "接続中..." + "value" : "QuickDropアプリで接続" } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "연결 중..." + "value" : "QuickDrop 앱으로 연결" } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "Verbinden..." + "value" : "Verbind met de QuickDrop-app" } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Conectando..." + "value" : "Conectar com o aplicativo QuickDrop" } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "A ligar..." + "value" : "Ligar com a app QuickDrop" } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Se conectează..." + "value" : "Conectează-te cu aplicația QuickDrop" } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Подключение..." + "value" : "Подключиться с помощью приложения QuickDrop" } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "กำลังเชื่อมต่อ..." + "value" : "เชื่อมต่อด้วยแอป QuickDrop" } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "Підключення..." + "value" : "Підключитися за допомогою додатка QuickDrop" } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "正在连接..." + "value" : "使用 QuickDrop 应用连接" } } } @@ -5346,109 +5346,109 @@ } } }, - "NFiles" : { + "ManageTrustedDevices" : { "extractionState" : "manual", "localizations" : { "ar" : { "stringUnit" : { "state" : "translated", - "value" : "%d ملفات" + "value" : "إدارة الأجهزة الموثوقة" } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "%d Dateien" + "value" : "Vertrauenswürdige Geräte verwalten" } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "%d files" + "value" : "Manage Trusted Devices" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "%d archivos" + "value" : "Gestionar dispositivos confiables" } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "%d fichiers" + "value" : "Gérer les appareils de confiance" } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "%d fájl" + "value" : "Megbízható eszközök kezelése" } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "%d files" + "value" : "Gestisci dispositivi affidabili" } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "%dつのファイル" + "value" : "信頼されたデバイスを管理" } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "%d개의 파일" + "value" : "신뢰하는 기기 관리" } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "%d bestanden" + "value" : "Beheer vertrouwde apparaten" } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "%d arquivos" + "value" : "Gerenciar Dispositivos Confiáveis" } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "%d ficheiros" + "value" : "Gerir dispositivos de confiança" } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "%d fișiere" + "value" : "Gestionează dispozitivele de încredere" } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "%d файлов" + "value" : "Управление доверенными устройствами" } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "%d ไฟล์" + "value" : "จัดการอุปกรณ์ที่เชื่อถือ" } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "%d files" + "value" : "Керування довіреними пристроями" } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "%d files" + "value" : "管理可信设备" } } } @@ -5667,6 +5667,113 @@ } } }, + "NFiles" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d ملفات" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d Dateien" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d files" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d archivos" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d fichiers" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d fájl" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d files" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "%dつのファイル" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d개의 파일" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d bestanden" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d arquivos" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d ficheiros" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d fișiere" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d файлов" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d ไฟล์" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d files" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d files" + } + } + } + }, "NoDevicesFound" : { "extractionState" : "manual", "localizations" : { @@ -6202,6 +6309,113 @@ } } }, + "NoTrustedDevices" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لا توجد أجهزة موثوقة" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine vertrauenswürdigen Geräte" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Trusted Devices" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin dispositivos confiables" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun appareil de confiance" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nincs megbízható eszköz" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nessun dispositivo affidabile" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "信頼されたデバイスはありません" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "신뢰하는 기기 없음" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Geen vertrouwde apparaten" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nenhum Dispositivo Confiável" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sem dispositivos de confiança" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Niciun dispozitiv de încredere" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нет доверенных устройств" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ไม่มีอุปกรณ์ที่เชื่อถือ" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Немає довірених пристроїв" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无可信设备" + } + } + } + }, "OpenFinderAfterReceiving" : { "localizations" : { "ar" : { @@ -6522,6 +6736,1388 @@ } } }, + "plusview_description" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "قم بفتح QuickDrop+ لمواصلة تبادل الملفات بلا حدود. QuickDrop+ هو شراء لمرة واحدة – لا حاجة للاشتراك. تشمل جميع الميزات الحالية والمستقبلية." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Schalte QuickDrop+ frei, um weiterhin Dateien unbegrenzt auszutauschen. QuickDrop+ ist ein Einmalkauf - ein Abonnement ist nicht erforderlich. Alle aktuellen und zukünftigen Funktionen sind enthalten." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unlock QuickDrop+ to continue exchanging files without limits. QuickDrop+ is a one-time purchase – no subscription required. All current and future features are included." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Desbloquea QuickDrop+ para seguir intercambiando archivos sin límites. QuickDrop+ es una compra única – no se requiere suscripción. Todas las funciones actuales y futuras están incluidas." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Débloquez QuickDrop+ pour continuer à échanger des fichiers sans limites. QuickDrop+ est un achat unique – aucun abonnement requis. Toutes les fonctionnalités actuelles et futures sont incluses." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oldd fel a QuickDrop+-t, hogy korlátlanul folytathasd a fájlcserét. A QuickDrop+ egy egyszeri vásárlás – előfizetés nem szükséges. Az összes jelenlegi és jövőbeli funkciót tartalmazza." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sblocca QuickDrop+ per continuare a scambiare file senza limiti. QuickDrop+ è un acquisto unico – nessun abbonamento richiesto. Tutte le funzionalità attuali e future sono incluse." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDrop+ をアンロックして、無制限にファイルを交換できます。QuickDrop+ は買い切り型のアプリです。サブスクリプション不要で、現在および将来のすべての機能が含まれます。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDrop+를 잠금 해제하여 파일을 제한 없이 교환하세요. QuickDrop+는 일회성 구매이며, 구독이 필요하지 않습니다. 모든 현재 및 미래 기능이 포함됩니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ontgrendel QuickDrop+ om bestanden zonder limieten te blijven uitwisselen. QuickDrop+ is een eenmalige aankoop – geen abonnement vereist. Alle huidige en toekomstige functies zijn inbegrepen." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Desbloqueie o QuickDrop+ para continuar trocando arquivos sem limites. QuickDrop+ é uma compra única – sem necessidade de assinatura. Todos os recursos atuais e futuros estão incluídos." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Desbloqueia o QuickDrop+ para continuar a trocar ficheiros sem limites. QuickDrop+ é uma compra única – não é necessária subscrição. Todas as funcionalidades atuais e futuras estão incluídas." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deblochează QuickDrop+ pentru a continua schimbul de fișiere fără limite. QuickDrop+ este o achiziție unică – nu este necesar abonament. Toate funcțiile curente și viitoare sunt incluse." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разблокируйте QuickDrop+, чтобы продолжить обмен файлами без ограничений. QuickDrop+ – это разовая покупка, подписка не требуется. Все текущие и будущие функции включены." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ปลดล็อก QuickDrop+ เพื่อแลกเปลี่ยนไฟล์ได้อย่างไม่จำกัด QuickDrop+ เป็นการซื้อครั้งเดียว – ไม่ต้องสมัครสมาชิก ฟีเจอร์ทั้งหมดทั้งปัจจุบันและอนาคตรวมอยู่ในนี้แล้ว" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Розблокуйте QuickDrop+, щоб продовжити обмін файлами без обмежень. QuickDrop+ – це одноразова покупка, підписка не потрібна. Всі поточні та майбутні функції включені." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "解锁 QuickDrop+ 以无限制地交换文件。QuickDrop+ 是一次性购买 – 无需订阅。所有当前和未来的功能均包含在内。" + } + } + } + }, + "plusview_nothingtorestore" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "لا يوجد شيء لاستعادته!" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Es gibt nichts wiederherzustellen!" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "There is nothing to restore!" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡No hay nada que restaurar!" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucun achat à restaurer !" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nincs visszaállítható vásárlás!" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Non c'è nulla da ripristinare!" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "復元するものがありません!" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "복원할 항목이 없습니다!" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Er is niets om te herstellen!" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nada para restaurar!" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Não há nada para restaurar!" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nu există nimic de restaurat!" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нет покупок для восстановления!" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ไม่มีรายการที่ต้องกู้คืน!" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Немає покупок для відновлення!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有可恢复的购买!" + } + } + } + }, + "plusview_productRequestFailed" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "تعذر جلب عمليات الشراء داخل التطبيق في الوقت الحالي." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "In-App-Käufe können momentan nicht abgerufen werden." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unable to fetch In-App Purchases at the moment." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No se pueden recuperar las compras dentro de la aplicación en este momento." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Impossible de récupérer les achats intégrés pour le moment." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jelenleg nem lehet lekérni az alkalmazáson belüli vásárlásokat." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Impossibile recuperare gli acquisti in-app al momento." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "現在、アプリ内購入情報を取得できません。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "현재 인앱 구매 정보를 가져올 수 없습니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "In-app aankopen kunnen momenteel niet worden opgehaald." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Não foi possível recuperar as compras dentro do aplicativo no momento." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Não foi possível recuperar as compras dentro do app no momento." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Momentan, nu se pot obține informații despre achizițiile în aplicație." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Не удалось получить данные о встроенных покупках." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ไม่สามารถดึงข้อมูลการซื้อภายในแอปได้ในขณะนี้" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Наразі неможливо отримати інформацію про покупки в додатку." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂时无法获取应用内购买信息。" + } + } + } + }, + "plusview_purchasefailed" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "فشل الشراء" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kauf fehlgeschlagen" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Purchase failed" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "La compra ha fallado" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Échec de l'achat" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "A vásárlás sikertelen" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Acquisto non riuscito" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "購入に失敗しました" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "구매 실패" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aankoop mislukt" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falha na compra" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falha na compra" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Achiziția a eșuat" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ошибка покупки" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "การซื้อล้มเหลว" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Помилка покупки" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "购买失败" + } + } + } + }, + "plusview_purchasefaileddescription" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إذا ظهر هذا الرسالة بشكل غير متوقع، يرجى التأكد من اتصالك بالإنترنت وأن عمليات الشراء داخل التطبيق مفعّلة على جهازك، ثم حاول مرة أخرى." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Falls diese Nachricht unerwartet erscheint, stelle sicher, dass du mit dem Internet verbunden bist und In-App-Käufe auf deinem Gerät aktiviert sind, und versuche es erneut." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "If this message appeared unexpectedly, please make sure that you are connected to the Internet and In-App-Purchases are enabled for your device and then try again." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si este mensaje apareció inesperadamente, asegúrate de estar conectado a internet y que las compras dentro de la aplicación estén habilitadas en tu dispositivo, luego intenta nuevamente." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si ce message est apparu de manière inattendue, assurez-vous d'être connecté à Internet et que les achats intégrés sont activés sur votre appareil, puis réessayez." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ha ez az üzenet váratlanul jelent meg, ellenőrizd az internetkapcsolatot, és győződj meg róla, hogy az alkalmazáson belüli vásárlások engedélyezve vannak az eszközödön, majd próbáld újra." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se questo messaggio è apparso inaspettatamente, assicurati di essere connesso a Internet e che gli acquisti in-app siano abilitati sul tuo dispositivo, quindi riprova." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "このメッセージが予期せず表示された場合、インターネット接続を確認し、アプリ内購入が有効になっていることを確認した上で再試行してください。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이 메시지가 예상치 않게 나타난 경우, 인터넷에 연결되어 있는지 확인하고 기기에서 인앱 결제가 활성화되어 있는지 확인한 후 다시 시도해 주세요." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Als dit bericht onverwachts verschijnt, controleer dan of je verbonden bent met internet en of in-app aankopen zijn ingeschakeld op je apparaat, en probeer het opnieuw." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se esta mensagem apareceu inesperadamente, verifique se você está conectado à internet e se as compras dentro do app estão ativadas no seu dispositivo e tente novamente." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se esta mensagem apareceu inesperadamente, certifique-se de estar conectado à Internet e que as compras dentro do app estejam ativadas no seu dispositivo, depois tente novamente." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dacă acest mesaj a apărut neașteptat, asigură-te că ești conectat la internet și că achizițiile în aplicație sunt activate pe dispozitivul tău, apoi încearcă din nou." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Если это сообщение появилось неожиданно, убедитесь, что у вас есть доступ к интернету и включены встроенные покупки на вашем устройстве, затем попробуйте снова." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "หากข้อความนี้ปรากฏขึ้นโดยไม่คาดคิด โปรดตรวจสอบว่าคุณเชื่อมต่ออินเทอร์เน็ตและเปิดใช้งานการซื้อภายในแอปในอุปกรณ์ของคุณแล้วลองอีกครั้ง" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Якщо це повідомлення з’явилося несподівано, переконайтеся, що у вас є підключення до Інтернету, а покупки в додатках увімкнені на вашому пристрої, і спробуйте ще раз." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "如果此消息意外出现,请确保您已连接到互联网,并且设备已启用应用内购买功能,然后重试。" + } + } + } + }, + "plusview_restorefailed" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "حدثت مشكلة أثناء استعادة عملية الشراء" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Es gab ein Problem beim Wiederherstellen deines Kaufs" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "There was a problem restoring your purchase" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hubo un problema al restaurar tu compra" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Un problème est survenu lors de la restauration de votre achat" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hiba történt a vásárlás visszaállítása során" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si è verificato un problema durante il ripristino dell'acquisto" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "購入の復元中に問題が発生しました" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "구매 복원 중 문제가 발생했습니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Er was een probleem bij het herstellen van je aankoop" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Houve um problema ao restaurar sua compra" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Houve um problema ao restaurar sua compra" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "A apărut o problemă la restaurarea achiziției" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Произошла ошибка при восстановлении покупки" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "เกิดปัญหาในการกู้คืนการซื้อของคุณ" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Сталася помилка під час відновлення покупки" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "恢复购买时出现问题" + } + } + } + }, + "plusview_restorefailed_proceed" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "موافق" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Okay" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Okay" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aceptar" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rendben" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ok" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "확인" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oké" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ok" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Окей" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ตกลง" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Гаразд" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确定" + } + } + } + }, + "plusview_restorepurchase" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "هل اشتريته بالفعل؟" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bereits gekauft?" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Already bought?" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Ya lo compraste?" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Déjà acheté ?" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Már megvásároltad?" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Già acquistato?" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "すでに購入済みですか?" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이미 구매하셨나요?" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Al gekocht?" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Já comprou?" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Já comprou?" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deja cumpărat?" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Уже куплено?" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "เคยซื้อแล้ว?" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Вже куплено?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已购买?" + } + } + } + }, + "plusview_success_button" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "حسنًا!" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alles klar!" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Got it!" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Entendido!" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "D'accord !" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Értettem!" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Capito!" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "了解!" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "알겠습니다!" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Begrepen!" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entendi!" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entendido!" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Înțeles!" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Понял!" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "รับทราบ!" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Зрозуміло!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "知道了!" + } + } + } + }, + "plusview_success_description" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "يمكنك الآن متابعة استلام الملفات بدون قيود. أي ملفات حاولت إرسالها سابقًا تم حفظها بالفعل على جهازك." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Du kannst nun weiterhin Dateien ohne Einschränkungen empfangen. Alle Dateien, welche gerade gesendet wurden, wurden bereits gespeichert." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You can now continue receiving files without restrictions. Any files you tried to send were already saved on your device." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ahora puedes seguir recibiendo archivos sin restricciones. Todos los archivos que intentaste enviar antes ya se han guardado en tu dispositivo." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vous pouvez maintenant continuer à recevoir des fichiers sans restrictions. Tous les fichiers que vous avez essayé d'envoyer précédemment ont déjà été enregistrés sur votre appareil." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostantól korlátozások nélkül fogadhat fájlokat. Az összes fájl, amelyet korábban próbált elküldeni, már el lett mentve az eszközére." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ora puoi continuare a ricevere file senza restrizioni. Tutti i file che hai provato a inviare in precedenza sono già stati salvati sul tuo dispositivo." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "これで、制限なくファイルを受信し続けることができます。以前送信しようとしたファイルはすでにデバイスに保存されています。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이제 파일을 제한 없이 계속 받을 수 있습니다. 이전에 전송을 시도한 모든 파일이 이미 기기에 저장되었습니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Je kunt nu bestanden blijven ontvangen zonder beperkingen. Alle bestanden die je eerder probeerde te verzenden, zijn al opgeslagen op je apparaat." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agora você pode continuar recebendo arquivos sem restrições. Todos os arquivos que você tentou enviar antes já foram salvos no seu dispositivo." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agora pode continuar a receber ficheiros sem restrições. Todos os ficheiros que tentou enviar antes já foram guardados no seu dispositivo." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Acum puteți continua să primiți fișiere fără restricții. Toate fișierele pe care ați încercat să le trimiteți anterior au fost deja salvate pe dispozitivul dvs." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Теперь вы можете продолжать получать файлы без ограничений. Все файлы, которые вы пытались отправить ранее, уже сохранены на вашем устройстве." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "คุณสามารถรับไฟล์ต่อไปได้โดยไม่มีข้อจำกัด ไฟล์ทั้งหมดที่คุณพยายามส่งก่อนหน้านี้ถูกบันทึกไว้ในอุปกรณ์ของคุณแล้ว" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Тепер ви можете продовжувати отримувати файли без обмежень. Усі файли, які ви намагалися надіслати раніше, вже збережено на вашому пристрої." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "您现在可以继续无限制地接收文件。您之前尝试发送的所有文件已保存到您的设备上。" + } + } + } + }, + "plusview_success_title" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "شكرًا لشرائك!" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Danke für deinen Kauf!" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Thanks for your purchase!" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Gracias por tu compra!" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Merci pour votre achat !" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Köszönjük a vásárlást!" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grazie per il tuo acquisto!" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "ご購入ありがとうございます!" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "구매해 주셔서 감사합니다!" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bedankt voor je aankoop!" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Obrigado pela sua compra!" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Obrigado pela sua compra!" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mulțumim pentru achiziție!" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Спасибо за покупку!" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ขอบคุณสำหรับการซื้อ!" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Дякуємо за покупку!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "感谢您的购买!" + } + } + } + }, + "plusview_title" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "شكرًا لاستخدامك QuickDrop!" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Danke, dass du QuickDrop benutzt!" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Thanks for using QuickDrop!" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Gracias por usar QuickDrop!" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Merci d'utiliser QuickDrop !" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Köszönjük, hogy használod a QuickDropot!" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grazie per aver usato QuickDrop!" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDropをご利用いただきありがとうございます!" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDrop을 사용해 주셔서 감사합니다!" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bedankt voor het gebruiken van QuickDrop!" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Obrigado por usar o QuickDrop!" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Obrigado por usar o QuickDrop!" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mulțumim că folosești QuickDrop!" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Спасибо за использование QuickDrop!" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ขอบคุณที่ใช้ QuickDrop!" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Дякуємо за використання QuickDrop!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "感谢使用 QuickDrop!" + } + } + } + }, + "plusview_unlock_label" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "ادعم QuickDrop" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unterstütze QuickDrop" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Support QuickDrop" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Apoyar QuickDrop" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Soutenir QuickDrop" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Támogasd a QuickDropot" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supporta QuickDrop" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDropをサポート" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "QuickDrop 지원하기" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ondersteun QuickDrop" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Apoie o QuickDrop" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Apoiar QuickDrop" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Susține QuickDrop" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Поддержать QuickDrop" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "สนับสนุน QuickDrop" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Підтримати QuickDrop" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "支持 QuickDrop" + } + } + } + }, "Preparing" : { "extractionState" : "manual", "localizations" : { @@ -7806,6 +9402,326 @@ } } }, + "Remove" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إزالة" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entfernen" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eltávolítás" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rimuovi" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "削除" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "제거" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verwijderen" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remover" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remover" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Elimină" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Удалить" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ลบ" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Видалити" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "移除" + } + } + } + }, + "RemoveTrustedDeviceAlertDescription" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إذا قمت بإزالة هذا الجهاز، يجب قبول النقل الوارد من هذا الجهاز يدويًا." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wenn Du dieses Gerät entfernst, müssen eingehende Übertragungen von diesem Gerät manuell akzeptiert werden." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "If you remove this device, incoming transfers from this device have to be accepted manually." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si eliminas este dispositivo, las transferencias entrantes de este dispositivo deberán aceptarse manualmente." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si vous retirez cet appareil, les transferts entrants devront être acceptés manuellement." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ha eltávolítja ezt az eszközt, az erről az eszközről érkező átviteleket manuálisan kell elfogadni." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se rimuovi questo dispositivo, i trasferimenti in arrivo da questo dispositivo dovranno essere accettati manualmente." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "このデバイスを削除すると、このデバイスからの受信転送は手動で受け入れる必要があります。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "이 기기를 제거하면, 이 기기에서 오는 전송은 수동으로 승인이 필요합니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Als u dit apparaat verwijdert, moeten binnenkomende overdrachten van dit apparaat handmatig worden geaccepteerd." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se você remover este dispositivo, transferências recebidas dele precisarão ser aceitas manualmente." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Se remover este dispositivo, as transferências recebidas deste dispositivo terão de ser aceites manualmente." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dacă elimini acest dispozitiv, transferurile primite de la acest dispozitiv trebuie acceptate manual." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Если вы удалите это устройство, входящие передачи с этого устройства придется принимать вручную." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "หากคุณลบอุปกรณ์นี้ การรับโอนย้ายข้อมูลจากอุปกรณ์นี้ต้องได้รับการยืนยันด้วยตนเอง" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Якщо ви видалите цей пристрій, вхідні передачі з цього пристрою доведеться приймати вручну." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "如果您移除此设备,此设备的传入传输必须手动接受。" + } + } + } + }, + "RemoveTrustedDeviceAlertTitle" : { + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "إزالة الجهاز الموثوق؟" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vertrauenswürdiges Gerät entfernen?" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove trusted device?" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Eliminar dispositivo de confianza?" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Supprimer l'appareil de confiance ?" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Megbízható eszköz eltávolítása?" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rimuovere il dispositivo attendibile?" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "信頼できるデバイスを削除しますか?" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "신뢰할 수 있는 기기를 제거하시겠습니까?" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vertrouwd apparaat verwijderen?" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remover dispositivo confiável?" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remover dispositivo confiável?" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ștergeți dispozitivul de încredere?" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Удалить доверенное устройство?" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "ลบอุปกรณ์ที่เชื่อถือได้หรือไม่?" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Видалити довірений пристрій?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "移除受信任的设备?" + } + } + } + }, "Reset UD" : { "localizations" : { "ar" : { @@ -10264,6 +12180,220 @@ } } }, + "TrustedDevices" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "الأجهزة الموثوقة" + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vertrauensw. Geräte" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Trusted Devices" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dispositivos de confianza" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appareils de confiance" + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Megbízható eszközök" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dispositivi attendibili" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "信頼できるデバイス" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "신뢰할 수 있는 기기" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vertrouwde apparaten" + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dispositivos Confiáveis" + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dispositivos Confiáveis" + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dispozitive de încredere" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Доверенные устройства" + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "อุปกรณ์ที่เชื่อถือได้" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Довірені пристрої" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "受信任的设备" + } + } + } + }, + "TrustedDevicesDescription" : { + "extractionState" : "manual", + "localizations" : { + "ar" : { + "stringUnit" : { + "state" : "translated", + "value" : "عند الوثوق بجهاز، سيظهر هنا. سيتم قبول النقل الوارد تلقائيًا مع الأجهزة الموثوق بها. لا تزال العمليات مُشفّرة من الطرف إلى الطرف وتستخدم السرية الأمامية المثالية (PFS)." + } + }, + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wenn Du einem Gerät vertraust, wird es hier angezeigt. Bei vertrauenswürdigen Geräten werden eingehende Übertragungen automatisch akzeptiert. Übertragungen sind weiterhin Ende-zu-Ende-verschlüsselt und verwenden Perfect Forward Secrecy (PFS)." + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "When you trust a device, it will appear here. With trusted devices, incoming transfers will be accepted automatically. Transmissions are still end-to-end encrypted and use Perfect Forward Secrecy (PFS)." + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cuando confíes en un dispositivo, aparecerá aquí. Con dispositivos de confianza, las transferencias entrantes se aceptarán automáticamente. Las transmisiones siguen estando cifradas de extremo a extremo y utilizan Perfect Forward Secrecy (PFS)." + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lorsque vous faites confiance à un appareil, il apparaîtra ici. Avec les appareils de confiance, les transferts entrants seront acceptés automatiquement. Les transmissions restent cryptées de bout en bout et utilisent le Secret de Transfert Parfait (PFS)." + } + }, + "hu" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ha egy eszközben megbízik, az itt fog megjelenni. A megbízható eszközökkel az érkező átvitelek automatikusan elfogadásra kerülnek. Az átvitelek továbbra is végponttól végpontig titkosítottak, és a tökéletes előremenő titkosítást (PFS) használják." + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quando autorizzi un dispositivo, apparirà qui. Con i dispositivi autorizzati, i trasferimenti in arrivo saranno accettati automaticamente. Le trasmissioni sono comunque crittografate end-to-end e utilizzano la Segretezza Perfetta a Termine (PFS)." + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "デバイスを信頼すると、ここに表示されます。信頼されたデバイスでは、受信転送が自動的に承認されます。送信は依然としてエンドツーエンドで暗号化され、完全前方秘匿性(PFS)が使用されます。" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "기기를 신뢰하면 여기에 표시됩니다. 신뢰하는 기기의 경우, 들어오는 전송이 자동으로 수락됩니다. 전송은 여전히 종단 간 암호화가 적용되며 완벽한 순방향 보안을 사용합니다." + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wanneer je een apparaat vertrouwt, verschijnt het hier. Bij vertrouwde apparaten worden inkomende overdrachten automatisch geaccepteerd. Overdrachten blijven end-to-end versleuteld en maken gebruik van Perfect Forward Secrecy (PFS)." + } + }, + "pt-BR" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quando você confia em um dispositivo, ele aparecerá aqui. Com dispositivos confiáveis, as transferências recebidas serão aceitas automaticamente. As transmissões ainda são criptografadas de ponta a ponta e utilizam o Perfect Forward Secrecy (PFS)." + } + }, + "pt-PT" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quando confia num dispositivo, este aparecerá aqui. Com dispositivos de confiança, as transferências recebidas serão aceites automaticamente. As transmissões continuam a ser encriptadas de ponta a ponta e utilizam Sigilo de Transmissão Perfeito (PFS)." + } + }, + "ro" : { + "stringUnit" : { + "state" : "translated", + "value" : "Când aveți încredere într-un dispozitiv, acesta va apărea aici. Cu dispozitive de încredere, transferurile primite vor fi acceptate automat. Transmisiunile sunt în continuare criptate de la un capăt la altul și utilizează Perfect Forward Secrecy (PFS)." + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Когда вы доверяете устройству, оно появится здесь. Для доверенных устройств входящие передачи будут приниматься автоматически. Передача данных по-прежнему зашифрована от конца до конца и использует Perfect Forward Secrecy (PFS)." + } + }, + "th" : { + "stringUnit" : { + "state" : "translated", + "value" : "เมื่อคุณไว้วางใจอุปกรณ์ อุปกรณ์จะปรากฏที่นี่ ด้วยอุปกรณ์ที่ไว้วางใจ การรับส่งไฟล์ที่เข้ามาจะถูกยอมรับโดยอัตโนมัติ การส่งข้อมูลยังคงถูกเข้ารหัสแบบปลายทางถึงปลายทางและใช้ความลับส่งต่อสมบูรณ์แบบ (PFS)" + } + }, + "uk" : { + "stringUnit" : { + "state" : "translated", + "value" : "Коли ви довіряєте пристрою, він з'явиться тут. Для довірених пристроїв вхідні передачі прийматимуться автоматично. Передача даних все ж залишатиметься повністю зашифрованою (end-to-end) і використовуватиме досконалу пряму секретність (PFS)." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "当您信任一台设备时,它会显示在这里。对于受信任的设备,传入的传输会被自动接受。传输仍然是端到端加密的,并使用完美前向保密(PFS)。" + } + } + } + }, "TypeNotSupported" : { "extractionState" : "manual", "localizations" : { @@ -11440,1388 +13570,6 @@ } } } - }, - "plusview_description" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "قم بفتح QuickDrop+ لمواصلة تبادل الملفات بلا حدود. QuickDrop+ هو شراء لمرة واحدة – لا حاجة للاشتراك. تشمل جميع الميزات الحالية والمستقبلية." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Schalte QuickDrop+ frei, um weiterhin Dateien unbegrenzt auszutauschen. QuickDrop+ ist ein Einmalkauf - ein Abonnement ist nicht erforderlich. Alle aktuellen und zukünftigen Funktionen sind enthalten." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unlock QuickDrop+ to continue exchanging files without limits. QuickDrop+ is a one-time purchase – no subscription required. All current and future features are included." - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Desbloquea QuickDrop+ para seguir intercambiando archivos sin límites. QuickDrop+ es una compra única – no se requiere suscripción. Todas las funciones actuales y futuras están incluidas." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Débloquez QuickDrop+ pour continuer à échanger des fichiers sans limites. QuickDrop+ est un achat unique – aucun abonnement requis. Toutes les fonctionnalités actuelles et futures sont incluses." - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Oldd fel a QuickDrop+-t, hogy korlátlanul folytathasd a fájlcserét. A QuickDrop+ egy egyszeri vásárlás – előfizetés nem szükséges. Az összes jelenlegi és jövőbeli funkciót tartalmazza." - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sblocca QuickDrop+ per continuare a scambiare file senza limiti. QuickDrop+ è un acquisto unico – nessun abbonamento richiesto. Tutte le funzionalità attuali e future sono incluse." - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDrop+ をアンロックして、無制限にファイルを交換できます。QuickDrop+ は買い切り型のアプリです。サブスクリプション不要で、現在および将来のすべての機能が含まれます。" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDrop+를 잠금 해제하여 파일을 제한 없이 교환하세요. QuickDrop+는 일회성 구매이며, 구독이 필요하지 않습니다. 모든 현재 및 미래 기능이 포함됩니다." - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ontgrendel QuickDrop+ om bestanden zonder limieten te blijven uitwisselen. QuickDrop+ is een eenmalige aankoop – geen abonnement vereist. Alle huidige en toekomstige functies zijn inbegrepen." - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Desbloqueie o QuickDrop+ para continuar trocando arquivos sem limites. QuickDrop+ é uma compra única – sem necessidade de assinatura. Todos os recursos atuais e futuros estão incluídos." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Desbloqueia o QuickDrop+ para continuar a trocar ficheiros sem limites. QuickDrop+ é uma compra única – não é necessária subscrição. Todas as funcionalidades atuais e futuras estão incluídas." - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deblochează QuickDrop+ pentru a continua schimbul de fișiere fără limite. QuickDrop+ este o achiziție unică – nu este necesar abonament. Toate funcțiile curente și viitoare sunt incluse." - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разблокируйте QuickDrop+, чтобы продолжить обмен файлами без ограничений. QuickDrop+ – это разовая покупка, подписка не требуется. Все текущие и будущие функции включены." - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ปลดล็อก QuickDrop+ เพื่อแลกเปลี่ยนไฟล์ได้อย่างไม่จำกัด QuickDrop+ เป็นการซื้อครั้งเดียว – ไม่ต้องสมัครสมาชิก ฟีเจอร์ทั้งหมดทั้งปัจจุบันและอนาคตรวมอยู่ในนี้แล้ว" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Розблокуйте QuickDrop+, щоб продовжити обмін файлами без обмежень. QuickDrop+ – це одноразова покупка, підписка не потрібна. Всі поточні та майбутні функції включені." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "解锁 QuickDrop+ 以无限制地交换文件。QuickDrop+ 是一次性购买 – 无需订阅。所有当前和未来的功能均包含在内。" - } - } - } - }, - "plusview_nothingtorestore" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "لا يوجد شيء لاستعادته!" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Es gibt nichts wiederherzustellen!" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "There is nothing to restore!" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "¡No hay nada que restaurar!" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aucun achat à restaurer !" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nincs visszaállítható vásárlás!" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Non c'è nulla da ripristinare!" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "復元するものがありません!" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "복원할 항목이 없습니다!" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Er is niets om te herstellen!" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nada para restaurar!" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Não há nada para restaurar!" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nu există nimic de restaurat!" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нет покупок для восстановления!" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ไม่มีรายการที่ต้องกู้คืน!" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Немає покупок для відновлення!" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "没有可恢复的购买!" - } - } - } - }, - "plusview_productRequestFailed" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "تعذر جلب عمليات الشراء داخل التطبيق في الوقت الحالي." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "In-App-Käufe können momentan nicht abgerufen werden." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unable to fetch In-App Purchases at the moment." - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "No se pueden recuperar las compras dentro de la aplicación en este momento." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Impossible de récupérer les achats intégrés pour le moment." - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Jelenleg nem lehet lekérni az alkalmazáson belüli vásárlásokat." - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Impossibile recuperare gli acquisti in-app al momento." - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "現在、アプリ内購入情報を取得できません。" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "현재 인앱 구매 정보를 가져올 수 없습니다." - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "In-app aankopen kunnen momenteel niet worden opgehaald." - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Não foi possível recuperar as compras dentro do aplicativo no momento." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Não foi possível recuperar as compras dentro do app no momento." - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Momentan, nu se pot obține informații despre achizițiile în aplicație." - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Не удалось получить данные о встроенных покупках." - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ไม่สามารถดึงข้อมูลการซื้อภายในแอปได้ในขณะนี้" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Наразі неможливо отримати інформацію про покупки в додатку." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "暂时无法获取应用内购买信息。" - } - } - } - }, - "plusview_purchasefailed" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "فشل الشراء" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kauf fehlgeschlagen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Purchase failed" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "La compra ha fallado" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Échec de l'achat" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "A vásárlás sikertelen" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Acquisto non riuscito" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "購入に失敗しました" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "구매 실패" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aankoop mislukt" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Falha na compra" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Falha na compra" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Achiziția a eșuat" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ошибка покупки" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "การซื้อล้มเหลว" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Помилка покупки" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "购买失败" - } - } - } - }, - "plusview_purchasefaileddescription" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "إذا ظهر هذا الرسالة بشكل غير متوقع، يرجى التأكد من اتصالك بالإنترنت وأن عمليات الشراء داخل التطبيق مفعّلة على جهازك، ثم حاول مرة أخرى." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Falls diese Nachricht unerwartet erscheint, stelle sicher, dass du mit dem Internet verbunden bist und In-App-Käufe auf deinem Gerät aktiviert sind, und versuche es erneut." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "If this message appeared unexpectedly, please make sure that you are connected to the Internet and In-App-Purchases are enabled for your device and then try again." - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Si este mensaje apareció inesperadamente, asegúrate de estar conectado a internet y que las compras dentro de la aplicación estén habilitadas en tu dispositivo, luego intenta nuevamente." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Si ce message est apparu de manière inattendue, assurez-vous d'être connecté à Internet et que les achats intégrés sont activés sur votre appareil, puis réessayez." - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ha ez az üzenet váratlanul jelent meg, ellenőrizd az internetkapcsolatot, és győződj meg róla, hogy az alkalmazáson belüli vásárlások engedélyezve vannak az eszközödön, majd próbáld újra." - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Se questo messaggio è apparso inaspettatamente, assicurati di essere connesso a Internet e che gli acquisti in-app siano abilitati sul tuo dispositivo, quindi riprova." - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "このメッセージが予期せず表示された場合、インターネット接続を確認し、アプリ内購入が有効になっていることを確認した上で再試行してください。" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "이 메시지가 예상치 않게 나타난 경우, 인터넷에 연결되어 있는지 확인하고 기기에서 인앱 결제가 활성화되어 있는지 확인한 후 다시 시도해 주세요." - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Als dit bericht onverwachts verschijnt, controleer dan of je verbonden bent met internet en of in-app aankopen zijn ingeschakeld op je apparaat, en probeer het opnieuw." - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Se esta mensagem apareceu inesperadamente, verifique se você está conectado à internet e se as compras dentro do app estão ativadas no seu dispositivo e tente novamente." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Se esta mensagem apareceu inesperadamente, certifique-se de estar conectado à Internet e que as compras dentro do app estejam ativadas no seu dispositivo, depois tente novamente." - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dacă acest mesaj a apărut neașteptat, asigură-te că ești conectat la internet și că achizițiile în aplicație sunt activate pe dispozitivul tău, apoi încearcă din nou." - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Если это сообщение появилось неожиданно, убедитесь, что у вас есть доступ к интернету и включены встроенные покупки на вашем устройстве, затем попробуйте снова." - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "หากข้อความนี้ปรากฏขึ้นโดยไม่คาดคิด โปรดตรวจสอบว่าคุณเชื่อมต่ออินเทอร์เน็ตและเปิดใช้งานการซื้อภายในแอปในอุปกรณ์ของคุณแล้วลองอีกครั้ง" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Якщо це повідомлення з’явилося несподівано, переконайтеся, що у вас є підключення до Інтернету, а покупки в додатках увімкнені на вашому пристрої, і спробуйте ще раз." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "如果此消息意外出现,请确保您已连接到互联网,并且设备已启用应用内购买功能,然后重试。" - } - } - } - }, - "plusview_restorefailed" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "حدثت مشكلة أثناء استعادة عملية الشراء" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Es gab ein Problem beim Wiederherstellen deines Kaufs" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "There was a problem restoring your purchase" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hubo un problema al restaurar tu compra" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Un problème est survenu lors de la restauration de votre achat" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hiba történt a vásárlás visszaállítása során" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Si è verificato un problema durante il ripristino dell'acquisto" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "購入の復元中に問題が発生しました" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "구매 복원 중 문제가 발생했습니다." - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Er was een probleem bij het herstellen van je aankoop" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Houve um problema ao restaurar sua compra" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Houve um problema ao restaurar sua compra" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "A apărut o problemă la restaurarea achiziției" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Произошла ошибка при восстановлении покупки" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "เกิดปัญหาในการกู้คืนการซื้อของคุณ" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сталася помилка під час відновлення покупки" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "恢复购买时出现问题" - } - } - } - }, - "plusview_restorefailed_proceed" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "موافق" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Okay" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Okay" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aceptar" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rendben" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ok" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "확인" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Oké" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ok" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Окей" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ตกลง" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Гаразд" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "确定" - } - } - } - }, - "plusview_restorepurchase" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "هل اشتريته بالفعل؟" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bereits gekauft?" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Already bought?" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "¿Ya lo compraste?" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Déjà acheté ?" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Már megvásároltad?" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Già acquistato?" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "すでに購入済みですか?" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "이미 구매하셨나요?" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Al gekocht?" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Já comprou?" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Já comprou?" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deja cumpărat?" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Уже куплено?" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "เคยซื้อแล้ว?" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Вже куплено?" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "已购买?" - } - } - } - }, - "plusview_success_button" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "حسنًا!" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alles klar!" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Got it!" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "¡Entendido!" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "D'accord !" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Értettem!" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Capito!" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "了解!" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "알겠습니다!" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Begrepen!" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Entendi!" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Entendido!" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Înțeles!" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Понял!" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "รับทราบ!" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зрозуміло!" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "知道了!" - } - } - } - }, - "plusview_success_description" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "يمكنك الآن متابعة استلام الملفات بدون قيود. أي ملفات حاولت إرسالها سابقًا تم حفظها بالفعل على جهازك." - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Du kannst nun weiterhin Dateien ohne Einschränkungen empfangen. Alle Dateien, welche gerade gesendet wurden, wurden bereits gespeichert." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "You can now continue receiving files without restrictions. Any files you tried to send were already saved on your device." - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ahora puedes seguir recibiendo archivos sin restricciones. Todos los archivos que intentaste enviar antes ya se han guardado en tu dispositivo." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Vous pouvez maintenant continuer à recevoir des fichiers sans restrictions. Tous les fichiers que vous avez essayé d'envoyer précédemment ont déjà été enregistrés sur votre appareil." - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mostantól korlátozások nélkül fogadhat fájlokat. Az összes fájl, amelyet korábban próbált elküldeni, már el lett mentve az eszközére." - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ora puoi continuare a ricevere file senza restrizioni. Tutti i file che hai provato a inviare in precedenza sono già stati salvati sul tuo dispositivo." - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "これで、制限なくファイルを受信し続けることができます。以前送信しようとしたファイルはすでにデバイスに保存されています。" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "이제 파일을 제한 없이 계속 받을 수 있습니다. 이전에 전송을 시도한 모든 파일이 이미 기기에 저장되었습니다." - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Je kunt nu bestanden blijven ontvangen zonder beperkingen. Alle bestanden die je eerder probeerde te verzenden, zijn al opgeslagen op je apparaat." - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agora você pode continuar recebendo arquivos sem restrições. Todos os arquivos que você tentou enviar antes já foram salvos no seu dispositivo." - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Agora pode continuar a receber ficheiros sem restrições. Todos os ficheiros que tentou enviar antes já foram guardados no seu dispositivo." - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Acum puteți continua să primiți fișiere fără restricții. Toate fișierele pe care ați încercat să le trimiteți anterior au fost deja salvate pe dispozitivul dvs." - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Теперь вы можете продолжать получать файлы без ограничений. Все файлы, которые вы пытались отправить ранее, уже сохранены на вашем устройстве." - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "คุณสามารถรับไฟล์ต่อไปได้โดยไม่มีข้อจำกัด ไฟล์ทั้งหมดที่คุณพยายามส่งก่อนหน้านี้ถูกบันทึกไว้ในอุปกรณ์ของคุณแล้ว" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Тепер ви можете продовжувати отримувати файли без обмежень. Усі файли, які ви намагалися надіслати раніше, вже збережено на вашому пристрої." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "您现在可以继续无限制地接收文件。您之前尝试发送的所有文件已保存到您的设备上。" - } - } - } - }, - "plusview_success_title" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "شكرًا لشرائك!" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Danke für deinen Kauf!" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Thanks for your purchase!" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "¡Gracias por tu compra!" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Merci pour votre achat !" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Köszönjük a vásárlást!" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grazie per il tuo acquisto!" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "ご購入ありがとうございます!" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "구매해 주셔서 감사합니다!" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bedankt voor je aankoop!" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Obrigado pela sua compra!" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Obrigado pela sua compra!" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mulțumim pentru achiziție!" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Спасибо за покупку!" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ขอบคุณสำหรับการซื้อ!" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дякуємо за покупку!" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "感谢您的购买!" - } - } - } - }, - "plusview_title" : { - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "شكرًا لاستخدامك QuickDrop!" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Danke, dass du QuickDrop benutzt!" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Thanks for using QuickDrop!" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "¡Gracias por usar QuickDrop!" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Merci d'utiliser QuickDrop !" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Köszönjük, hogy használod a QuickDropot!" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grazie per aver usato QuickDrop!" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDropをご利用いただきありがとうございます!" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDrop을 사용해 주셔서 감사합니다!" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bedankt voor het gebruiken van QuickDrop!" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Obrigado por usar o QuickDrop!" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Obrigado por usar o QuickDrop!" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mulțumim că folosești QuickDrop!" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Спасибо за использование QuickDrop!" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "ขอบคุณที่ใช้ QuickDrop!" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дякуємо за використання QuickDrop!" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "感谢使用 QuickDrop!" - } - } - } - }, - "plusview_unlock_label" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "ادعم QuickDrop" - } - }, - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unterstütze QuickDrop" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Support QuickDrop" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apoyar QuickDrop" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Soutenir QuickDrop" - } - }, - "hu" : { - "stringUnit" : { - "state" : "translated", - "value" : "Támogasd a QuickDropot" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Supporta QuickDrop" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDropをサポート" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "QuickDrop 지원하기" - } - }, - "nl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ondersteun QuickDrop" - } - }, - "pt-BR" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apoie o QuickDrop" - } - }, - "pt-PT" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apoiar QuickDrop" - } - }, - "ro" : { - "stringUnit" : { - "state" : "translated", - "value" : "Susține QuickDrop" - } - }, - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Поддержать QuickDrop" - } - }, - "th" : { - "stringUnit" : { - "state" : "translated", - "value" : "สนับสนุน QuickDrop" - } - }, - "uk" : { - "stringUnit" : { - "state" : "translated", - "value" : "Підтримати QuickDrop" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "支持 QuickDrop" - } - } - } } }, "version" : "1.0" diff --git a/QuickDrop/View/SettingsView.swift b/QuickDrop/View/SettingsView.swift index 86471a6..a7b0fc9 100644 --- a/QuickDrop/View/SettingsView.swift +++ b/QuickDrop/View/SettingsView.swift @@ -45,21 +45,27 @@ struct SettingsView: View { Toggle("OpenFinderAfterReceiving", isOn: $openFinderAfterReceiving) .padding(.top, 5) - Text("OpenFinderAfterReceivingFooter") - .font(.footnote) - .padding(.top, 5) - - if #available(macOS 13.0, *) { - - Divider() - .padding(.vertical, 10) - LaunchAtLogin.Toggle { Text("LaunchAtLogin") } .padding(.top, 5) } + + Divider() + .padding(.vertical, 10) + + Button { + openTrustedDevicesWindow() + } label: { + Text("ManageTrustedDevices") + .underline() + .font(.subheadline) + .opacity(0.5) + .frame(maxWidth: .infinity) + .padding(.vertical, 15) + } + .buttonStyle(PlainButtonStyle()) } } } @@ -98,8 +104,27 @@ struct SettingsView: View { } } } + + + private func openTrustedDevicesWindow() { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 600, height: 400), + styleMask: [.titled, .closable, .resizable], + backing: .buffered, + defer: false + ) + window.center() + window.isReleasedWhenClosed = false + window.title = "TrustedDevices".localized() + window.contentView = NSHostingView(rootView: TrustedDevicesView()) + + NSApp.activate(ignoringOtherApps: true) + window.makeKeyAndOrderFront(nil) + window.level = .normal + } } + struct SettingsView_Previews: PreviewProvider { static var previews: some View { SettingsView() diff --git a/QuickDrop/View/TrustedDevicesView.swift b/QuickDrop/View/TrustedDevicesView.swift new file mode 100644 index 0000000..592d02a --- /dev/null +++ b/QuickDrop/View/TrustedDevicesView.swift @@ -0,0 +1,125 @@ +// +// TrustedDevicesView.swift +// QuickDrop +// +// Created by Leon Böttger on 23.08.25. +// + +import SwiftUI +#if !os(macOS) +import LUI +#endif + +struct TrustedDevicesView: View { + @StateObject private var store = TrustStore.shared + + @State private var deviceToRemove: String? = nil + @State private var showRemoveAlert = false + + var body: some View { + VStack { + if store.trustedCertificates.isEmpty { + VStack(spacing: 12) { + Text("NoTrustedDevices") + .font(.headline) + .foregroundColor(.secondary) + Text("TrustedDevicesDescription") + .font(.subheadline) + .foregroundColor(.secondary) + } + .multilineTextAlignment(.center) + .padding() + .frame(maxHeight: .infinity) + } else { + + #if !os(macOS) + CustomSection(footer: "TrustedDevicesDescription") { + devicesView + .padding(.vertical, 4) + } + #else + List { + devicesView + + Text("TrustedDevicesDescription") + .font(.footnote) + .fixedSize(horizontal: false, vertical: true) + .foregroundColor(.secondary) + .padding(.top, 4) + } + #endif + } + } + .animation(.default, value: store.trustedCertificates) + .alert(isPresented: $showRemoveAlert) { + Alert( + title: Text("RemoveTrustedDeviceAlertTitle"), + message: Text("RemoveTrustedDeviceAlertDescription"), + primaryButton: .destructive(Text("Remove")) { + if let key = deviceToRemove { + store.removeTrusted(secretIdHex: key) + } + }, + secondaryButton: .cancel() + ) + } + } + + + var devicesView: some View { + ForEach(Array(store.trustedCertificates.keys), id: \.self) { key in + if let cert = store.trustedCertificates[key] { + HStack { + VStack(alignment: .leading, spacing: 4) { + Text(cert.device.name ?? "Unknown".localized()) + .font(.headline) + + // macOS 11: use DateFormatter instead of .formatted + Text(Self.dateFormatter.string(from: cert.creationDate)) + .font(.subheadline) + .foregroundColor(.secondary) + } + Spacer() + Button(action: { + deviceToRemove = key + showRemoveAlert = true + }) { + Image(systemName: "minus.circle.fill") + .font(.system(size: 20)) + .foregroundColor(.red) + } + .buttonStyle(BorderlessButtonStyle()) + } + .padding(.vertical, 8) + } + } + } + + + // MARK: - DateFormatter for macOS 11 + private static let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeStyle = .short + return formatter + }() +} + + +#Preview { + TrustedDevicesView() + .onAppear { + + var cert1 = Sharing_Nearby_PublicCertificate() + cert1.secretID = Data([0x01, 0x02, 0x03, 0x04]) + + TrustStore.shared.addTrusted(certificate: cert1, device: RemoteDeviceInfo(name: "MacBook Pro", type: .computer)) + + + var cert2 = Sharing_Nearby_PublicCertificate() + cert2.secretID = Data([0x0A, 0x0B, 0x0C, 0x0D]) + + TrustStore.shared.addTrusted(certificate: cert2, device: RemoteDeviceInfo(name: "iPhone", type: .phone)) + + } +} diff --git a/QuickDropiOS/ContentView.swift b/QuickDropiOS/ContentView.swift index 9578051..430ba5f 100644 --- a/QuickDropiOS/ContentView.swift +++ b/QuickDropiOS/ContentView.swift @@ -24,6 +24,12 @@ struct ContentView: View { } label: { NavigationLinkLabel(imageName: "folder.fill", text: "BrowseDownloadedFiles") } + + LUILink(destination: NavigationSubView(header: "TrustedDevices") { + TrustedDevicesView() + }) { + NavigationLinkLabel(imageName: "checkmark.shield.fill", text: "ManageTrustedDevices", backgroundColor: .green) + } } }) } diff --git a/QuickDropiOS/ReceiveModel.swift b/QuickDropiOS/ReceiveModel.swift index 2cb13b5..70cfb39 100644 --- a/QuickDropiOS/ReceiveModel.swift +++ b/QuickDropiOS/ReceiveModel.swift @@ -61,8 +61,15 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { let pinCodeMessage = String(format: "PinCode".localized(), arguments: [transfer.pinCode ?? "?"]) let transferID = transfer.id + + #if os(macOS) + let isMac = true + #else + let isMac = false + #endif + - if acceptAutomatically && isMac() { + if acceptAutomatically && isMac { pressAcceptButton(transferID: transfer.id, trustDevice: false) UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, _ in