From 3301ee7034ffdb786aa3337a6694c44c331c0972 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:22:25 -0500 Subject: [PATCH 01/20] Add InstanceCommandStatus model for Activity tasks --- Ruddarr/Models/Commands/CommandStatus.swift | 91 +++++++++++++++++++++ Tests/CommandsTests.swift | 68 +++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 Ruddarr/Models/Commands/CommandStatus.swift create mode 100644 Tests/CommandsTests.swift diff --git a/Ruddarr/Models/Commands/CommandStatus.swift b/Ruddarr/Models/Commands/CommandStatus.swift new file mode 100644 index 00000000..ac75de8b --- /dev/null +++ b/Ruddarr/Models/Commands/CommandStatus.swift @@ -0,0 +1,91 @@ +import Foundation + +struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { + let id: Int + let name: String + let commandName: String? + var message: String? + var status: String + var result: String? + let queued: Date + var started: Date? + var ended: Date? + let trigger: String? + + /// Stamped client-side after decoding so we can group + filter per instance. + var instanceId: Instance.ID? + + /// Stamped client-side at dispatch time with a human-readable subject + /// (e.g. "Breaking Bad — Season 2") so the list row can show something + /// richer than the raw command name. + var subject: String? + + enum CodingKeys: String, CodingKey { + case id, name, commandName, message, status, result + case queued, started, ended, trigger + } + + var state: CommandStatusState { + CommandStatusState(rawValue: status) ?? .unknown + } + + var isTerminal: Bool { + switch state { + case .completed, .failed, .aborted, .cancelled, .orphaned: + return true + case .queued, .started, .unknown: + return false + } + } + + var isSearchCommand: Bool { + Self.searchCommandNames.contains(name) + } + + static let searchCommandNames: Set = [ + "MoviesSearch", + "SeriesSearch", + "SeasonSearch", + "EpisodeSearch", + ] + + /// Sort key: most recent first. Uses `started` if available, otherwise `queued`. + var sortDate: Date { + started ?? queued + } +} + +enum CommandStatusState: String, Codable { + case queued + case started + case completed + case failed + case aborted + case cancelled + case orphaned + case unknown + + var label: String { + switch self { + case .queued: String(localized: "Queued", comment: "Command status") + case .started: String(localized: "Running", comment: "Command status") + case .completed: String(localized: "Completed", comment: "Command status") + case .failed: String(localized: "Failed", comment: "Command status") + case .aborted: String(localized: "Aborted", comment: "Command status") + case .cancelled: String(localized: "Cancelled", comment: "Command status") + case .orphaned: String(localized: "Orphaned", comment: "Command status") + case .unknown: String(localized: "Unknown", comment: "Command status") + } + } + + var systemImage: String { + switch self { + case .queued: "clock" + case .started: "arrow.triangle.2.circlepath" + case .completed: "checkmark.circle" + case .failed, .aborted, .orphaned: "exclamationmark.triangle" + case .cancelled: "xmark.circle" + case .unknown: "questionmark.circle" + } + } +} diff --git a/Tests/CommandsTests.swift b/Tests/CommandsTests.swift new file mode 100644 index 00000000..79570cac --- /dev/null +++ b/Tests/CommandsTests.swift @@ -0,0 +1,68 @@ +import Testing +import Foundation +@testable import Ruddarr + +struct CommandsTests { + @Test func decodesCompletedSeriesSearch() throws { + let json = """ + { + "id": 42, + "name": "SeriesSearch", + "commandName": "Series Search", + "message": "Completed", + "status": "completed", + "result": "successful", + "queued": "2026-04-05T10:15:00Z", + "started": "2026-04-05T10:15:01Z", + "ended": "2026-04-05T10:15:04Z", + "trigger": "manual" + } + """.data(using: .utf8)! + + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + + let status = try decoder.decode(InstanceCommandStatus.self, from: json) + + #expect(status.id == 42) + #expect(status.name == "SeriesSearch") + #expect(status.state == .completed) + #expect(status.message == "Completed") + #expect(status.isSearchCommand == true) + #expect(status.isTerminal == true) + } + + @Test func decodesQueuedCommandWithoutEndedDate() throws { + let json = """ + { + "id": 7, + "name": "MoviesSearch", + "status": "queued", + "queued": "2026-04-05T10:00:00Z", + "trigger": "manual" + } + """.data(using: .utf8)! + + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + + let status = try decoder.decode(InstanceCommandStatus.self, from: json) + + #expect(status.state == .queued) + #expect(status.ended == nil) + #expect(status.isTerminal == false) + } + + @Test func unknownStateFallsBack() throws { + let json = """ + { "id": 1, "name": "Foo", "status": "warp-driving", "queued": "2026-04-05T10:00:00Z" } + """.data(using: .utf8)! + + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + + let status = try decoder.decode(InstanceCommandStatus.self, from: json) + #expect(status.state == .unknown) + #expect(status.isSearchCommand == false) + } +} From 875a8d7030d88a682d264cd87d55e84a19d432de Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:28:50 -0500 Subject: [PATCH 02/20] Return command status from API layer --- Ruddarr/Dependencies/API/API+Live.swift | 21 ++++++++++++- Ruddarr/Dependencies/API/API+Mock.swift | 40 ++++++++++++++++++++++--- Ruddarr/Dependencies/API/API.swift | 4 ++- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/Ruddarr/Dependencies/API/API+Live.swift b/Ruddarr/Dependencies/API/API+Live.swift index 694c7553..10bc1193 100644 --- a/Ruddarr/Dependencies/API/API+Live.swift +++ b/Ruddarr/Dependencies/API/API+Live.swift @@ -220,7 +220,26 @@ extension API { let url = try instance.baseURL() .appending(path: "/api/v3/command") - return try await request(method: .post, url: url, headers: instance.auth, body: command.payload) + var status: InstanceCommandStatus = try await request( + method: .post, url: url, headers: instance.auth, body: command.payload + ) + status.instanceId = instance.id + return status + }, fetchCommand: { id, instance in + let url = try instance.baseURL() + .appending(path: "/api/v3/command") + .appending(path: String(id)) + + var status: InstanceCommandStatus = try await request(url: url, headers: instance.auth) + status.instanceId = instance.id + return status + }, fetchCommands: { instance in + let url = try instance.baseURL() + .appending(path: "/api/v3/command") + + var statuses: [InstanceCommandStatus] = try await request(url: url, headers: instance.auth) + for i in statuses.indices { statuses[i].instanceId = instance.id } + return statuses }, downloadRelease: { payload, instance in let url = try instance.baseURL() .appending(path: "/api/v3/release") diff --git a/Ruddarr/Dependencies/API/API+Mock.swift b/Ruddarr/Dependencies/API/API+Mock.swift index d2c13f27..7de7842c 100644 --- a/Ruddarr/Dependencies/API/API+Mock.swift +++ b/Ruddarr/Dependencies/API/API+Mock.swift @@ -124,10 +124,42 @@ extension API { let episodes: [Episode] = loadPreviewData(filename: "calendar-episodes") return modifyCalendarEpisodes(episodes, instance) - }, command: { _, _ in - try await Task.sleep(for: .seconds(2)) - - return Empty() + }, command: { cmd, instance in + var status = InstanceCommandStatus( + id: Int.random(in: 1...999), + name: cmd.payload.name, + commandName: nil, + message: "Queued", + status: "queued", + result: nil, + queued: Date(), + started: nil, + ended: nil, + trigger: "manual", + instanceId: nil, + subject: nil + ) + status.instanceId = instance.id + return status + }, fetchCommand: { id, instance in + var status = InstanceCommandStatus( + id: id, + name: "MoviesSearch", + commandName: nil, + message: "Completed", + status: "completed", + result: "successful", + queued: Date().addingTimeInterval(-10), + started: Date().addingTimeInterval(-9), + ended: Date().addingTimeInterval(-1), + trigger: "manual", + instanceId: nil, + subject: nil + ) + status.instanceId = instance.id + return status + }, fetchCommands: { _ in + [] }, downloadRelease: { _, _ in try await Task.sleep(for: .seconds(1)) diff --git a/Ruddarr/Dependencies/API/API.swift b/Ruddarr/Dependencies/API/API.swift index 34f5a4d7..9b3610b2 100644 --- a/Ruddarr/Dependencies/API/API.swift +++ b/Ruddarr/Dependencies/API/API.swift @@ -35,7 +35,9 @@ struct API { var movieCalendar: (Date, Date, Instance) async throws -> [Movie] var episodeCalendar: (Date, Date, Instance) async throws -> [Episode] - var command: (InstanceCommand, Instance) async throws -> Empty + var command: (InstanceCommand, Instance) async throws -> InstanceCommandStatus + var fetchCommand: (Int, Instance) async throws -> InstanceCommandStatus + var fetchCommands: (Instance) async throws -> [InstanceCommandStatus] var downloadRelease: (DownloadReleaseCommand, Instance) async throws -> Empty var systemStatus: (Instance) async throws -> InstanceStatus From 10c3e4f720dcd78ed813afb612b62e4210df7291 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:33:18 -0500 Subject: [PATCH 03/20] Return command status from Movies and SeriesModel --- Ruddarr/Models/Movies/Movies.swift | 23 +++++++++++++++++++++-- Ruddarr/Models/Series/SeriesModel.swift | 23 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Ruddarr/Models/Movies/Movies.swift b/Ruddarr/Models/Movies/Movies.swift index a74e4a8c..2178f49a 100644 --- a/Ruddarr/Models/Movies/Movies.swift +++ b/Ruddarr/Models/Movies/Movies.swift @@ -99,8 +99,27 @@ class Movies { await request(.download(guid, indexerId, movieId)) } - func command(_ command: InstanceCommand) async -> Bool { - await request(.command(command)) + func command(_ command: InstanceCommand) async -> InstanceCommandStatus? { + error = nil + isWorking = true + defer { isWorking = false } + + do { + return try await dependencies.api.command(command, instance) + } catch is CancellationError { + return nil + } catch let apiError as API.Error { + error = apiError + leaveBreadcrumb( + .error, category: "movies", + message: "Command failed", + data: ["command": command, "error": apiError] + ) + return nil + } catch { + self.error = API.Error(from: error) + return nil + } } func request(_ operation: Operation) async -> Bool { diff --git a/Ruddarr/Models/Series/SeriesModel.swift b/Ruddarr/Models/Series/SeriesModel.swift index 0ecd5cc3..d99491ed 100644 --- a/Ruddarr/Models/Series/SeriesModel.swift +++ b/Ruddarr/Models/Series/SeriesModel.swift @@ -108,8 +108,27 @@ class SeriesModel { await request(.download(guid, indexerId, seriesId, seasonId, episodeId)) } - func command(_ command: InstanceCommand) async -> Bool { - await request(.command(command)) + func command(_ command: InstanceCommand) async -> InstanceCommandStatus? { + error = nil + isWorking = true + defer { isWorking = false } + + do { + return try await dependencies.api.command(command, instance) + } catch is CancellationError { + return nil + } catch let apiError as API.Error { + error = apiError + leaveBreadcrumb( + .error, category: "series", + message: "Command failed", + data: ["command": command, "error": apiError] + ) + return nil + } catch { + self.error = API.Error(from: error) + return nil + } } func request(_ operation: Operation, silent: Bool = false) async -> Bool { From efa0b9572446a42e17d7ab20d597b57c922ded53 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:39:32 -0500 Subject: [PATCH 04/20] Add Commands observable store and merge tests --- Ruddarr/Models/Commands/Commands.swift | 122 +++++++++++++++++++++++++ Tests/CommandsTests.swift | 62 +++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 Ruddarr/Models/Commands/Commands.swift diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift new file mode 100644 index 00000000..71826c12 --- /dev/null +++ b/Ruddarr/Models/Commands/Commands.swift @@ -0,0 +1,122 @@ +import Foundation + +@MainActor +@Observable +final class Commands { + static let shared = Commands() + + private var timer: Timer? + + var error: API.Error? + var isLoading: Bool = false + var performRefresh: Bool = false + + var instances: [Instance] = [] + var items: [Instance.ID: [InstanceCommandStatus]] = [:] + + /// Max items to keep per instance. The instance also trims its own + /// history, but we cap locally so long-running sessions don't grow forever. + private let perInstanceLimit = 50 + + init() { + let interval: TimeInterval = isRunningIn(.preview) ? 30 : 5 + self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in + Task { @MainActor in + guard self.performRefresh else { return } + await self.refreshActive() + } + } + } + + /// Test-only factory that skips timer scheduling. + static func makeForTesting() -> Commands { + let c = Commands() + c.timer?.invalidate() + c.timer = nil + return c + } + + /// Called from `dispatchSearch` call sites immediately after a command POST + /// so the user sees the new row without waiting for the next poll. + func track(_ status: InstanceCommandStatus) { + guard let instanceId = status.instanceId else { return } + var list = items[instanceId] ?? [] + list.removeAll { $0.id == status.id } + list.insert(status, at: 0) + items[instanceId] = Array(list.prefix(perInstanceLimit)) + } + + /// Merges a fresh list of statuses fetched from the instance. Existing + /// entries are updated in place (preserving client-side `subject`), + /// unknown entries are inserted, and anything not seen since the last + /// `fetchAll` is left alone (the instance may have trimmed them). + func merge(_ incoming: [InstanceCommandStatus], for instanceId: Instance.ID) { + var existing = items[instanceId] ?? [] + let existingById = Dictionary(uniqueKeysWithValues: existing.map { ($0.id, $0) }) + + for var fresh in incoming { + if let prior = existingById[fresh.id], fresh.subject == nil { + fresh.subject = prior.subject + } + if let idx = existing.firstIndex(where: { $0.id == fresh.id }) { + existing[idx] = fresh + } else { + existing.append(fresh) + } + } + + existing.sort { $0.sortDate > $1.sortDate } + items[instanceId] = Array(existing.prefix(perInstanceLimit)) + } + + /// Initial population + pull-to-refresh. + func fetchAll() async { + guard !isLoading else { return } + error = nil + isLoading = true + + for instance in instances { + do { + let statuses = try await dependencies.api.fetchCommands(instance) + merge(statuses, for: instance.id) + } catch is CancellationError { + // ignore + } catch let apiError as API.Error { + error = apiError + leaveBreadcrumb(.error, category: "commands", message: "Fetch failed", data: ["error": apiError]) + } catch { + self.error = API.Error(from: error) + } + } + + isLoading = false + } + + /// Called by the polling timer. Only re-fetches commands that are still + /// non-terminal, to minimize API traffic. + func refreshActive() async { + for instance in instances { + guard let list = items[instance.id] else { continue } + let active = list.filter { !$0.isTerminal } + for command in active { + do { + let updated = try await dependencies.api.fetchCommand(command.id, instance) + merge([updated], for: instance.id) + } catch is CancellationError { + // ignore + } catch { + leaveBreadcrumb(.warning, category: "commands", message: "Poll failed", + data: ["id": command.id, "error": error]) + } + } + } + } + + /// Returns a flat, sorted list across all instances, respecting the + /// search-only default filter. + func filteredItems(showAll: Bool) -> [InstanceCommandStatus] { + let all = items.values.flatMap { $0 } + let filtered = showAll ? all : all.filter { $0.isSearchCommand } + return filtered.sorted { $0.sortDate > $1.sortDate } + } +} diff --git a/Tests/CommandsTests.swift b/Tests/CommandsTests.swift index 79570cac..2458e081 100644 --- a/Tests/CommandsTests.swift +++ b/Tests/CommandsTests.swift @@ -65,4 +65,66 @@ struct CommandsTests { #expect(status.state == .unknown) #expect(status.isSearchCommand == false) } + + @Test @MainActor func trackInsertsCommandAtFront() async { + let commands = Commands.makeForTesting() + let instanceId = UUID() + + let status = InstanceCommandStatus( + id: 1, name: "SeriesSearch", commandName: nil, message: nil, + status: "queued", result: nil, + queued: Date(), started: nil, ended: nil, trigger: "manual", + instanceId: instanceId, subject: "Breaking Bad" + ) + commands.track(status) + + #expect(commands.items[instanceId]?.count == 1) + #expect(commands.items[instanceId]?.first?.subject == "Breaking Bad") + } + + @Test @MainActor func mergeReplacesByIdAndKeepsSubject() async { + let commands = Commands.makeForTesting() + let instanceId = UUID() + + let queued = InstanceCommandStatus( + id: 9, name: "MoviesSearch", commandName: nil, message: nil, + status: "queued", result: nil, + queued: Date(), started: nil, ended: nil, trigger: "manual", + instanceId: instanceId, subject: "Inception" + ) + commands.track(queued) + + var completed = queued + completed.status = "completed" + completed.ended = Date() + completed.subject = nil // server won't know the subject + commands.merge([completed], for: instanceId) + + let stored = commands.items[instanceId]?.first + #expect(stored?.state == .completed) + #expect(stored?.subject == "Inception") // preserved from local track + } + + @Test @MainActor func defaultFilterKeepsOnlySearchCommands() async { + let commands = Commands.makeForTesting() + let instanceId = UUID() + + let search = InstanceCommandStatus( + id: 1, name: "SeriesSearch", commandName: nil, message: nil, + status: "queued", result: nil, + queued: Date(), started: nil, ended: nil, trigger: "manual", + instanceId: instanceId, subject: nil + ) + let rss = InstanceCommandStatus( + id: 2, name: "RssSync", commandName: nil, message: nil, + status: "queued", result: nil, + queued: Date(), started: nil, ended: nil, trigger: "scheduled", + instanceId: instanceId, subject: nil + ) + + commands.merge([search, rss], for: instanceId) + + #expect(commands.filteredItems(showAll: false).count == 1) + #expect(commands.filteredItems(showAll: true).count == 2) + } } From 8476a0cf24e6c18de7242c9eae49a05e4170eaec Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:46:54 -0500 Subject: [PATCH 05/20] Address Commands review: weak timer capture + safe merge dictionary --- Ruddarr/Models/Commands/Commands.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index 71826c12..e0889668 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -20,9 +20,9 @@ final class Commands { init() { let interval: TimeInterval = isRunningIn(.preview) ? 30 : 5 - self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in + self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in Task { @MainActor in - guard self.performRefresh else { return } + guard let self, self.performRefresh else { return } await self.refreshActive() } } @@ -52,7 +52,7 @@ final class Commands { /// `fetchAll` is left alone (the instance may have trimmed them). func merge(_ incoming: [InstanceCommandStatus], for instanceId: Instance.ID) { var existing = items[instanceId] ?? [] - let existingById = Dictionary(uniqueKeysWithValues: existing.map { ($0.id, $0) }) + let existingById = Dictionary(existing.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first }) for var fresh in incoming { if let prior = existingById[fresh.id], fresh.subject == nil { From 53545f903cb7043579fcfeb9824faa3309821090 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:49:06 -0500 Subject: [PATCH 06/20] Add Episode.subjectLabel helper for Activity tasks --- Ruddarr/Models/Series/Episode.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Ruddarr/Models/Series/Episode.swift b/Ruddarr/Models/Series/Episode.swift index 758a57b5..9024aa36 100644 --- a/Ruddarr/Models/Series/Episode.swift +++ b/Ruddarr/Models/Series/Episode.swift @@ -203,6 +203,19 @@ enum EpisodeReleaseType: String, Equatable, Codable { } } +extension Episode { + /// Formatted subject for Activity / Commands rows, e.g. "Breaking Bad — S1E3". + var subjectLabel: String { + let numbering = "S\(seasonNumber)E\(episodeNumber)" + + if let seriesTitle = series?.title, !seriesTitle.isEmpty { + return "\(seriesTitle) — \(numbering)" + } + + return String(localized: "Episode", comment: "Fallback episode subject") + } +} + extension Episode { static var void: Self { .init( From 5de7e62864bf00e593d37b5cb40b1b062de6c192 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:49:07 -0500 Subject: [PATCH 07/20] Add CommandListItem row view --- Ruddarr/Views/Activity/CommandListItem.swift | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Ruddarr/Views/Activity/CommandListItem.swift diff --git a/Ruddarr/Views/Activity/CommandListItem.swift b/Ruddarr/Views/Activity/CommandListItem.swift new file mode 100644 index 00000000..54731c61 --- /dev/null +++ b/Ruddarr/Views/Activity/CommandListItem.swift @@ -0,0 +1,64 @@ +import SwiftUI + +struct CommandListItem: View { + var command: InstanceCommandStatus + + @State private var now = Date() + private let timer = Timer.publish(every: 1, tolerance: 0.5, on: .main, in: .common).autoconnect() + + var body: some View { + VStack(alignment: .leading) { + Text(titleLabel) + .font(.headline.monospacedDigit()) + .fontWeight(.semibold) + .lineLimit(1) + .truncationMode(.middle) + + HStack(spacing: 6) { + Image(systemName: command.state.systemImage) + .imageScale(.small) + Text(command.state.label) + + if let subline { + Bullet() + Text(subline) + .monospacedDigit() + .id(now) + } + } + .font(.subheadline) + .foregroundStyle(.secondary) + .lineLimit(1) + } + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .onReceive(timer) { _ in + if command.state == .started || command.state == .queued { + withAnimation { now = Date() } + } + } + } + + private var titleLabel: String { + command.subject ?? command.commandName ?? command.name + } + + private var subline: String? { + switch command.state { + case .started, .queued: + let elapsed = now.timeIntervalSince(command.started ?? command.queued) + return formatElapsed(elapsed) + case .completed, .failed, .aborted, .cancelled, .orphaned, .unknown: + guard let ended = command.ended else { return nil } + return ended.formatted(.relative(presentation: .named)) + } + } + + private func formatElapsed(_ seconds: TimeInterval) -> String { + let s = max(0, Int(seconds)) + if s < 60 { return "\(s)s" } + let m = s / 60 + let r = s % 60 + return "\(m)m \(r)s" + } +} From be18f8708db44cc4e9332973b4d2f3a9a67c276a Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:49:08 -0500 Subject: [PATCH 08/20] Add CommandSheet detail view --- Ruddarr/Views/Activity/CommandSheet.swift | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Ruddarr/Views/Activity/CommandSheet.swift diff --git a/Ruddarr/Views/Activity/CommandSheet.swift b/Ruddarr/Views/Activity/CommandSheet.swift new file mode 100644 index 00000000..2a303526 --- /dev/null +++ b/Ruddarr/Views/Activity/CommandSheet.swift @@ -0,0 +1,87 @@ +import SwiftUI + +struct CommandSheet: View { + var command: InstanceCommandStatus + + @EnvironmentObject var settings: AppSettings + @Environment(\.dismiss) private var dismiss + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + header + Divider() + details + } + .padding() + .frame(maxWidth: .infinity, alignment: .leading) + } + } + + private var header: some View { + VStack(alignment: .leading, spacing: 4) { + Text(command.subject ?? command.commandName ?? command.name) + .font(.title3) + .fontWeight(.semibold) + + HStack(spacing: 6) { + Image(systemName: command.state.systemImage) + Text(command.state.label) + } + .font(.subheadline) + .foregroundStyle(stateTint) + } + } + + private var details: some View { + VStack(alignment: .leading, spacing: 8) { + row(String(localized: "Instance"), instanceLabel) + row(String(localized: "Command"), command.commandName ?? command.name) + if let result = command.result { row(String(localized: "Result"), result) } + if let message = command.message { row(String(localized: "Message"), message) } + row(String(localized: "Queued"), command.queued.formatted(date: .omitted, time: .standard)) + if let started = command.started { + row(String(localized: "Started"), started.formatted(date: .omitted, time: .standard)) + } + if let ended = command.ended { + row(String(localized: "Ended"), ended.formatted(date: .omitted, time: .standard)) + } + if let duration = durationLabel { + row(String(localized: "Duration"), duration) + } + } + } + + private func row(_ label: String, _ value: String) -> some View { + HStack(alignment: .firstTextBaseline) { + Text(label).foregroundStyle(.secondary) + Spacer() + Text(value).multilineTextAlignment(.trailing) + } + .font(.subheadline) + } + + private var instanceLabel: String { + guard let id = command.instanceId, + let instance = settings.instances.first(where: { $0.id == id }) + else { return "—" } + return instance.label + } + + private var durationLabel: String? { + guard let started = command.started, let ended = command.ended else { return nil } + let secs = Int(ended.timeIntervalSince(started)) + if secs < 60 { return "\(secs)s" } + return "\(secs / 60)m \(secs % 60)s" + } + + private var stateTint: Color { + switch command.state { + case .completed: .green + case .failed, .aborted, .orphaned: .red + case .cancelled: .secondary + case .queued, .started: .accentColor + case .unknown: .secondary + } + } +} From 3a51b2658cc5d5cf3a321e390718328c216e91fc Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 09:55:22 -0500 Subject: [PATCH 09/20] Address Activity tasks review: close button, shared formatter, displayTitle --- Ruddarr/Models/Commands/CommandStatus.swift | 6 +++ Ruddarr/Models/Series/Episode.swift | 10 ++-- Ruddarr/Utilities/Formatters.swift | 8 ++++ Ruddarr/Views/Activity/CommandListItem.swift | 16 +------ Ruddarr/Views/Activity/CommandSheet.swift | 49 ++++++++++++-------- 5 files changed, 49 insertions(+), 40 deletions(-) diff --git a/Ruddarr/Models/Commands/CommandStatus.swift b/Ruddarr/Models/Commands/CommandStatus.swift index ac75de8b..1d525443 100644 --- a/Ruddarr/Models/Commands/CommandStatus.swift +++ b/Ruddarr/Models/Commands/CommandStatus.swift @@ -53,6 +53,12 @@ struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { var sortDate: Date { started ?? queued } + + /// Human-readable title for rows and sheets: client-stamped subject if present, + /// otherwise the server-provided command name, otherwise the raw command key. + var displayTitle: String { + subject ?? commandName ?? name + } } enum CommandStatusState: String, Codable { diff --git a/Ruddarr/Models/Series/Episode.swift b/Ruddarr/Models/Series/Episode.swift index 9024aa36..05146cb9 100644 --- a/Ruddarr/Models/Series/Episode.swift +++ b/Ruddarr/Models/Series/Episode.swift @@ -204,15 +204,13 @@ enum EpisodeReleaseType: String, Equatable, Codable { } extension Episode { - /// Formatted subject for Activity / Commands rows, e.g. "Breaking Bad — S1E3". + /// Formatted subject for Activity / Commands rows, e.g. "Breaking Bad — 1x03". + /// Uses the existing `episodeLabel` format for numbering consistency. var subjectLabel: String { - let numbering = "S\(seasonNumber)E\(episodeNumber)" - if let seriesTitle = series?.title, !seriesTitle.isEmpty { - return "\(seriesTitle) — \(numbering)" + return "\(seriesTitle) — \(episodeLabel)" } - - return String(localized: "Episode", comment: "Fallback episode subject") + return episodeLabel } } diff --git a/Ruddarr/Utilities/Formatters.swift b/Ruddarr/Utilities/Formatters.swift index 2f248eaa..da125b91 100644 --- a/Ruddarr/Utilities/Formatters.swift +++ b/Ruddarr/Utilities/Formatters.swift @@ -29,6 +29,14 @@ func formatIndexer(_ name: String) -> String { } } +func formatDuration(_ seconds: TimeInterval) -> String { + let totalSeconds = max(0, Int(seconds)) + if totalSeconds < 60 { return "\(totalSeconds)s" } + let minutes = totalSeconds / 60 + let remainingSeconds = totalSeconds % 60 + return "\(minutes)m \(remainingSeconds)s" +} + func formatRuntime(_ minutes: Int) -> String? { let formatter = DateComponentsFormatter() formatter.allowedUnits = [.hour, .minute] diff --git a/Ruddarr/Views/Activity/CommandListItem.swift b/Ruddarr/Views/Activity/CommandListItem.swift index 54731c61..b8f7d5f8 100644 --- a/Ruddarr/Views/Activity/CommandListItem.swift +++ b/Ruddarr/Views/Activity/CommandListItem.swift @@ -8,7 +8,7 @@ struct CommandListItem: View { var body: some View { VStack(alignment: .leading) { - Text(titleLabel) + Text(command.displayTitle) .font(.headline.monospacedDigit()) .fontWeight(.semibold) .lineLimit(1) @@ -39,26 +39,14 @@ struct CommandListItem: View { } } - private var titleLabel: String { - command.subject ?? command.commandName ?? command.name - } - private var subline: String? { switch command.state { case .started, .queued: let elapsed = now.timeIntervalSince(command.started ?? command.queued) - return formatElapsed(elapsed) + return formatDuration(elapsed) case .completed, .failed, .aborted, .cancelled, .orphaned, .unknown: guard let ended = command.ended else { return nil } return ended.formatted(.relative(presentation: .named)) } } - - private func formatElapsed(_ seconds: TimeInterval) -> String { - let s = max(0, Int(seconds)) - if s < 60 { return "\(s)s" } - let m = s / 60 - let r = s % 60 - return "\(m)m \(r)s" - } } diff --git a/Ruddarr/Views/Activity/CommandSheet.swift b/Ruddarr/Views/Activity/CommandSheet.swift index 2a303526..fc41453f 100644 --- a/Ruddarr/Views/Activity/CommandSheet.swift +++ b/Ruddarr/Views/Activity/CommandSheet.swift @@ -7,20 +7,31 @@ struct CommandSheet: View { @Environment(\.dismiss) private var dismiss var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - header - Divider() - details + NavigationStack { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + header + Divider() + details + } + .padding() + .frame(maxWidth: .infinity, alignment: .leading) + } + .toolbar { + ToolbarItem(placement: .destructiveAction) { + Button("Close", systemImage: "xmark") { + dismiss() + } + .hideIconOnMac() + .tint(.primary) + } } - .padding() - .frame(maxWidth: .infinity, alignment: .leading) } } private var header: some View { VStack(alignment: .leading, spacing: 4) { - Text(command.subject ?? command.commandName ?? command.name) + Text(command.displayTitle) .font(.title3) .fontWeight(.semibold) @@ -35,24 +46,24 @@ struct CommandSheet: View { private var details: some View { VStack(alignment: .leading, spacing: 8) { - row(String(localized: "Instance"), instanceLabel) - row(String(localized: "Command"), command.commandName ?? command.name) - if let result = command.result { row(String(localized: "Result"), result) } - if let message = command.message { row(String(localized: "Message"), message) } - row(String(localized: "Queued"), command.queued.formatted(date: .omitted, time: .standard)) + row("Instance", instanceLabel) + row("Command", command.commandName ?? command.name) + if let result = command.result { row("Result", result) } + if let message = command.message { row("Message", message) } + row("Queued", command.queued.formatted(date: .abbreviated, time: .shortened)) if let started = command.started { - row(String(localized: "Started"), started.formatted(date: .omitted, time: .standard)) + row("Started", started.formatted(date: .abbreviated, time: .shortened)) } if let ended = command.ended { - row(String(localized: "Ended"), ended.formatted(date: .omitted, time: .standard)) + row("Ended", ended.formatted(date: .abbreviated, time: .shortened)) } if let duration = durationLabel { - row(String(localized: "Duration"), duration) + row("Duration", duration) } } } - private func row(_ label: String, _ value: String) -> some View { + private func row(_ label: LocalizedStringKey, _ value: String) -> some View { HStack(alignment: .firstTextBaseline) { Text(label).foregroundStyle(.secondary) Spacer() @@ -70,9 +81,7 @@ struct CommandSheet: View { private var durationLabel: String? { guard let started = command.started, let ended = command.ended else { return nil } - let secs = Int(ended.timeIntervalSince(started)) - if secs < 60 { return "\(secs)s" } - return "\(secs / 60)m \(secs % 60)s" + return formatDuration(ended.timeIntervalSince(started)) } private var stateTint: Color { From 89f952052742dc468dd8805bdbfb83fbb01ec49e Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 10:02:06 -0500 Subject: [PATCH 10/20] Track dispatched commands in Activity tab --- Ruddarr/Views/Movies/MovieContextMenu.swift | 5 ++++- Ruddarr/Views/Movies/MovieDetails.swift | 5 ++++- Ruddarr/Views/Movies/MovieView.swift | 5 ++++- Ruddarr/Views/Series/EpisodeContextMenu.swift | 5 ++++- Ruddarr/Views/Series/EpisodeView.swift | 5 ++++- Ruddarr/Views/Series/SeasonView.swift | 5 ++++- Ruddarr/Views/Series/SeriesContextMenu.swift | 5 ++++- Ruddarr/Views/Series/SeriesDetails.swift | 5 ++++- Ruddarr/Views/Series/SeriesItemView.swift | 5 ++++- 9 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Ruddarr/Views/Movies/MovieContextMenu.swift b/Ruddarr/Views/Movies/MovieContextMenu.swift index 58f2321f..a00e6904 100644 --- a/Ruddarr/Views/Movies/MovieContextMenu.swift +++ b/Ruddarr/Views/Movies/MovieContextMenu.swift @@ -19,10 +19,13 @@ struct MovieContextMenu: View { } func dispatchSearch() async { - guard await instance.movies.command(.search([movie.id])) else { + guard var status = await instance.movies.command(.search([movie.id])) else { return } + status.subject = movie.title + Commands.shared.track(status) + dependencies.toast.show(.movieSearchQueued) Telemetry.record(.movieSearchDispatched) diff --git a/Ruddarr/Views/Movies/MovieDetails.swift b/Ruddarr/Views/Movies/MovieDetails.swift index 314b9890..d470ceb4 100644 --- a/Ruddarr/Views/Movies/MovieDetails.swift +++ b/Ruddarr/Views/Movies/MovieDetails.swift @@ -190,12 +190,15 @@ struct MovieDetails: View { defer { dispatchingSearch = false } dispatchingSearch = true - guard await instance.movies.command( + guard var status = await instance.movies.command( .search([movie.id]) ) else { return } + status.subject = movie.title + Commands.shared.track(status) + dependencies.toast.show(.movieSearchQueued) Telemetry.record(.movieSearchDispatched) diff --git a/Ruddarr/Views/Movies/MovieView.swift b/Ruddarr/Views/Movies/MovieView.swift index 200cd051..0ed92ebc 100644 --- a/Ruddarr/Views/Movies/MovieView.swift +++ b/Ruddarr/Views/Movies/MovieView.swift @@ -165,10 +165,13 @@ extension MovieView { } func dispatchSearch() async { - guard await instance.movies.command(.search([movie.id])) else { + guard var status = await instance.movies.command(.search([movie.id])) else { return } + status.subject = movie.title + Commands.shared.track(status) + dependencies.toast.show(.movieSearchQueued) Telemetry.record(.movieSearchDispatched) diff --git a/Ruddarr/Views/Series/EpisodeContextMenu.swift b/Ruddarr/Views/Series/EpisodeContextMenu.swift index bc6a9482..52947752 100644 --- a/Ruddarr/Views/Series/EpisodeContextMenu.swift +++ b/Ruddarr/Views/Series/EpisodeContextMenu.swift @@ -28,10 +28,13 @@ struct EpisodeContextMenu: View { } func dispatchSearch() async { - guard await instance.series.command(.episodeSearch([episode.id])) else { + guard var status = await instance.series.command(.episodeSearch([episode.id])) else { return } + status.subject = episode.subjectLabel + Commands.shared.track(status) + dependencies.toast.show(.episodeSearchQueued) Telemetry.record(.episodeSearchDispatched) diff --git a/Ruddarr/Views/Series/EpisodeView.swift b/Ruddarr/Views/Series/EpisodeView.swift index 2b0f05c1..e2fb8d31 100644 --- a/Ruddarr/Views/Series/EpisodeView.swift +++ b/Ruddarr/Views/Series/EpisodeView.swift @@ -330,11 +330,14 @@ extension EpisodeView { defer { dispatchingSearch = false } dispatchingSearch = true - guard await instance.series.command( + guard var status = await instance.series.command( .episodeSearch([episode.id])) else { return } + status.subject = episode.subjectLabel + Commands.shared.track(status) + dependencies.toast.show(.episodeSearchQueued) Telemetry.record(.episodeSearchDispatched) diff --git a/Ruddarr/Views/Series/SeasonView.swift b/Ruddarr/Views/Series/SeasonView.swift index 0da57d1d..b66cad01 100644 --- a/Ruddarr/Views/Series/SeasonView.swift +++ b/Ruddarr/Views/Series/SeasonView.swift @@ -274,12 +274,15 @@ extension SeasonView { defer { dispatchingSearch = false } dispatchingSearch = true - guard await instance.series.command( + guard var status = await instance.series.command( .seasonSearch(series.id, season: season.id) ) else { return } + status.subject = "\(series.title) — \(String(localized: "Season \(season.id)", comment: "Season number for command subject"))" + Commands.shared.track(status) + dependencies.toast.show(.seasonSearchQueued) Telemetry.record(.seasonSearchDispatched) diff --git a/Ruddarr/Views/Series/SeriesContextMenu.swift b/Ruddarr/Views/Series/SeriesContextMenu.swift index 4939eff4..fcfc3cc8 100644 --- a/Ruddarr/Views/Series/SeriesContextMenu.swift +++ b/Ruddarr/Views/Series/SeriesContextMenu.swift @@ -21,10 +21,13 @@ struct SeriesContextMenu: View { } func dispatchSearch() async { - guard await instance.series.command(.seriesSearch(series.id)) else { + guard var status = await instance.series.command(.seriesSearch(series.id)) else { return } + status.subject = series.title + Commands.shared.track(status) + dependencies.toast.show(.monitoredSearchQueued) Telemetry.record(.seriesSearchDispatched) diff --git a/Ruddarr/Views/Series/SeriesDetails.swift b/Ruddarr/Views/Series/SeriesDetails.swift index 92884064..5e2b684d 100644 --- a/Ruddarr/Views/Series/SeriesDetails.swift +++ b/Ruddarr/Views/Series/SeriesDetails.swift @@ -186,12 +186,15 @@ struct SeriesDetails: View { defer { dispatchingSearch = false } dispatchingSearch = true - guard await instance.series.command( + guard var status = await instance.series.command( .seriesSearch(series.id) ) else { return } + status.subject = series.title + Commands.shared.track(status) + dependencies.toast.show(.monitoredSearchQueued) Telemetry.record(.seriesSearchDispatched) diff --git a/Ruddarr/Views/Series/SeriesItemView.swift b/Ruddarr/Views/Series/SeriesItemView.swift index e7d0393e..739d509c 100644 --- a/Ruddarr/Views/Series/SeriesItemView.swift +++ b/Ruddarr/Views/Series/SeriesItemView.swift @@ -172,12 +172,15 @@ extension SeriesDetailView { } func dispatchSearch() async { - guard await instance.series.command( + guard var status = await instance.series.command( .seriesSearch(series.id) ) else { return } + status.subject = series.title + Commands.shared.track(status) + dependencies.toast.show(.monitoredSearchQueued) Telemetry.record(.seriesSearchDispatched) From 02bee29794a8a3d851cd0e5f6f343a7766e92668 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 10:09:11 -0500 Subject: [PATCH 11/20] Add CommandsListView and localized strings --- Ruddarr/Localizable.xcstrings | 150 ++++++++++++++++++ Ruddarr/Views/Activity/CommandsListView.swift | 104 ++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 Ruddarr/Views/Activity/CommandsListView.swift diff --git a/Ruddarr/Localizable.xcstrings b/Ruddarr/Localizable.xcstrings index 0e13d4d2..a655d6d1 100644 --- a/Ruddarr/Localizable.xcstrings +++ b/Ruddarr/Localizable.xcstrings @@ -293,6 +293,16 @@ } } }, + "Aborted" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aborted" + } + } + } + }, "About" : { "comment" : "Preferences section title", "localizations" : { @@ -802,6 +812,16 @@ } } }, + "Automatic searches and other commands will appear here." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatic searches and other commands will appear here." + } + } + } + }, "Availability" : { "comment" : "Very short version of Minimum Availability", "localizations" : { @@ -927,6 +947,16 @@ } } }, + "Cancelled" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancelled" + } + } + } + }, "Cards" : { "comment" : "Grid item display style", "localizations" : { @@ -1031,6 +1061,26 @@ } } }, + "Command" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Command" + } + } + } + }, + "Completed" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Completed" + } + } + } + }, "Connect a %@ instance under %@." : { "localizations" : { "en" : { @@ -1472,6 +1522,26 @@ } } }, + "Downloads" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloads" + } + } + } + }, + "Duration" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Duration" + } + } + } + }, "Dynamic Range" : { "comment" : "Video file dynamic range", "localizations" : { @@ -2545,6 +2615,16 @@ } } }, + "Message" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Message" + } + } + } + }, "Metadata" : { "comment" : "Type of the extra movie file", "localizations" : { @@ -3028,6 +3108,16 @@ } } }, + "No Recent Tasks" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Recent Tasks" + } + } + } + }, "No Releases Found" : { "localizations" : { "en" : { @@ -3759,6 +3849,16 @@ } } }, + "Orphaned" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Orphaned" + } + } + } + }, "Other" : { "comment" : "Type of the extra movie file", "localizations" : { @@ -4293,6 +4393,16 @@ } } }, + "Result" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Result" + } + } + } + }, "Retry" : { "localizations" : { "en" : { @@ -4324,6 +4434,16 @@ } } }, + "Running" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Running" + } + } + } + }, "Runtime" : { "comment" : "Video runtime", "localizations" : { @@ -4693,6 +4813,16 @@ } } }, + "Show All Tasks" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show All Tasks" + } + } + } + }, "Single Episode" : { "localizations" : { "en" : { @@ -4785,6 +4915,16 @@ } } }, + "Started" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Started" + } + } + } + }, "Status" : { "localizations" : { "en" : { @@ -4933,6 +5073,16 @@ } } }, + "Tasks" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tasks" + } + } + } + }, "TBA" : { "comment" : "(Short, 3-6 characters) Conveying unannounced", "localizations" : { diff --git a/Ruddarr/Views/Activity/CommandsListView.swift b/Ruddarr/Views/Activity/CommandsListView.swift new file mode 100644 index 00000000..87e1f6df --- /dev/null +++ b/Ruddarr/Views/Activity/CommandsListView.swift @@ -0,0 +1,104 @@ +import SwiftUI + +struct CommandsListView: View { + @State var commands = Commands.shared + @State private var selected: InstanceCommandStatus? + @State private var showAll: Bool = false + + @EnvironmentObject var settings: AppSettings + @Environment(\.deviceType) private var deviceType + + var body: some View { + Group { + if settings.configuredInstances.isEmpty { + NoInstance() + } else { + List { + Section { + ForEach(filteredItems) { command in + Button { + selected = command + } label: { + CommandListItem(command: command) + } + .buttonStyle(.plain) + } + #if os(macOS) + .padding(.vertical, 4) + #else + .listRowBackground(Color.card) + #endif + } header: { + sectionHeader + } + } + #if os(iOS) + .background(.systemBackground) + #endif + .scrollContentBackground(.hidden) + .overlay { + if filteredItems.isEmpty { + empty + } + } + } + } + .toolbar { + ToolbarItem(placement: .primaryAction) { + Toggle(isOn: $showAll) { + Label( + "Show All Tasks", + systemImage: showAll ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease.circle" + ) + } + .toggleStyle(.button) + .tint(.primary) + } + } + .onAppear { + commands.instances = settings.instances + commands.performRefresh = true + } + .onDisappear { + commands.performRefresh = false + } + .task { + await commands.fetchAll() + } + .refreshable { + await Task { await commands.fetchAll() }.value + } + .sheet(item: $selected) { command in + CommandSheet(command: command) + .presentationDetents(dynamic: [ + deviceType == .phone ? .fraction(0.7) : .large + ]) + .presentationBackground(.sheetBackground) + .environmentObject(settings) + } + } + + private var filteredItems: [InstanceCommandStatus] { + commands.filteredItems(showAll: showAll) + } + + private var sectionHeader: some View { + HStack(spacing: 6) { + Text("\(filteredItems.count) Task") + + if commands.isLoading { + ProgressView() + .controlSize(.small) + .tint(.secondary) + } + } + } + + private var empty: some View { + ContentUnavailableView( + "No Recent Tasks", + systemImage: "checklist", + description: Text("Automatic searches and other commands will appear here.") + ) + } +} From 3c60ec4fb31953694a977a0602c60d9c516d0b39 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 10:11:28 -0500 Subject: [PATCH 12/20] Split Activity tab into Downloads and Tasks segments --- .../Views/Activity/ActivityView+Toolbar.swift | 20 +-- Ruddarr/Views/ActivityView.swift | 144 +++++++++++------- 2 files changed, 96 insertions(+), 68 deletions(-) diff --git a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift index 98754f8f..bdc6322f 100644 --- a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift +++ b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift @@ -30,16 +30,18 @@ extension ActivityView { @ToolbarContentBuilder var toolbarButtons: some ToolbarContent { - ToolbarItem(placement: .navigation) { - toolbarFilterButton - .tint(.primary) - .menuIndicator(.hidden) - } + if segment == .downloads { + ToolbarItem(placement: .navigation) { + toolbarFilterButton + .tint(.primary) + .menuIndicator(.hidden) + } - ToolbarItem(placement: .navigation) { - toolbarSortingButton - .tint(.primary) - .menuIndicator(.hidden) + ToolbarItem(placement: .navigation) { + toolbarSortingButton + .tint(.primary) + .menuIndicator(.hidden) + } } #if os(iOS) diff --git a/Ruddarr/Views/ActivityView.swift b/Ruddarr/Views/ActivityView.swift index 8ac93bf9..a5183f7d 100644 --- a/Ruddarr/Views/ActivityView.swift +++ b/Ruddarr/Views/ActivityView.swift @@ -6,79 +6,100 @@ struct ActivityView: View { @State var sort: QueueSort = .init() @State var items: [QueueItem] = [] @State private var selectedItem: QueueItem? + @State var segment: ActivitySegment = .downloads @EnvironmentObject var settings: AppSettings @Environment(\.deviceType) private var deviceType var body: some View { - // swiftlint:disable:next closure_body_length NavigationStack { - Group { - if settings.configuredInstances.isEmpty { - NoInstance() - } else { - List { - Section { - ForEach(items) { item in - Button { - selectedItem = item - } label: { - QueueListItem(item: item) - } - .buttonStyle(.plain) - } - #if os(macOS) - .padding(.vertical, 4) - #else - .listRowBackground(Color.card) - #endif - } header: { - if !items.isEmpty { sectionHeader } - } - } - #if os(iOS) - .background(.systemBackground) - #endif - .scrollContentBackground(.hidden) - .overlay { - if items.isEmpty { - queueEmpty - } - } + VStack(spacing: 0) { + Picker("", selection: $segment) { + Text("Downloads").tag(ActivitySegment.downloads) + Text("Tasks").tag(ActivitySegment.tasks) + } + .pickerStyle(.segmented) + .padding(.horizontal) + .padding(.top, 8) + + switch segment { + case .downloads: + downloadsContent + case .tasks: + CommandsListView() + .environmentObject(settings) } } .safeNavigationBarTitleDisplayMode(.inline) .toolbar { toolbarButtons } - .onChange(of: sort.option, updateSortDirection) - .onChange(of: sort, updateDisplayedItems) - .onChange(of: queue.items, updateDisplayedItems) - .onChange(of: queue.items, updateSelectedItem) - .onAppear { - queue.instances = settings.instances - queue.performRefresh = true - updateDisplayedItems() - } - .onDisappear { - queue.performRefresh = false - } - .task { - await queue.fetchTasks() - } - .refreshable { - Task { await queue.refreshDownloadClients() } - await Task { await queue.fetchTasks() }.value - } - .sheet(item: $selectedItem) { item in - QueueItemSheet(item: item) - .presentationDetents(dynamic: [ - deviceType == .phone ? .fraction(0.7) : .large - ]) - .presentationBackground(.sheetBackground) - .environmentObject(settings) + } + } + + // swiftlint:disable:next closure_body_length + private var downloadsContent: some View { + Group { + if settings.configuredInstances.isEmpty { + NoInstance() + } else { + List { + Section { + ForEach(items) { item in + Button { + selectedItem = item + } label: { + QueueListItem(item: item) + } + .buttonStyle(.plain) + } + #if os(macOS) + .padding(.vertical, 4) + #else + .listRowBackground(Color.card) + #endif + } header: { + if !items.isEmpty { sectionHeader } + } + } + #if os(iOS) + .background(.systemBackground) + #endif + .scrollContentBackground(.hidden) + .overlay { + if items.isEmpty { + queueEmpty + } + } } } + .onChange(of: sort.option, updateSortDirection) + .onChange(of: sort, updateDisplayedItems) + .onChange(of: queue.items, updateDisplayedItems) + .onChange(of: queue.items, updateSelectedItem) + .onAppear { + queue.instances = settings.instances + queue.performRefresh = true + updateDisplayedItems() + } + .onDisappear { + queue.performRefresh = false + } + .task { + await queue.fetchTasks() + } + .refreshable { + Task { await queue.refreshDownloadClients() } + await Task { await queue.fetchTasks() }.value + } + .sheet(item: $selectedItem) { item in + QueueItemSheet(item: item) + .presentationDetents(dynamic: [ + deviceType == .phone ? .fraction(0.7) : .large + ]) + .presentationBackground(.sheetBackground) + .environmentObject(settings) + } } var queueEmpty: some View { @@ -159,6 +180,11 @@ struct ActivityView: View { } } +enum ActivitySegment: Hashable { + case downloads + case tasks +} + #Preview { dependencies.router.selectedTab = .activity From 0c8e1df92c390f352d0ad9155a467268175b88d7 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 10:31:05 -0500 Subject: [PATCH 13/20] Register new Activity task files in Xcode project --- Ruddarr.xcodeproj/project.pbxproj | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Ruddarr.xcodeproj/project.pbxproj b/Ruddarr.xcodeproj/project.pbxproj index 0c2e5989..11bf2950 100644 --- a/Ruddarr.xcodeproj/project.pbxproj +++ b/Ruddarr.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 1AFC24FA2F82B753009FF858 /* Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24F82F82B753009FF858 /* Commands.swift */; }; + 1AFC24FB2F82B753009FF858 /* CommandStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24F92F82B753009FF858 /* CommandStatus.swift */; }; + 1AFC24FF2F82B789009FF858 /* CommandSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */; }; + 1AFC25002F82B789009FF858 /* CommandsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */; }; + 1AFC25012F82B789009FF858 /* CommandListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */; }; 2B949CE52CC92CA20088B1A8 /* sonarr-history.json in Resources */ = {isa = PBXBuildFile; fileRef = 2B949CE42CC92C970088B1A8 /* sonarr-history.json */; }; 2B949CE72CC92F370088B1A8 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B949CE62CC92F320088B1A8 /* History.swift */; }; 2B949CEB2CCBC8690088B1A8 /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */; }; @@ -260,6 +265,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1AFC24F82F82B753009FF858 /* Commands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Commands.swift; path = Commands/Commands.swift; sourceTree = ""; }; + 1AFC24F92F82B753009FF858 /* CommandStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CommandStatus.swift; path = Commands/CommandStatus.swift; sourceTree = ""; }; + 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandListItem.swift; sourceTree = ""; }; + 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandSheet.swift; sourceTree = ""; }; + 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsListView.swift; sourceTree = ""; }; 2B949CE42CC92C970088B1A8 /* sonarr-history.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "sonarr-history.json"; sourceTree = ""; }; 2B949CE62CC92F320088B1A8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = ""; }; @@ -771,6 +781,9 @@ BBB8AED22C10DA0F00AA2D9C /* Activity */ = { isa = PBXGroup; children = ( + 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */, + 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */, + 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */, 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */, BB50F2282C3B3322005E14CA /* ActivityView+Toolbar.swift */, BBDBBC682C13A0600087C844 /* QueueSort.swift */, @@ -916,6 +929,8 @@ BBF477A62B4F8AA300C2DED3 /* Models */ = { isa = PBXGroup; children = ( + 1AFC24F82F82B753009FF858 /* Commands.swift */, + 1AFC24F92F82B753009FF858 /* CommandStatus.swift */, BB2370DC2DCE76A600261710 /* Queue */, BBF583C02BACA40D00AFA7FB /* Movies */, BB507D202BD9702B00EC4016 /* Series */, @@ -1222,6 +1237,8 @@ BBE7CE032B91745100431801 /* MovieDetails+Information.swift in Sources */, 2B949CEB2CCBC8690088B1A8 /* HistoryView.swift in Sources */, 79159D6E2B5953E800F7F997 /* API.swift in Sources */, + 1AFC24FA2F82B753009FF858 /* Commands.swift in Sources */, + 1AFC24FB2F82B753009FF858 /* CommandStatus.swift in Sources */, BB05C9052B86D0EC009B6444 /* Languages.swift in Sources */, BBC136A42B62DD780074C7AA /* Network.swift in Sources */, BB89ABC62B756B91009FB62D /* MovieReleaseRow.swift in Sources */, @@ -1283,6 +1300,9 @@ BBD3F2D82BFA578000DE5D8E /* MediaHistory.swift in Sources */, BBA50F4F2D760CAA008A16FA /* SettingsIconLabelStyle.swift in Sources */, BBE1E43F2B51F61700946222 /* MovieLookup.swift in Sources */, + 1AFC24FF2F82B789009FF858 /* CommandSheet.swift in Sources */, + 1AFC25002F82B789009FF858 /* CommandsListView.swift in Sources */, + 1AFC25012F82B789009FF858 /* CommandListItem.swift in Sources */, BBE564DF2DC99A8C005C26B6 /* MovieGridCard.swift in Sources */, 2B949CE72CC92F370088B1A8 /* History.swift in Sources */, BBAED12D2B72D444006C6CF2 /* ButtonLabel.swift in Sources */, From 29bb1df6618f156fda86f6d5fa5dd1c081ab6576 Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 18:04:43 -0500 Subject: [PATCH 14/20] Fix review issues: composite identity, live polling, stale sheet, refresh call sites --- Ruddarr.xcodeproj/project.pbxproj | 2 ++ Ruddarr/Dependencies/API/API+Mock.swift | 4 ++-- Ruddarr/Models/Commands/CommandStatus.swift | 11 ++++++++-- Ruddarr/Models/Commands/Commands.swift | 22 +------------------ Ruddarr/Views/Activity/CommandsListView.swift | 8 +++++++ Ruddarr/Views/Movies/MovieView.swift | 2 +- Ruddarr/Views/Series/SeriesItemView.swift | 2 +- Tests/CommandsTests.swift | 10 ++++----- 8 files changed, 29 insertions(+), 32 deletions(-) diff --git a/Ruddarr.xcodeproj/project.pbxproj b/Ruddarr.xcodeproj/project.pbxproj index 11bf2950..e098cd14 100644 --- a/Ruddarr.xcodeproj/project.pbxproj +++ b/Ruddarr.xcodeproj/project.pbxproj @@ -270,6 +270,7 @@ 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandListItem.swift; sourceTree = ""; }; 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandSheet.swift; sourceTree = ""; }; 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsListView.swift; sourceTree = ""; }; + 1AFC25022F832036009FF858 /* CommandsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsTests.swift; sourceTree = ""; }; 2B949CE42CC92C970088B1A8 /* sonarr-history.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "sonarr-history.json"; sourceTree = ""; }; 2B949CE62CC92F320088B1A8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = ""; }; @@ -558,6 +559,7 @@ BB000000000000000000AAA4 /* Tests */ = { isa = PBXGroup; children = ( + 1AFC25022F832036009FF858 /* CommandsTests.swift */, BB000000000000000000AAA3 /* RuddarrTests.swift */, ); path = Tests; diff --git a/Ruddarr/Dependencies/API/API+Mock.swift b/Ruddarr/Dependencies/API/API+Mock.swift index 7de7842c..1a8f7ba6 100644 --- a/Ruddarr/Dependencies/API/API+Mock.swift +++ b/Ruddarr/Dependencies/API/API+Mock.swift @@ -126,7 +126,7 @@ extension API { return modifyCalendarEpisodes(episodes, instance) }, command: { cmd, instance in var status = InstanceCommandStatus( - id: Int.random(in: 1...999), + commandId: Int.random(in: 1...999), name: cmd.payload.name, commandName: nil, message: "Queued", @@ -143,7 +143,7 @@ extension API { return status }, fetchCommand: { id, instance in var status = InstanceCommandStatus( - id: id, + commandId: id, name: "MoviesSearch", commandName: nil, message: "Completed", diff --git a/Ruddarr/Models/Commands/CommandStatus.swift b/Ruddarr/Models/Commands/CommandStatus.swift index 1d525443..19f2b8c2 100644 --- a/Ruddarr/Models/Commands/CommandStatus.swift +++ b/Ruddarr/Models/Commands/CommandStatus.swift @@ -1,7 +1,7 @@ import Foundation struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { - let id: Int + let commandId: Int let name: String let commandName: String? var message: String? @@ -21,10 +21,17 @@ struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { var subject: String? enum CodingKeys: String, CodingKey { - case id, name, commandName, message, status, result + case commandId = "id" + case name, commandName, message, status, result case queued, started, ended, trigger } + /// Composite identity used by SwiftUI `ForEach` / `.sheet(item:)` so two + /// instances that both expose command id 42 don't collide. + var id: String { + "\(instanceId?.uuidString ?? "none")-\(commandId)" + } + var state: CommandStatusState { CommandStatusState(rawValue: status) ?? .unknown } diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index e0889668..6dd710b3 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -23,7 +23,7 @@ final class Commands { self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in Task { @MainActor in guard let self, self.performRefresh else { return } - await self.refreshActive() + await self.fetchAll() } } } @@ -92,26 +92,6 @@ final class Commands { isLoading = false } - /// Called by the polling timer. Only re-fetches commands that are still - /// non-terminal, to minimize API traffic. - func refreshActive() async { - for instance in instances { - guard let list = items[instance.id] else { continue } - let active = list.filter { !$0.isTerminal } - for command in active { - do { - let updated = try await dependencies.api.fetchCommand(command.id, instance) - merge([updated], for: instance.id) - } catch is CancellationError { - // ignore - } catch { - leaveBreadcrumb(.warning, category: "commands", message: "Poll failed", - data: ["id": command.id, "error": error]) - } - } - } - } - /// Returns a flat, sorted list across all instances, respecting the /// search-only default filter. func filteredItems(showAll: Bool) -> [InstanceCommandStatus] { diff --git a/Ruddarr/Views/Activity/CommandsListView.swift b/Ruddarr/Views/Activity/CommandsListView.swift index 87e1f6df..94212cd6 100644 --- a/Ruddarr/Views/Activity/CommandsListView.swift +++ b/Ruddarr/Views/Activity/CommandsListView.swift @@ -76,6 +76,14 @@ struct CommandsListView: View { .presentationBackground(.sheetBackground) .environmentObject(settings) } + .onChange(of: commands.items) { updateSelected() } + } + + private func updateSelected() { + guard let current = selected else { return } + if let fresh = commands.items[current.instanceId ?? UUID()]?.first(where: { $0.id == current.id }) { + selected = fresh + } } private var filteredItems: [InstanceCommandStatus] { diff --git a/Ruddarr/Views/Movies/MovieView.swift b/Ruddarr/Views/Movies/MovieView.swift index 0ed92ebc..9e30293e 100644 --- a/Ruddarr/Views/Movies/MovieView.swift +++ b/Ruddarr/Views/Movies/MovieView.swift @@ -153,7 +153,7 @@ extension MovieView { } func refresh() async { - guard await instance.movies.command(.refreshMovie([movie.id])) else { + guard await instance.movies.command(.refreshMovie([movie.id])) != nil else { return } diff --git a/Ruddarr/Views/Series/SeriesItemView.swift b/Ruddarr/Views/Series/SeriesItemView.swift index 739d509c..dab6d6c8 100644 --- a/Ruddarr/Views/Series/SeriesItemView.swift +++ b/Ruddarr/Views/Series/SeriesItemView.swift @@ -160,7 +160,7 @@ extension SeriesDetailView { } func refresh() async { - guard await instance.series.command(.refreshSeries(series.id)) else { + guard await instance.series.command(.refreshSeries(series.id)) != nil else { return } diff --git a/Tests/CommandsTests.swift b/Tests/CommandsTests.swift index 2458e081..a681b945 100644 --- a/Tests/CommandsTests.swift +++ b/Tests/CommandsTests.swift @@ -24,7 +24,7 @@ struct CommandsTests { let status = try decoder.decode(InstanceCommandStatus.self, from: json) - #expect(status.id == 42) + #expect(status.commandId == 42) #expect(status.name == "SeriesSearch") #expect(status.state == .completed) #expect(status.message == "Completed") @@ -71,7 +71,7 @@ struct CommandsTests { let instanceId = UUID() let status = InstanceCommandStatus( - id: 1, name: "SeriesSearch", commandName: nil, message: nil, + commandId: 1, name: "SeriesSearch", commandName: nil, message: nil, status: "queued", result: nil, queued: Date(), started: nil, ended: nil, trigger: "manual", instanceId: instanceId, subject: "Breaking Bad" @@ -87,7 +87,7 @@ struct CommandsTests { let instanceId = UUID() let queued = InstanceCommandStatus( - id: 9, name: "MoviesSearch", commandName: nil, message: nil, + commandId: 9, name: "MoviesSearch", commandName: nil, message: nil, status: "queued", result: nil, queued: Date(), started: nil, ended: nil, trigger: "manual", instanceId: instanceId, subject: "Inception" @@ -110,13 +110,13 @@ struct CommandsTests { let instanceId = UUID() let search = InstanceCommandStatus( - id: 1, name: "SeriesSearch", commandName: nil, message: nil, + commandId: 1, name: "SeriesSearch", commandName: nil, message: nil, status: "queued", result: nil, queued: Date(), started: nil, ended: nil, trigger: "manual", instanceId: instanceId, subject: nil ) let rss = InstanceCommandStatus( - id: 2, name: "RssSync", commandName: nil, message: nil, + commandId: 2, name: "RssSync", commandName: nil, message: nil, status: "queued", result: nil, queued: Date(), started: nil, ended: nil, trigger: "scheduled", instanceId: instanceId, subject: nil From 098f67bf37946b3aaabef316b75dccbe66bc190e Mon Sep 17 00:00:00 2001 From: joptimus Date: Sun, 5 Apr 2026 18:22:00 -0500 Subject: [PATCH 15/20] Rename Tasks segment to Searches and show it first --- Ruddarr/Localizable.xcstrings | 7105 +++++++++++++++--------------- Ruddarr/Views/ActivityView.swift | 12 +- 2 files changed, 3562 insertions(+), 3555 deletions(-) diff --git a/Ruddarr/Localizable.xcstrings b/Ruddarr/Localizable.xcstrings index a655d6d1..0d32d976 100644 --- a/Ruddarr/Localizable.xcstrings +++ b/Ruddarr/Localizable.xcstrings @@ -1,21 +1,22 @@ { - "sourceLanguage" : "en", - "strings" : { - "(%lld Issue)" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "(%lld Issue)" + "sourceLanguage": "en", + "strings": { + "": {}, + "(%lld Issue)": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "(%lld Issue)" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "(%lld Issues)" + "other": { + "stringUnit": { + "state": "translated", + "value": "(%lld Issues)" } } } @@ -23,83 +24,83 @@ } } }, - "%.1f years" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%.1f years" + "%.1f years": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%.1f years" } } } }, - "%@ at %@" : { - "comment" : "(Today/Tomorrow/Yesterday) at (time)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$@ at %2$@" + "%@ at %@": { + "comment": "(Today/Tomorrow/Yesterday) at (time)", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%1$@ at %2$@" } } } }, - "%@ does not start an automatic search when adding media, but you can." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ does not start an automatic search when adding media, but you can." + "%@ does not start an automatic search when adding media, but you can.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ does not start an automatic search when adding media, but you can." } } } }, - "%@." : { - "comment" : "Prefix for episode title (episode number)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@." + "%@.": { + "comment": "Prefix for episode title (episode number)", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@." } } } }, - "%1$@ downloaded successfully and imported from %2$@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$@ downloaded successfully and imported from %2$@." + "%1$@ downloaded successfully and imported from %2$@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%1$@ downloaded successfully and imported from %2$@." } } } }, - "%1$@ grabbed from %2$@ and sent to %3$@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$@ grabbed from %2$@ and sent to %3$@." + "%1$@ grabbed from %2$@ and sent to %3$@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%1$@ grabbed from %2$@ and sent to %3$@." } } } }, - "%d days" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d day" + "%d days": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%d day" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d days" + "other": { + "stringUnit": { + "state": "translated", + "value": "%d days" } } } @@ -107,21 +108,21 @@ } } }, - "%d hours" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d hour" + "%d hours": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%d hour" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d hours" + "other": { + "stringUnit": { + "state": "translated", + "value": "%d hours" } } } @@ -129,21 +130,21 @@ } } }, - "%d minutes" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d minute" + "%d minutes": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%d minute" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d minutes" + "other": { + "stringUnit": { + "state": "translated", + "value": "%d minutes" } } } @@ -151,21 +152,21 @@ } } }, - "%d months" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d month" + "%d months": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%d month" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d months" + "other": { + "stringUnit": { + "state": "translated", + "value": "%d months" } } } @@ -173,31 +174,31 @@ } } }, - "%d years" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d years" + "%d years": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%d years" } } } }, - "%lld Season" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Season" + "%lld Season": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%lld Season" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Seasons" + "other": { + "stringUnit": { + "state": "translated", + "value": "%lld Seasons" } } } @@ -205,21 +206,21 @@ } } }, - "%lld Seasons" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Season" + "%lld Seasons": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%lld Season" } }, - "other" : { - "stringUnit" : { - "state" : "new", - "value" : "%lld Seasons" + "other": { + "stringUnit": { + "state": "new", + "value": "%lld Seasons" } } } @@ -227,21 +228,21 @@ } } }, - "%lld Tag" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Tag" + "%lld Tag": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%lld Tag" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Tags" + "other": { + "stringUnit": { + "state": "translated", + "value": "%lld Tags" } } } @@ -249,21 +250,21 @@ } } }, - "%lld Task" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Task" + "%lld Task": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "%lld Task" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld Tasks" + "other": { + "stringUnit": { + "state": "translated", + "value": "%lld Tasks" } } } @@ -271,21 +272,21 @@ } } }, - "+%lld more..." : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "+%lld more..." + "+%lld more...": { + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "+%lld more..." } }, - "other" : { - "stringUnit" : { - "state" : "new", - "value" : "+%lld more..." + "other": { + "stringUnit": { + "state": "new", + "value": "+%lld more..." } } } @@ -293,4296 +294,4302 @@ } } }, - "Aborted" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Aborted" + "Aborted": { + "comment": "Command status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Aborted" } } } }, - "About" : { - "comment" : "Preferences section title", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "About" + "About": { + "comment": "Preferences section title", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "About" } } } }, - "Accent Color" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Accent Color" + "Accent Color": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Accent Color" } } } }, - "Active" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Active" + "Active": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Active" } } } }, - "Activity" : { - "comment" : "Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Activity" + "Activity": { + "comment": "Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Activity" } } } }, - "Add Authentication" : { - "comment" : "Add Basic HTTP Authentication to instance", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Authentication" + "Add Authentication": { + "comment": "Add Basic HTTP Authentication to instance", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Authentication" } } } }, - "Add Exclusion" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Exclusion" + "Add Exclusion": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Exclusion" } } } }, - "Add Header" : { - "comment" : "Add HTTP Header to instance", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Header" + "Add Header": { + "comment": "Add HTTP Header to instance", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Header" } } } }, - "Add Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Instance" + "Add Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Instance" } } } }, - "Add Movie" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Movie" + "Add Movie": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Movie" } } } }, - "Add Series" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Add Series" + "Add Series": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Series" } } } }, - "Added" : { - "comment" : "Media grid sorting", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Added" + "Added": { + "comment": "Media grid sorting", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Added" } } } }, - "Age" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Age" + "Age": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Age" } } } }, - "Airing" : { - "comment" : "The time the next episode airs", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Airing" + "Airing": { + "comment": "The time the next episode airs", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Airing" } } } }, - "Alias" : { - "comment" : "Match type of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alias" + "Alias": { + "comment": "Match type of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Alias" } } } }, - "All Episodes" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "All Episodes" + "All Episodes": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "All Episodes" } } } }, - "All Events" : { - "comment" : "(Short) History event filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "All Events" + "All Events": { + "comment": "(Short) History event filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "All Events" } } } }, - "All instance queues are empty." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "All instance queues are empty." + "All instance queues are empty.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "All instance queues are empty." } } } }, - "All Movies" : { - "comment" : "Media grid filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "All Movies" + "All Movies": { + "comment": "Media grid filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "All Movies" } } } }, - "All TV Series" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "All TV Series" + "All TV Series": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "All TV Series" } } } }, - "Alternatively, %@ comes with many notification integrations that can be self-hosted." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Alternatively, %@ comes with many notification integrations that can be self-hosted." + "Alternatively, %@ comes with many notification integrations that can be self-hosted.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Alternatively, %@ comes with many notification integrations that can be self-hosted." } } } }, - "An error occurred." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "An error occurred." + "An error occurred.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "An error occurred." } } } }, - "An unexpected error occurred." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "An unexpected error occurred." + "An unexpected error occurred.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "An unexpected error occurred." } } } }, - "An unknown error occurred: %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "An unknown error occurred: %@" + "An unknown error occurred: %@": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "An unknown error occurred: %@" } } } }, - "Anime" : { - "comment" : "Series type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Anime" + "Anime": { + "comment": "Series type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Anime" } } } }, - "Announced" : { - "comment" : "Media status label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Announced" + "Announced": { + "comment": "Media status label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Announced" } } } }, - "Any" : { - "comment" : "Season pack or single episode option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any" + "Any": { + "comment": "Season pack or single episode option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any" } } } }, - "Any Client" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Client" + "Any Client": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Client" } } } }, - "Any Folder" : { - "comment" : "Short spelling of Root Folder", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Folder" + "Any Folder": { + "comment": "Short spelling of Root Folder", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Folder" } } } }, - "Any Format" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Format" + "Any Format": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Format" } } } }, - "Any Indexer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Indexer" + "Any Indexer": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Indexer" } } } }, - "Any Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Instance" + "Any Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Instance" } } } }, - "Any Language" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Language" + "Any Language": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Language" } } } }, - "Any Protocol" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Protocol" + "Any Protocol": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Protocol" } } } }, - "Any Quality" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Any Quality" + "Any Quality": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Any Quality" } } } }, - "API Key" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "API Key" + "API Key": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "API Key" } } } }, - "App Icon" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "App Icon" + "App Icon": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "App Icon" } } } }, - "Appearance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Appearance" + "Appearance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Appearance" } } } }, - "Application Updated" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Application Updated" + "Application Updated": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Application Updated" } } } }, - "Approved" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Approved" + "Approved": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Approved" } } } }, - "Are you attempting to connect to a private IP address from outside its network?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Are you attempting to connect to a private IP address from outside its network?" + "Are you attempting to connect to a private IP address from outside its network?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you attempting to connect to a private IP address from outside its network?" } } } }, - "Are you sure you want to delete the instance?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Are you sure you want to delete the instance?" + "Are you sure you want to delete the instance?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you sure you want to delete the instance?" } } } }, - "Are you sure you want to erase all settings?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Are you sure you want to erase all settings?" + "Are you sure you want to erase all settings?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you sure you want to erase all settings?" } } } }, - "Are you sure?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Are you sure?" + "Are you sure?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you sure?" } } } }, - "Ascending" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ascending" + "Ascending": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Ascending" } } } }, - "At least you're not on hold." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "At least you're not on hold." + "At least you're not on hold.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "At least you're not on hold." } } } }, - "Audio" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Audio" + "Audio": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Audio" } } } }, - "Authentication" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Authentication" + "Authentication": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Authentication" } } } }, - "Automatic" : { - "comment" : "Appearance that adapts to the system", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatic" + "Automatic": { + "comment": "Appearance that adapts to the system", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Automatic" } } } }, - "Automatic Search" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatic Search" + "Automatic Search": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Automatic Search" } } } }, - "Automatic searches and other commands will appear here." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Automatic searches and other commands will appear here." + "Automatic searches and other commands will appear here.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Automatic searches and other commands will appear here." } } } }, - "Availability" : { - "comment" : "Very short version of Minimum Availability", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Availability" + "Availability": { + "comment": "Very short version of Minimum Availability", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Availability" } } } }, - "Bad status code: %lld" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bad status code: %lld" + "Bad status code: %lld": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Bad status code: %lld" } } } }, - "Barbie" : { - "comment" : "Localized name of the Barbie brand", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Barbie" + "Barbie": { + "comment": "Localized name of the Barbie brand", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Barbie" } } } }, - "Basic Authentication" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Basic Authentication" + "Basic Authentication": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Basic Authentication" } } } }, - "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." + "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." } } } }, - "Bitrate" : { - "comment" : "Audio/video bitrate", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bitrate" + "Bitrate": { + "comment": "Audio/video bitrate", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Bitrate" } } } }, - "Blocklist Release" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Blocklist Release" + "Blocklist Release": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blocklist Release" } } } }, - "Blocks this release from being redownloaded via Automatic Search or RSS." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Blocks this release from being redownloaded via Automatic Search or RSS." + "Blocks this release from being redownloaded via Automatic Search or RSS.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blocks this release from being redownloaded via Automatic Search or RSS." } } } }, - "Books" : { - "comment" : "Localized name of Apple's Books app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Books" + "Books": { + "comment": "Localized name of Apple's Books app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Books" } } } }, - "Bug Report Sent" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bug Report Sent" + "Bug Report Sent": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Bug Report Sent" } } } }, - "Calendar" : { - "comment" : "Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Calendar" + "Calendar": { + "comment": "Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Calendar" } } } }, - "Cancel" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cancel" + "Cancel": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cancel" } } } }, - "Cancelled" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cancelled" + "Cancelled": { + "comment": "Command status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cancelled" } } } }, - "Cards" : { - "comment" : "Grid item display style", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cards" + "Cards": { + "comment": "Grid item display style", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cards" } } } }, - "Channels" : { - "comment" : "Audio channel count", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Channels" + "Channels": { + "comment": "Audio channel count", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Channels" } } } }, - "Check the spelling or try [adding the movie](%@)." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Check the spelling or try [adding the movie](%@)." + "Check the spelling or try [adding the movie](%@).": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Check the spelling or try [adding the movie](%@)." } } } }, - "Check the spelling or try [adding the series](%@)." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Check the spelling or try [adding the series](%@)." + "Check the spelling or try [adding the series](%@).": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Check the spelling or try [adding the series](%@)." } } } }, - "Clear Filters" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clear Filters" + "Clear Filters": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Clear Filters" } } } }, - "Clear Image Cache" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Clear Image Cache" + "Clear Image Cache": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Clear Image Cache" } } } }, - "Client" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Client" + "Client": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Client" } } } }, - "Close" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Close" + "Close": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Close" } } } }, - "Codec" : { - "comment" : "Audio/video codec", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Codec" + "Codec": { + "comment": "Audio/video codec", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Codec" } } } }, - "Color Depth" : { - "comment" : "Video color depth", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Color Depth" + "Color Depth": { + "comment": "Video color depth", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Color Depth" } } } }, - "Command" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Command" + "Command": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Command" } } } }, - "Completed" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Completed" + "Completed": { + "comment": "Command status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Completed" } } } }, - "Connect a %@ instance under %@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connect a %1$@ instance under %2$@." + "Connect a %@ instance under %@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connect a %1$@ instance under %2$@." } } } }, - "Connected" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connected" + "Connected": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connected" } } } }, - "Connecting..." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connecting..." + "Connecting...": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connecting..." } } } }, - "Connection Failed" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connection Failed" + "Connection Failed": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connection Failed" } } } }, - "Connection Failure" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Connection Failure" + "Connection Failure": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connection Failure" } } } }, - "Continue" : { - "comment" : "Button to close whats new sheet", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Continue" + "Continue": { + "comment": "Button to close whats new sheet", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Continue" } } } }, - "Continuing" : { - "comment" : "(Single word) Series status", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Continuing" + "Continuing": { + "comment": "(Single word) Series status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Continuing" } } } }, - "Contribute on GitHub" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Contribute on GitHub" + "Contribute on GitHub": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Contribute on GitHub" } } } }, - "Copy Link" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Copy Link" + "Copy Link": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Link" } } } }, - "Custom Format" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Custom Format" + "Custom Format": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Custom Format" } } } }, - "Custom Formats" : { - "comment" : "Custom formats of media file", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Custom Formats" + "Custom Formats": { + "comment": "Custom formats of media file", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Custom Formats" } } } }, - "Custom Headers can be used to access instances protected by Zero Trust services." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Custom Headers can be used to access instances protected by Zero Trust services." + "Custom Headers can be used to access instances protected by Zero Trust services.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Custom Headers can be used to access instances protected by Zero Trust services." } } } }, - "Custom Score" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Custom Score" + "Custom Score": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Custom Score" } } } }, - "Daily" : { - "comment" : "Series type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Daily" + "Daily": { + "comment": "Series type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Daily" } } } }, - "Dangling" : { - "comment" : "Media grid filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dangling" + "Dangling": { + "comment": "Media grid filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Dangling" } } } }, - "Dark" : { - "comment" : "Dark appearance/mode", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dark" + "Dark": { + "comment": "Dark appearance/mode", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Dark" } } } }, - "Default" : { - "comment" : "Default app icon name", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Default" + "Default": { + "comment": "Default app icon name", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Default" } } } }, - "Delete" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete" + "Delete": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete" } } } }, - "Delete File" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete File" + "Delete File": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete File" } } } }, - "Delete Files" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete Files" + "Delete Files": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete Files" } } } }, - "Delete Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete Instance" + "Delete Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete Instance" } } } }, - "Delete Movie" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete Movie" + "Delete Movie": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete Movie" } } } }, - "Delete Series" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete Series" + "Delete Series": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete Series" } } } }, - "Delete Spotlight Index" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete Spotlight Index" + "Delete Spotlight Index": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete Spotlight Index" } } } }, - "Deleted" : { - "comment" : "(Short) History event filter\n(Short) Title of history event\n(Single word) Series status\nMedia status label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deleted" + "Deleted": { + "comment": "(Short) History event filter\n(Short) Title of history event\n(Single word) Series status\nMedia status label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Deleted" } } } }, - "Deleting Files" : { - "comment" : "Title of a tip, not a status", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Deleting Files" + "Deleting Files": { + "comment": "Title of a tip, not a status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Deleting Files" } } } }, - "Descending" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Descending" + "Descending": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Descending" } } } }, - "Details" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Details" + "Details": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Details" } } } }, - "Digital Release" : { - "comment" : "Media grid sorting", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Digital Release" + "Digital Release": { + "comment": "Media grid sorting", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Digital Release" } } } }, - "Direction" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Direction" + "Direction": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Direction" } } } }, - "Discovering new ways of making you wait." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Discovering new ways of making you wait." + "Discovering new ways of making you wait.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Discovering new ways of making you wait." } } } }, - "Display" : { - "comment" : "Preferences section title", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Display" + "Display": { + "comment": "Preferences section title", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Display" } } } }, - "Download" : { - "comment" : "Short version of Download Release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download" + "Download": { + "comment": "Short version of Download Release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download" } } } }, - "download client" : { - "comment" : "Fallback for download client name within mid-sentence", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "download client" + "download client": { + "comment": "Fallback for download client name within mid-sentence", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "download client" } } } }, - "Download Client Unavailable" : { - "comment" : "Status of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Client Unavailable" + "Download Client Unavailable": { + "comment": "Status of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Client Unavailable" } } } }, - "Download Client Warning" : { - "comment" : "Status of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Client Warning" + "Download Client Warning": { + "comment": "Status of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Client Warning" } } } }, - "Download Failed" : { - "comment" : "Status of task in queue\nTitle of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Failed" + "Download Failed": { + "comment": "Status of task in queue\nTitle of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Failed" } } } }, - "Download Ignored" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Ignored" + "Download Ignored": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Ignored" } } } }, - "Download Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Queued" + "Download Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Queued" } } } }, - "Download Release" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Download Release" + "Download Release": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download Release" } } } }, - "Downloaded" : { - "comment" : "(Single word) Episode status label\nMedia grid filter\nState of media item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Downloaded" + "Downloaded": { + "comment": "(Single word) Episode status label\nMedia grid filter\nState of media item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Downloaded" } } } }, - "Downloading" : { - "comment" : "(Short) State of task in queue\nState of task in queue\nStatus of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Downloading" + "Downloading": { + "comment": "(Short) State of task in queue\nState of task in queue\nStatus of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Downloading" } } } }, - "Downloads" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Downloads" + "Downloads": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Downloads" } } } }, - "Duration" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Duration" + "Duration": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Duration" } } } }, - "Dynamic Range" : { - "comment" : "Video file dynamic range", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Dynamic Range" + "Dynamic Range": { + "comment": "Video file dynamic range", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Dynamic Range" } } } }, - "Edit" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Edit" + "Edit": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Edit" } } } }, - "Email" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Email" + "Email": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Email" } } } }, - "Enable Notifications" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enable Notifications" + "Enable Notifications": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enable Notifications" } } } }, - "Ended" : { - "comment" : "(Single word) Series status", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ended" + "Ended": { + "comment": "(Single word) Series status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Ended" } } } }, - "Enter a valid URL." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enter a valid URL." + "Enter a valid URL.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enter a valid URL." } } } }, - "Enter an instance label." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enter an instance label." + "Enter an instance label.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enter an instance label." } } } }, - "Episode" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode" + "Episode": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode" } } } }, - "Episode Deleted" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Deleted" + "Episode Deleted": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Deleted" } } } }, - "Episode file was renamed." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode file was renamed." + "Episode file was renamed.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode file was renamed." } } } }, - "Episode Renamed" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Renamed" + "Episode Renamed": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Renamed" } } } }, - "Episode Search Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Search Queued" + "Episode Search Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Search Queued" } } } }, - "Episodes" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episodes" + "Episodes": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episodes" } } } }, - "Error" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Error" + "Error": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Error" } } } }, - "Event Type" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Event Type" + "Event Type": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Event Type" } } } }, - "Everything" : { - "comment" : "Movies and series filter option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Everything" + "Everything": { + "comment": "Movies and series filter option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Everything" } } } }, - "Existing Episodes" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Existing Episodes" + "Existing Episodes": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Existing Episodes" } } } }, - "Expired" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Expired" + "Expired": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Expired" } } } }, - "Failed" : { - "comment" : "(Short) History event filter\n(Short) State of task in queue\n(Short) Title of history event", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Failed" + "Failed": { + "comment": "(Short) History event filter\n(Short) State of task in queue\n(Short) Title of history event\nCommand status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Failed" } } } }, - "File" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File" + "File": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File" } } } }, - "File Deleted" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File Deleted" + "File Deleted": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File Deleted" } } } }, - "File Imported" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File Imported" + "File Imported": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File Imported" } } } }, - "File Size" : { - "comment" : "Media grid sorting\nRelease filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File Size" + "File Size": { + "comment": "Media grid sorting\nRelease filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File Size" } } } }, - "File Upgraded" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File Upgraded" + "File Upgraded": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File Upgraded" } } } }, - "File was deleted either manually or by a client through the API." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File was deleted either manually or by a client through the API." + "File was deleted either manually or by a client through the API.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File was deleted either manually or by a client through the API." } } } }, - "File was deleted to import an upgrade." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File was deleted to import an upgrade." + "File was deleted to import an upgrade.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File was deleted to import an upgrade." } } } }, - "File was not found on disk so it was unlinked from the episode in the database." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File was not found on disk so it was unlinked from the episode in the database." + "File was not found on disk so it was unlinked from the episode in the database.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File was not found on disk so it was unlinked from the episode in the database." } } } }, - "File was not found on disk so it was unlinked from the movie in the database." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "File was not found on disk so it was unlinked from the movie in the database." + "File was not found on disk so it was unlinked from the movie in the database.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File was not found on disk so it was unlinked from the movie in the database." } } } }, - "Files" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Files" + "Files": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Files" } } } }, - "Files & History" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Files & History" + "Files & History": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Files & History" } } } }, - "Filter" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Filter" + "Filter": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Filter" } } } }, - "First Season" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "First Season" + "First Season": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "First Season" } } } }, - "Fitness" : { - "comment" : "Localized name of Apple's Fitness app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Fitness" + "Fitness": { + "comment": "Localized name of Apple's Fitness app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fitness" } } } }, - "Flags" : { - "comment" : "Indexer flags", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Flags" + "Flags": { + "comment": "Indexer flags", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Flags" } } } }, - "Folder Imported" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Folder Imported" + "Folder Imported": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Folder Imported" } } } }, - "Framerate" : { - "comment" : "Video frame rate", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Framerate" + "Framerate": { + "comment": "Video frame rate", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Framerate" } } } }, - "FreeLeech" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "FreeLeech" + "FreeLeech": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "FreeLeech" } } } }, - "Future Episodes" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Future Episodes" + "Future Episodes": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Future Episodes" } } } }, - "Genre" : { - "comment" : "Genres of the movie/series", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Genre" + "Genre": { + "comment": "Genres of the movie/series", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Genre" } } } }, - "Grab Release" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grab Release" + "Grab Release": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Grab Release" } } } }, - "Grabbed" : { - "comment" : "(Short) History event filter\n(Short) Title of history event\nMedia grid sorting", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grabbed" + "Grabbed": { + "comment": "(Short) History event filter\n(Short) Title of history event\nMedia grid sorting", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Grabbed" } } } }, - "Grid" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Grid" + "Grid": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Grid" } } } }, - "Header name" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Header name" + "Header name": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Header name" } } } }, - "Header value" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Header value" + "Header value": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Header value" } } } }, - "Headers" : { - "comment" : "HTTP Headers", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Headers" + "Headers": { + "comment": "HTTP Headers", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Headers" } } } }, - "Health Issue" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Health Issue" + "Health Issue": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Health Issue" } } } }, - "Health Restored" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Health Restored" + "Health Restored": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Health Restored" } } } }, - "Hide Specials" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hide Specials" + "Hide Specials": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hide Specials" } } } }, - "History" : { - "comment" : "Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "History" + "History": { + "comment": "Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "History" } } } }, - "Hold on, this may take a moment." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hold on, this may take a moment." + "Hold on, this may take a moment.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hold on, this may take a moment." } } } }, - "Home" : { - "comment" : "(Preferences) Home tab", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Home" + "Home": { + "comment": "(Preferences) Home tab", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Home" } } } }, - "Icons" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Icons" + "Icons": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Icons" } } } }, - "Identifier" : { - "comment" : "Match type of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Identifier" + "Identifier": { + "comment": "Match type of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Identifier" } } } }, - "Ignored" : { - "comment" : "(Short) History event filter\n(Short) Title of history event", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ignored" + "Ignored": { + "comment": "(Short) History event filter\n(Short) Title of history event", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Ignored" } } } }, - "Import" : { - "comment" : "(Short) Importing a queue task", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Import" + "Import": { + "comment": "(Short) Importing a queue task", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Import" } } } }, - "Import Blocked" : { - "comment" : "(Short) State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Import Blocked" + "Import Blocked": { + "comment": "(Short) State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Import Blocked" } } } }, - "Import Completed" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Import Completed" + "Import Completed": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Import Completed" } } } }, - "Import Pending" : { - "comment" : "(Short) State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Import Pending" + "Import Pending": { + "comment": "(Short) State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Import Pending" } } } }, - "Import Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Import Queued" + "Import Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Import Queued" } } } }, - "Imported" : { - "comment" : "(Short) History event filter\n(Short) Title of history event", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Imported" + "Imported": { + "comment": "(Short) History event filter\n(Short) Title of history event", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Imported" } } } }, - "Importing" : { - "comment" : "(Short) State of task in queue\nState of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Importing" + "Importing": { + "comment": "(Short) State of task in queue\nState of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Importing" } } } }, - "In Cinemas" : { - "comment" : "Media status label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "In Cinemas" + "In Cinemas": { + "comment": "Media status label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "In Cinemas" } } } }, - "Inactive" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inactive" + "Inactive": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Inactive" } } } }, - "Include Warnings" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Include Warnings" + "Include Warnings": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Include Warnings" } } } }, - "indexer" : { - "comment" : "Fallback for indexer name within mid-sentence", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "indexer" + "indexer": { + "comment": "Fallback for indexer name within mid-sentence", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "indexer" } } } }, - "Indexer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Indexer" + "Indexer": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Indexer" } } } }, - "Information" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Information" + "Information": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Information" } } } }, - "Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instance" + "Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Instance" } } } }, - "Instance URL is not valid: %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instance URL is not valid: %@" + "Instance URL is not valid: %@": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Instance URL is not valid: %@" } } } }, - "Instances" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Instances" + "Instances": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Instances" } } } }, - "Integrations" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Integrations" + "Integrations": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Integrations" } } } }, - "Interactive" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Interactive" + "Interactive": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Interactive" } } } }, - "Interactive Search" : { - "comment" : "Source of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Interactive Search" + "Interactive Search": { + "comment": "Source of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Interactive Search" } } } }, - "Invalid Instance Label" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Invalid Instance Label" + "Invalid Instance Label": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Invalid Instance Label" } } } }, - "Invalid URL" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Invalid URL" + "Invalid URL": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Invalid URL" } } } }, - "Is this running on Windows?" : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Is this running on Windows?" + "Is this running on Windows?": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Is this running on Windows?" } } } }, - "Issues" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Issues" + "Issues": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Issues" } } } }, - "Join the Discord" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Join the Discord" + "Join the Discord": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Join the Discord" } } } }, - "Just now" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Just now" + "Just now": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Just now" } } } }, - "Just testing your patience." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Just testing your patience." + "Just testing your patience.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Just testing your patience." } } } }, - "Label" : { - "comment" : "Instance label/name", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Label" + "Label": { + "comment": "Instance label/name", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Label" } } } }, - "Language" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Language" + "Language": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Language" } } } }, - "Languages" : { - "comment" : "Metadata row label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Languages" + "Languages": { + "comment": "Metadata row label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Languages" } } } }, - "Last Season" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Last Season" + "Last Season": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Last Season" } } } }, - "Latest" : { - "comment" : "Media search scope", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Latest" + "Latest": { + "comment": "Media search scope", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Latest" } } } }, - "Leave a Review" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Leave a Review" + "Leave a Review": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Leave a Review" } } } }, - "Let's hope it's worth the wait." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Let's hope it's worth the wait." + "Let's hope it's worth the wait.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Let's hope it's worth the wait." } } } }, - "Light" : { - "comment" : "Light appearance/mode", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Light" + "Light": { + "comment": "Light appearance/mode", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Light" } } } }, - "Link" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Link" + "Link": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Link" } } } }, - "Link Copied" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Link Copied" + "Link Copied": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Link Copied" } } } }, - "Load More" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Load More" + "Load More": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Load More" } } } }, - "Loading..." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Loading..." + "Loading...": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Loading..." } } } }, - "Local Network Access Denied" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Local Network Access Denied" + "Local Network Access Denied": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Local Network Access Denied" } } } }, - "Local network access must be granted in %@ to connect to instances using private IP addresses." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Local network access must be granted in %@ to connect to instances using private IP addresses." + "Local network access must be granted in %@ to connect to instances using private IP addresses.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Local network access must be granted in %@ to connect to instances using private IP addresses." } } } }, - "Local network access must be granted in System Settings to connect to instances on private IP addresses." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Local network access must be granted in System Settings to connect to instances on private IP addresses." + "Local network access must be granted in System Settings to connect to instances on private IP addresses.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Local network access must be granted in System Settings to connect to instances on private IP addresses." } } } }, - "Long-press any file to delete it." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Long-press any file to delete it." + "Long-press any file to delete it.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Long-press any file to delete it." } } } }, - "Looking to [add a new movie](%@)?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Looking to [add a new movie](%@)?" + "Looking to [add a new movie](%@)?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Looking to [add a new movie](%@)?" } } } }, - "Looking to [add a new series](%@)?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Looking to [add a new series](%@)?" + "Looking to [add a new series](%@)?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Looking to [add a new series](%@)?" } } } }, - "Mail" : { - "comment" : "Localized name of Apple's Mail app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mail" + "Mail": { + "comment": "Localized name of Apple's Mail app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Mail" } } } }, - "Manual Import" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manual Import" + "Manual Import": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Manual Import" } } } }, - "Manual Interaction Required" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manual Interaction Required" + "Manual Interaction Required": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Manual Interaction Required" } } } }, - "Match Type" : { - "comment" : "Release match type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Match Type" + "Match Type": { + "comment": "Release match type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Match Type" } } } }, - "Media Type" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Media Type" + "Media Type": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Media Type" } } } }, - "Message" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Message" + "Message": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Message" } } } }, - "Metadata" : { - "comment" : "Type of the extra movie file", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metadata" + "Metadata": { + "comment": "Type of the extra movie file", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Metadata" } } } }, - "Midseason Finale" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Midseason Finale" + "Midseason Finale": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Midseason Finale" } } } }, - "Min. Availability" : { - "comment" : "Shorter version of Minimum Availability", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Min. Availability" + "Min. Availability": { + "comment": "Shorter version of Minimum Availability", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Min. Availability" } } } }, - "Minimum Availability" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Minimum Availability" + "Minimum Availability": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Minimum Availability" } } } }, - "Missing" : { - "comment" : "(Single word) Episode status label\nMedia grid filter\nState of media item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Missing" + "Missing": { + "comment": "(Single word) Episode status label\nMedia grid filter\nState of media item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Missing" } } } }, - "Missing Episodes" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Missing Episodes" + "Missing Episodes": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Missing Episodes" } } } }, - "Monitor" : { - "comment" : "Label of picker of what to monitor (movie, collection, episodes, etc.)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monitor" + "Monitor": { + "comment": "Label of picker of what to monitor (movie, collection, episodes, etc.)", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monitor" } } } }, - "Monitor New Seasons" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monitor New Seasons" + "Monitor New Seasons": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monitor New Seasons" } } } }, - "Monitor Specials" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monitor Specials" + "Monitor Specials": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monitor Specials" } } } }, - "Monitored" : { - "comment" : "Media grid filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monitored" + "Monitored": { + "comment": "Media grid filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monitored" } } } }, - "Monitored Search Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monitored Search Queued" + "Monitored Search Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monitored Search Queued" } } } }, - "Monochrome" : { - "comment" : "Name of the 'Monochrome' theme", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Monochrome" + "Monochrome": { + "comment": "Name of the 'Monochrome' theme", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Monochrome" } } } }, - "Move Files" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Move Files" + "Move Files": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Move Files" } } } }, - "Move the movie files to \"%@\"?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Move the movie files to \"%@\"?" + "Move the movie files to \"%@\"?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Move the movie files to \"%@\"?" } } } }, - "Move the series files to \"%@\"?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Move the series files to \"%@\"?" + "Move the series files to \"%@\"?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Move the series files to \"%@\"?" } } } }, - "Movie" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie" + "Movie": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie" } } } }, - "Movie + Collection" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie + Collection" + "Movie + Collection": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie + Collection" } } } }, - "Movie Added" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Added" + "Movie Added": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Added" } } } }, - "Movie Deleted" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Deleted" + "Movie Deleted": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Deleted" } } } }, - "Movie Downloading" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Downloading" + "Movie Downloading": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Downloading" } } } }, - "Movie File Deleted" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie File Deleted" + "Movie File Deleted": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie File Deleted" } } } }, - "Movie file was renamed." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie file was renamed." + "Movie file was renamed.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie file was renamed." } } } }, - "Movie has no files." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie has no files." + "Movie has no files.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie has no files." } } } }, - "Movie has no history." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie has no history." + "Movie has no history.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie has no history." } } } }, - "Movie Imported" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Imported" + "Movie Imported": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Imported" } } } }, - "Movie imported from folder." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie imported from folder." + "Movie imported from folder.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie imported from folder." } } } }, - "Movie Renamed" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Renamed" + "Movie Renamed": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Renamed" } } } }, - "Movie Search Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Search Queued" + "Movie Search Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Search Queued" } } } }, - "Movie Upgraded" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Upgraded" + "Movie Upgraded": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Upgraded" } } } }, - "Movies" : { - "comment" : "Plural. Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movies" + "Movies": { + "comment": "Plural. Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movies" } } } }, - "Multi-Episode" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Multi-Episode" + "Multi-Episode": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Multi-Episode" } } } }, - "Multilingual" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Multilingual" + "Multilingual": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Multilingual" } } } }, - "Music" : { - "comment" : "Localized name of Apple's Music app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Music" + "Music": { + "comment": "Localized name of Apple's Music app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Music" } } } }, - "Network" : { - "comment" : "The network that airs the show", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Network" + "Network": { + "comment": "The network that airs the show", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Network" } } } }, - "New Seasons" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "New Seasons" + "New Seasons": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "New Seasons" } } } }, - "Next Airing" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Next Airing" + "Next Airing": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Next Airing" } } } }, - "No" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No" + "No": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No" } } } }, - "No %@ Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No %@ Instance" + "No %@ Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No %@ Instance" } } } }, - "No Automatic Search" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Automatic Search" + "No Automatic Search": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Automatic Search" } } } }, - "No Events" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Events" + "No Events": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Events" } } } }, - "No Events Match" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Events Match" + "No Events Match": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Events Match" } } } }, - "No events match the selected filters." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No events match the selected filters." + "No events match the selected filters.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No events match the selected filters." } } } }, - "No importable files found." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No importable files found." + "No importable files found.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No importable files found." } } } }, - "No Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Instance" + "No Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Instance" } } } }, - "No Internet Connection" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Internet Connection" + "No Internet Connection": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Internet Connection" } } } }, - "No Movies Match" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Movies Match" + "No Movies Match": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Movies Match" } } } }, - "No movies match the selected filters." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No movies match the selected filters." + "No movies match the selected filters.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No movies match the selected filters." } } } }, - "No Recent Tasks" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Recent Tasks" + "No Recent Tasks": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Recent Tasks" } } } }, - "No Releases Found" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Releases Found" + "No Releases Found": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Releases Found" } } } }, - "No releases found for \"%@\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No releases found for \"%@\"." + "No releases found for \"%@\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No releases found for \"%@\"." } } } }, - "No Releases Match" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Releases Match" + "No Releases Match": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Releases Match" } } } }, - "No releases match \"%@\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No releases match \"%@\"." + "No releases match \"%@\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No releases match \"%@\"." } } } }, - "No releases match the selected filters and \"%@\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No releases match the selected filters and \"%@\"." + "No releases match the selected filters and \"%@\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No releases match the selected filters and \"%@\"." } } } }, - "No releases match the selected filters." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No releases match the selected filters." + "No releases match the selected filters.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No releases match the selected filters." } } } }, - "No Results for \"%@\"" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Results for \"%@\"" + "No Results for \"%@\"": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Results for \"%@\"" } } } }, - "No Series Match" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Series Match" + "No Series Match": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Series Match" } } } }, - "No series match the selected filters." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No series match the selected filters." + "No series match the selected filters.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No series match the selected filters." } } } }, - "None" : { - "comment" : "Movie monitoring option\nSeries monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "None" + "None": { + "comment": "Movie monitoring option\nSeries monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "None" } } } }, - "Not Subscribed" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Not Subscribed" + "Not Subscribed": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Not Subscribed" } } } }, - "Notes" : { - "comment" : "Localized name of Apple's Notes app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notes" + "Notes": { + "comment": "Localized name of Apple's Notes app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notes" } } } }, - "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." + "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." } } } }, - "NOTIFICATION_APPLICATION_UPDATE" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ Updated" + "NOTIFICATION_APPLICATION_UPDATE": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ Updated" } } } }, - "NOTIFICATION_EPISODE_DOWNLOAD" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Downloaded on %@" + "NOTIFICATION_EPISODE_DOWNLOAD": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Downloaded on %@" } } } }, - "NOTIFICATION_EPISODE_DOWNLOAD_BODY" : { - "comment" : "Notification body (series, season, episode)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (S%@ E%@)" + "NOTIFICATION_EPISODE_DOWNLOAD_BODY": { + "comment": "Notification body (series, season, episode)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (S%@ E%@)" } } } }, - "NOTIFICATION_EPISODE_FILE_DELETED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode File Deleted on %@" + "NOTIFICATION_EPISODE_FILE_DELETED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode File Deleted on %@" } } } }, - "NOTIFICATION_EPISODE_FILE_DELETED_BODY" : { - "comment" : "Notification body (series, season, episode)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (S%@ E%@)" + "NOTIFICATION_EPISODE_FILE_DELETED_BODY": { + "comment": "Notification body (series, season, episode)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (S%@ E%@)" } } } }, - "NOTIFICATION_EPISODE_GRAB" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Downloading on %@" + "NOTIFICATION_EPISODE_GRAB": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Downloading on %@" } } } }, - "NOTIFICATION_EPISODE_GRAB_SUBTITLE" : { - "comment" : "Notification subtitle (series, season, episode)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (S%@ E%@)" + "NOTIFICATION_EPISODE_GRAB_SUBTITLE": { + "comment": "Notification subtitle (series, season, episode)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (S%@ E%@)" } } } }, - "NOTIFICATION_EPISODE_UPGRADE" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Episode Upgraded on %@" + "NOTIFICATION_EPISODE_UPGRADE": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Episode Upgraded on %@" } } } }, - "NOTIFICATION_EPISODE_UPGRADE_BODY" : { - "comment" : "Notification body (old quality, new quality)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Upgraded from %1$@ to %2$@" + "NOTIFICATION_EPISODE_UPGRADE_BODY": { + "comment": "Notification body (old quality, new quality)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Upgraded from %1$@ to %2$@" } } } }, - "NOTIFICATION_EPISODE_UPGRADE_SUBTITLE" : { - "comment" : "Notification subtitle (series, season, episode)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (S%@ E%@)" + "NOTIFICATION_EPISODE_UPGRADE_SUBTITLE": { + "comment": "Notification subtitle (series, season, episode)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (S%@ E%@)" } } } }, - "NOTIFICATION_EPISODES_DOWNLOAD" : { - "comment" : "Notification title (instance name, episode count)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%2$@ Episodes Downloaded on %1$@" + "NOTIFICATION_EPISODES_DOWNLOAD": { + "comment": "Notification title (instance name, episode count)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%2$@ Episodes Downloaded on %1$@" } } } }, - "NOTIFICATION_EPISODES_DOWNLOAD_BODY" : { - "comment" : "Notification body (series, season)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (Season %@)" + "NOTIFICATION_EPISODES_DOWNLOAD_BODY": { + "comment": "Notification body (series, season)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (Season %@)" } } } }, - "NOTIFICATION_EPISODES_GRAB" : { - "comment" : "Notification title (instance name, episode count)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%2$@ Episodes Downloading on %1$@" + "NOTIFICATION_EPISODES_GRAB": { + "comment": "Notification title (instance name, episode count)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%2$@ Episodes Downloading on %1$@" } } } }, - "NOTIFICATION_EPISODES_GRAB_BODY" : { - "comment" : "Notification body (quality, indexer)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Downloading %@ from %@" + "NOTIFICATION_EPISODES_GRAB_BODY": { + "comment": "Notification body (quality, indexer)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Downloading %@ from %@" } } } }, - "NOTIFICATION_EPISODES_GRAB_SUBTITLE" : { - "comment" : "Notification subtitle (series, season)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (Season %@)" + "NOTIFICATION_EPISODES_GRAB_SUBTITLE": { + "comment": "Notification subtitle (series, season)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (Season %@)" } } } }, - "NOTIFICATION_HEALTH" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Health Issue on %@" + "NOTIFICATION_HEALTH": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Health Issue on %@" } } } }, - "NOTIFICATION_HEALTH_RESTORED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Health Issue Resolved on %@" + "NOTIFICATION_HEALTH_RESTORED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Health Issue Resolved on %@" } } } }, - "NOTIFICATION_MANUAL_INTERACTION_REQUIRED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manual Interaction Required on %@" + "NOTIFICATION_MANUAL_INTERACTION_REQUIRED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Manual Interaction Required on %@" } } } }, - "NOTIFICATION_MOVIE_ADDED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Added on %@" + "NOTIFICATION_MOVIE_ADDED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Added on %@" } } } }, - "NOTIFICATION_MOVIE_ADDED_BODY" : { - "comment" : "Notification body (title, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_ADDED_BODY": { + "comment": "Notification body (title, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_DELETED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Deleted on %@" + "NOTIFICATION_MOVIE_DELETED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Deleted on %@" } } } }, - "NOTIFICATION_MOVIE_DELETED_BODY" : { - "comment" : "Notification body (title, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_DELETED_BODY": { + "comment": "Notification body (title, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_DOWNLOAD" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Downloaded on %@" + "NOTIFICATION_MOVIE_DOWNLOAD": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Downloaded on %@" } } } }, - "NOTIFICATION_MOVIE_DOWNLOAD_BODY" : { - "comment" : "Notification body (title, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_DOWNLOAD_BODY": { + "comment": "Notification body (title, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_FILE_DELETED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie File Deleted on %@" + "NOTIFICATION_MOVIE_FILE_DELETED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie File Deleted on %@" } } } }, - "NOTIFICATION_MOVIE_FILE_DELETED_BODY" : { - "comment" : "Notification body (movie, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_FILE_DELETED_BODY": { + "comment": "Notification body (movie, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_GRAB" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Downloading on %@" + "NOTIFICATION_MOVIE_GRAB": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Downloading on %@" } } } }, - "NOTIFICATION_MOVIE_GRAB_BODY" : { - "comment" : "Notification body (quality, indexer)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Downloading %@ from %@" + "NOTIFICATION_MOVIE_GRAB_BODY": { + "comment": "Notification body (quality, indexer)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Downloading %@ from %@" } } } }, - "NOTIFICATION_MOVIE_GRAB_SUBTITLE" : { - "comment" : "Notification subtitle (movie, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_GRAB_SUBTITLE": { + "comment": "Notification subtitle (movie, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_UPGRADE" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Movie Upgraded on %@" + "NOTIFICATION_MOVIE_UPGRADE": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Movie Upgraded on %@" } } } }, - "NOTIFICATION_MOVIE_UPGRADE_BODY" : { - "comment" : "Notification body (old quality, new quality)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Upgraded from %1$@ to %2$@" + "NOTIFICATION_MOVIE_UPGRADE_BODY": { + "comment": "Notification body (old quality, new quality)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Upgraded from %1$@ to %2$@" } } } }, - "NOTIFICATION_MOVIE_UPGRADE_SUBTITLE" : { - "comment" : "Notification subtitle (movie, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_MOVIE_UPGRADE_SUBTITLE": { + "comment": "Notification subtitle (movie, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_SERIES_ADDED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Added on %@" + "NOTIFICATION_SERIES_ADDED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Added on %@" } } } }, - "NOTIFICATION_SERIES_ADDED_BODY" : { - "comment" : "Notification body (movie, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_SERIES_ADDED_BODY": { + "comment": "Notification body (movie, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_SERIES_DELETED" : { - "comment" : "Notification title (instance name)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Deleted on %@" + "NOTIFICATION_SERIES_DELETED": { + "comment": "Notification title (instance name)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Deleted on %@" } } } }, - "NOTIFICATION_SERIES_DELETED_BODY" : { - "comment" : "Notification body (series, year)", - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@ (%@)" + "NOTIFICATION_SERIES_DELETED_BODY": { + "comment": "Notification body (series, year)", + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ (%@)" } } } }, - "NOTIFICATION_TEST" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Test Notification" + "NOTIFICATION_TEST": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Test Notification" } } } }, - "NOTIFICATION_TEST_BODY" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This is a test notification." + "NOTIFICATION_TEST_BODY": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This is a test notification." } } } }, - "Notifications" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications" + "Notifications": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notifications" } } } }, - "Notifications are disabled, please enable them in %@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications are disabled, please enable them in %@." + "Notifications are disabled, please enable them in %@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notifications are disabled, please enable them in %@." } } } }, - "Notifications require a subscription to %@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications require a subscription to %@." + "Notifications require a subscription to %@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notifications require a subscription to %@." } } } }, - "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." : { - "comment" : "1 = CloudKit status", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." + "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@).": { + "comment": "1 = CloudKit status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." } } } }, - "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." + "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." } } } }, - "OK" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "OK" + "OK": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "OK" } } } }, - "Open %@" : { - "comment" : "Open (app name)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open %@" + "Open %@": { + "comment": "Open (app name)", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open %@" } } } }, - "Open ${target}" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open ${target}" + "Open ${target}": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open ${target}" } } } }, - "Open in %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open in %@" + "Open in %@": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open in %@" } } } }, - "Open In..." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open In..." + "Open In...": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open In..." } } } }, - "Open Ruddarr" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open Ruddarr" + "Open Ruddarr": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Ruddarr" } } } }, - "Open Website" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Open Website" + "Open Website": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Website" } } } }, - "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." + "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." } } } }, - "Original" : { - "comment" : "Release filter (original language)", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Original" + "Original": { + "comment": "Release filter (original language)", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Original" } } } }, - "Orphaned" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Orphaned" + "Orphaned": { + "comment": "Command status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Orphaned" } } } }, - "Other" : { - "comment" : "Type of the extra movie file", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Other" + "Other": { + "comment": "Type of the extra movie file", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Other" } } } }, - "Password" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Password" + "Password": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Password" } } } }, - "Paste" : { - "comment" : "Paste from clipboard", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Paste" + "Paste": { + "comment": "Paste from clipboard", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Paste" } } } }, - "Paused" : { - "comment" : "(Short) State of task in queue\nStatus of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Paused" + "Paused": { + "comment": "(Short) State of task in queue\nStatus of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Paused" } } } }, - "Peers" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Peers" + "Peers": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Peers" } } } }, - "Pending" : { - "comment" : "(Short) State of task in queue\nStatus of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pending" + "Pending": { + "comment": "(Short) State of task in queue\nStatus of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pending" } } } }, - "Permanently erase the folder and its contents." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Permanently erase the folder and its contents." + "Permanently erase the folder and its contents.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Permanently erase the folder and its contents." } } } }, - "Physical Release" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Physical Release" + "Physical Release": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Physical Release" } } } }, - "Pilot Episode" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pilot Episode" + "Pilot Episode": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pilot Episode" } } } }, - "Please check your internet connection and try again." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Please check your internet connection and try again." + "Please check your internet connection and try again.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Please check your internet connection and try again." } } } }, - "Podcasts" : { - "comment" : "Localized name of Apple's Podcasts app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Podcasts" + "Podcasts": { + "comment": "Localized name of Apple's Podcasts app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Podcasts" } } } }, - "Popular This Week" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Popular This Week" + "Popular This Week": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Popular This Week" } } } }, - "Posters" : { - "comment" : "Grid item display style", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Posters" + "Posters": { + "comment": "Grid item display style", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Posters" } } } }, - "Preferences" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Preferences" + "Preferences": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Preferences" } } } }, - "Preferred language and other app-related settings can be configured in the [System Settings](#link)." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Preferred language and other app-related settings can be configured in the [System Settings](#link)." + "Preferred language and other app-related settings can be configured in the [System Settings](#link).": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Preferred language and other app-related settings can be configured in the [System Settings](#link)." } } } }, - "Premieres" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Premieres" + "Premieres": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Premieres" } } } }, - "Preserve" : { - "comment" : "(Preferences) Preserve release filters", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Preserve" + "Preserve": { + "comment": "(Preferences) Preserve release filters", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Preserve" } } } }, - "Prevent from being readded to library by lists." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Prevent from being readded to library by lists." + "Prevent from being readded to library by lists.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Prevent from being readded to library by lists." } } } }, - "Previous Airing" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Previous Airing" + "Previous Airing": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Previous Airing" } } } }, - "Proper" : { - "comment" : "The PROPER flag", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Proper" + "Proper": { + "comment": "The PROPER flag", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Proper" } } } }, - "Protocol" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Protocol" + "Protocol": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Protocol" } } } }, - "Provide a detailed description of the issue along with the exact steps to reproduce it." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Provide a detailed description of the issue along with the exact steps to reproduce it." + "Provide a detailed description of the issue along with the exact steps to reproduce it.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Provide a detailed description of the issue along with the exact steps to reproduce it." } } } }, - "Published" : { - "comment" : "Release publish date", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Published" + "Published": { + "comment": "Release publish date", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Published" } } } }, - "Quality" : { - "comment" : "Release filter\nShort version of Quality Profile", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Quality" + "Quality": { + "comment": "Release filter\nShort version of Quality Profile", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Quality" } } } }, - "Quality Profile" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Quality Profile" + "Quality Profile": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Quality Profile" } } } }, - "Queued" : { - "comment" : "(Short) State of task in queue\nStatus of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Queued" + "Queued": { + "comment": "(Short) State of task in queue\nCommand status\nStatus of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Queued" } } } }, - "Queues Empty" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Queues Empty" + "Queues Empty": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Queues Empty" } } } }, - "Rating" : { - "comment" : "Media grid sorting\nMedia search scope", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Rating" + "Rating": { + "comment": "Media grid sorting\nMedia search scope", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Rating" } } } }, - "Recent Episodes" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Recent Episodes" + "Recent Episodes": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Recent Episodes" } } } }, - "Refresh" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Refresh" + "Refresh": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Refresh" } } } }, - "Refresh Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Refresh Queued" + "Refresh Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Refresh Queued" } } } }, - "Release Downloading" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Downloading" + "Release Downloading": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Downloading" } } } }, - "Release Filters" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Filters" + "Release Filters": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Filters" } } } }, - "Release Grabbed" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Grabbed" + "Release Grabbed": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Grabbed" } } } }, - "Release Group" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Group" + "Release Group": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Group" } } } }, - "Release Notes" : { - "comment" : "Also know as changelog", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Notes" + "Release Notes": { + "comment": "Also know as changelog", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Notes" } } } }, - "Release Push" : { - "comment" : "Source of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Push" + "Release Push": { + "comment": "Source of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Push" } } } }, - "Release Rejected" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Rejected" + "Release Rejected": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Rejected" } } } }, - "Release Type" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Release Type" + "Release Type": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Type" } } } }, - "Released" : { - "comment" : "Media status label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Released" + "Released": { + "comment": "Media status label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Released" } } } }, - "Relevant" : { - "comment" : "Media search scope", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Relevant" + "Relevant": { + "comment": "Media search scope", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Relevant" } } } }, - "Remove" : { - "comment" : "(Short) Removing a queue task", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Remove" + "Remove": { + "comment": "(Short) Removing a queue task", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Remove" } } } }, - "Remove from Client" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Remove from Client" + "Remove from Client": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Remove from Client" } } } }, - "Remove Task" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Remove Task" + "Remove Task": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Remove Task" } } } }, - "Renamed" : { - "comment" : "(Short) History event filter\n(Short) Title of history event", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Renamed" + "Renamed": { + "comment": "(Short) History event filter\n(Short) Title of history event", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Renamed" } } } }, - "Repack" : { - "comment" : "The REPACK flag", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Repack" + "Repack": { + "comment": "The REPACK flag", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Repack" } } } }, - "Report an Issue" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Report an Issue" + "Report an Issue": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Report an Issue" } } } }, - "Reset" : { - "comment" : "(Preferences) Reset release filters", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reset" + "Reset": { + "comment": "(Preferences) Reset release filters", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset" } } } }, - "Reset All Settings" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Reset All Settings" + "Reset All Settings": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset All Settings" } } } }, - "Resolution" : { - "comment" : "Video file resolution", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Resolution" + "Resolution": { + "comment": "Video file resolution", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Resolution" } } } }, - "Response Decoding Error" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Response Decoding Error" + "Response Decoding Error": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Response Decoding Error" } } } }, - "Result" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Result" + "Result": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Result" } } } }, - "Retry" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Retry" + "Retry": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Retry" } } } }, - "Revoked" : { - "comment" : "Status of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Revoked" + "Revoked": { + "comment": "Status of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Revoked" } } } }, - "Root Folder" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Root Folder" + "Root Folder": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Root Folder" } } } }, - "Running" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Running" + "Running": { + "comment": "Command status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Running" } } } }, - "Runtime" : { - "comment" : "Video runtime", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Runtime" + "Runtime": { + "comment": "Video runtime", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Runtime" } } } }, - "Save" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Save" + "Save": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Save" } } } }, - "Scan Type" : { - "comment" : "Video scan Type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Scan Type" + "Scan Type": { + "comment": "Video scan Type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Scan Type" } } } }, - "Score" : { - "comment" : "Custom score of media file", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Score" + "Score": { + "comment": "Custom score of media file", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Score" } } } }, - "Search" : { - "comment" : "Source of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search" + "Search": { + "comment": "Source of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search" } } } }, - "Search for Movie" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search for Movie" + "Search for Movie": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search for Movie" } } } }, - "Search for movie with ${name}" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search for movie with ${name}" + "Search for movie with ${name}": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search for movie with ${name}" } } } }, - "Search for Replacement" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search for Replacement" + "Search for Replacement": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search for Replacement" } } } }, - "Search for TV Series" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search for TV Series" + "Search for TV Series": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search for TV Series" } } } }, - "Search for TV series with ${name}" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search for TV series with ${name}" + "Search for TV series with ${name}": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search for TV series with ${name}" } } } }, - "Search Monitored" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Search Monitored" + "Search Monitored": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search Monitored" } } } }, - "Searching..." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Searching..." + "Searching...": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Searching..." } } } }, - "Season %lld" : { - "localizations" : { - "en" : { - "variations" : { - "plural" : { - "one" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season %lld" + "Season %lld": { + "comment": "Season number for command subject", + "localizations": { + "en": { + "variations": { + "plural": { + "one": { + "stringUnit": { + "state": "translated", + "value": "Season %lld" } }, - "other" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season %lld" + "other": { + "stringUnit": { + "state": "translated", + "value": "Season %lld" } } } @@ -4590,1157 +4597,1157 @@ } } }, - "Season Files Deleted" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Files Deleted" + "Season Files Deleted": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Files Deleted" } } } }, - "Season Finale" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Finale" + "Season Finale": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Finale" } } } }, - "Season Folders" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Folders" + "Season Folders": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Folders" } } } }, - "Season Pack" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Pack" + "Season Pack": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Pack" } } } }, - "Season Premiere" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Premiere" + "Season Premiere": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Premiere" } } } }, - "Season Search Queued" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Season Search Queued" + "Season Search Queued": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Season Search Queued" } } } }, - "Seasons" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Seasons" + "Seasons": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Seasons" } } } }, - "Seeders" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Seeders" + "Seeders": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Seeders" } } } }, - "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." + "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." } } } }, - "Series" : { - "comment" : "Plural. Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series" + "Series": { + "comment": "Plural. Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series" } } } }, - "Series Added" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Added" + "Series Added": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Added" } } } }, - "Series Deleted" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Deleted" + "Series Deleted": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Deleted" } } } }, - "Series Finale" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Finale" + "Series Finale": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Finale" } } } }, - "Series imported from folder." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series imported from folder." + "Series imported from folder.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series imported from folder." } } } }, - "Series Not Monitored" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Not Monitored" + "Series Not Monitored": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Not Monitored" } } } }, - "Series Premiere" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Premiere" + "Series Premiere": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Premiere" } } } }, - "Series Type" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Series Type" + "Series Type": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Series Type" } } } }, - "Server Error Response" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server Error Response" + "Server Error Response": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Server Error Response" } } } }, - "Server returned %lld status code." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Server returned %lld status code." + "Server returned %lld status code.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Server returned %lld status code." } } } }, - "Settings" : { - "comment" : "Tab/sidebar menu item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Settings" + "Settings": { + "comment": "Tab/sidebar menu item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Settings" } } } }, - "Share App" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Share App" + "Share App": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Share App" } } } }, - "Show Advanced Settings" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Show Advanced Settings" + "Show Advanced Settings": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Advanced Settings" } } } }, - "Show All Tasks" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Show All Tasks" + "Show All Tasks": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show All Tasks" } } } }, - "Single Episode" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Single Episode" + "Single Episode": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Single Episode" } } } }, - "Slow Instance" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Slow Instance" + "Slow Instance": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Slow Instance" } } } }, - "Some releases are hidden by the selected filters." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Some releases are hidden by the selected filters." + "Some releases are hidden by the selected filters.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Some releases are hidden by the selected filters." } } } }, - "Something Went Wrong" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Something Went Wrong" + "Something Went Wrong": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Something Went Wrong" } } } }, - "Sort By" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sort By" + "Sort By": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sort By" } } } }, - "Source" : { - "comment" : "Release source", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Source" + "Source": { + "comment": "Release source", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Source" } } } }, - "Special" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Special" + "Special": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Special" } } } }, - "Specials" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Specials" + "Specials": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Specials" } } } }, - "Standard" : { - "comment" : "Series type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Standard" + "Standard": { + "comment": "Series type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Standard" } } } }, - "Started" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Started" + "Started": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Started" } } } }, - "Status" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Status" + "Status": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Status" } } } }, - "Still searching for releases." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Still searching for releases." + "Still searching for releases.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Still searching for releases." } } } }, - "Streams" : { - "comment" : "Audio stream count", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Streams" + "Streams": { + "comment": "Audio stream count", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Streams" } } } }, - "Studio" : { - "comment" : "The studio that produces the movie", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Studio" + "Studio": { + "comment": "The studio that produces the movie", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Studio" } } } }, - "Submit" : { - "comment" : "Send bug report", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Submit" + "Submit": { + "comment": "Send bug report", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Submit" } } } }, - "Subscription" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Subscription" + "Subscription": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Subscription" } } } }, - "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." + "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." } } } }, - "Subtitles" : { - "comment" : "Type of the extra movie file", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Subtitles" + "Subtitles": { + "comment": "Type of the extra movie file", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Subtitles" } } } }, - "System" : { - "comment" : "Preferences section header", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "System" + "System": { + "comment": "Preferences section header", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "System" } } } }, - "System Settings" : { - "comment" : "Settings app name", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "System Settings" + "System Settings": { + "comment": "Settings app name", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "System Settings" } } } }, - "System Settings > Notifications > %@" : { - "comment" : "macOS notifications path", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "System Settings > Notifications > %@" + "System Settings > Notifications > %@": { + "comment": "macOS notifications path", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "System Settings > Notifications > %@" } } } }, - "System Settings > Privacy & Security > Local Network" : { - "comment" : "macOS local network path", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "System Settings > Privacy & Security > Local Network" + "System Settings > Privacy & Security > Local Network": { + "comment": "macOS local network path", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "System Settings > Privacy & Security > Local Network" } } } }, - "Tab" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tab" + "Tab": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tab" } } } }, - "Tags" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tags" + "Tags": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tags" } } } }, - "Tasks" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tasks" + "TBA": { + "comment": "(Short, 3-6 characters) Conveying unannounced", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "TBA" } } } }, - "TBA" : { - "comment" : "(Short, 3-6 characters) Conveying unannounced", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "TBA" + "TestFlight for macOS": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "TestFlight for macOS" } } } }, - "TestFlight for macOS" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "TestFlight for macOS" + "The API Key can be found in the web interface under \"Settings > General > Security\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The API Key can be found in the web interface under \"Settings > General > Security\"." } } } }, - "The API Key can be found in the web interface under \"Settings > General > Security\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The API Key can be found in the web interface under \"Settings > General > Security\"." + "The credentials will be encoded and added as an \"Authorization\" header.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The credentials will be encoded and added as an \"Authorization\" header." } } } }, - "The credentials will be encoded and added as an \"Authorization\" header." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The credentials will be encoded and added as an \"Authorization\" header." + "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" } } } }, - "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" + "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" } } } }, - "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" + "The URL used to access the %@ web interface.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The URL used to access the %@ web interface." } } } }, - "The URL used to access the %@ web interface." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The URL used to access the %@ web interface." + "This will permanently erase all episode files of this season.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will permanently erase all episode files of this season." } } } }, - "This will permanently erase all episode files of this season." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This will permanently erase all episode files of this season." + "This will permanently erase the episode file.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will permanently erase the episode file." } } } }, - "This will permanently erase the episode file." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This will permanently erase the episode file." + "This will permanently erase the movie file.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will permanently erase the movie file." } } } }, - "This will permanently erase the movie file." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "This will permanently erase the movie file." + "Time flies when you're having fun.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Time flies when you're having fun." } } } }, - "Time flies when you're having fun." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Time flies when you're having fun." + "Title": { + "comment": "Match type of the release\nMedia grid sorting", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Title" } } } }, - "Title" : { - "comment" : "Match type of the release\nMedia grid sorting", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Title" + "To monitor a season or episode, the series itself must be monitored.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "To monitor a season or episode, the series itself must be monitored." } } } }, - "To monitor a season or episode, the series itself must be monitored." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "To monitor a season or episode, the series itself must be monitored." + "Today": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Today" } } } }, - "Today" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Today" + "Tomorrow": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tomorrow" } } } }, - "Tomorrow" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tomorrow" + "Torrent": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Torrent" } } } }, - "Torrent" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Torrent" + "Trailer": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Trailer" } } } }, - "Trailer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Trailer" + "Translate the App": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Translate the App" } } } }, - "Translate the App" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Translate the App" + "Try again later.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Try again later." } } } }, - "Try again later." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Try again later." + "Try holding your breath.": { + "comment": "Release search taunt", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Try holding your breath." } } } }, - "Try holding your breath." : { - "comment" : "Release search taunt", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Try holding your breath." + "Type": { + "comment": "Short version of Series Type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Type" } } } }, - "Type" : { - "comment" : "Short version of Series Type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Type" + "Unable to Import Automatically": { + "comment": "State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unable to Import Automatically" } } } }, - "Unable to Import Automatically" : { - "comment" : "State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unable to Import Automatically" + "Unaired": { + "comment": "(Single word) Episode status label", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unaired" } } } }, - "Unaired" : { - "comment" : "(Single word) Episode status label", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unaired" + "Unannounced": { + "comment": "Media status label\nMissing media title", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unannounced" } } } }, - "Unannounced" : { - "comment" : "Media status label\nMissing media title", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unannounced" + "Uncoded": { + "comment": "Label for uncoded languages", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Uncoded" } } } }, - "Uncoded" : { - "comment" : "Label for uncoded languages", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Uncoded" + "Undetermined": { + "comment": "Label for unknown/undetermined language", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Undetermined" } } } }, - "Undetermined" : { - "comment" : "Label for unknown/undetermined language", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Undetermined" + "Unknown": { + "comment": "(Short) State of task in queue\n(Short) Title of history event\nCommand status\nStatus of task in queue\nStatus of the app subscription", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unknown" } } } }, - "Unknown" : { - "comment" : "(Short) State of task in queue\n(Short) Title of history event\nStatus of task in queue\nStatus of the app subscription", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unknown" + "Unknown Event": { + "comment": "Title of history event type", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unknown Event" } } } }, - "Unknown Event" : { - "comment" : "Title of history event type", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unknown Event" + "Unknown event.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unknown event." } } } }, - "Unknown event." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unknown event." + "Unmonitor Specials": { + "comment": "Series monitoring option", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unmonitor Specials" } } } }, - "Unmonitor Specials" : { - "comment" : "Series monitoring option", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unmonitor Specials" + "Unmonitored": { + "comment": "Media grid filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unmonitored" } } } }, - "Unmonitored" : { - "comment" : "Media grid filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unmonitored" + "Unrated": { + "comment": "No age/audience rating available", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unrated" } } } }, - "Unrated" : { - "comment" : "No age/audience rating available", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unrated" + "Unreleased": { + "comment": "State of media item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unreleased" } } } }, - "Unreleased" : { - "comment" : "State of media item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unreleased" + "Unsupported URL: %@": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unsupported URL: %@" } } } }, - "Unsupported URL: %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unsupported URL: %@" + "Unwanted": { + "comment": "State of media item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unwanted" } } } }, - "Unwanted" : { - "comment" : "State of media item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Unwanted" + "Upcoming": { + "comment": "(Single word) Series status", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Upcoming" } } } }, - "Upcoming" : { - "comment" : "(Single word) Series status", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Upcoming" + "Upgrade to Sonarr v4.0.5 or newer.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Upgrade to Sonarr v4.0.5 or newer." } } } }, - "Upgrade to Sonarr v4.0.5 or newer." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Upgrade to Sonarr v4.0.5 or newer." + "URL": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "URL" } } } }, - "URL" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL" + "URL identified itself as a %@ instance, not a %@ instance.": { + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "URL identified itself as a %1$@ instance, not a %2$@ instance." } } } }, - "URL identified itself as a %@ instance, not a %@ instance." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "new", - "value" : "URL identified itself as a %1$@ instance, not a %2$@ instance." + "URL must start with \"http://\" or \"https://\".": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "URL must start with \"http://\" or \"https://\"." } } } }, - "URL must start with \"http://\" or \"https://\"." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL must start with \"http://\" or \"https://\"." + "URL Not Reachable": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "URL Not Reachable" } } } }, - "URL Not Reachable" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "URL Not Reachable" + "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." } } } }, - "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." + "Usenet": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Usenet" } } } }, - "Usenet" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Usenet" + "User Invoked Search": { + "comment": "Source of the release", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "User Invoked Search" } } } }, - "User Invoked Search" : { - "comment" : "Source of the release", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "User Invoked Search" + "Username": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Username" } } } }, - "Username" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Username" + "Version %@ (%@)": { + "comment": "$1 = version, $2 = build", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Version %1$@ (%2$@)" } } } }, - "Version %@ (%@)" : { - "comment" : "$1 = version, $2 = build", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Version %1$@ (%2$@)" + "Video": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Video" } } } }, - "Video" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Video" + "Waiting": { + "comment": "(Short) State of task in queue\nState of media item", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Waiting" } } } }, - "Waiting" : { - "comment" : "(Short) State of task in queue\nState of media item", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Waiting" + "Waiting to Import": { + "comment": "State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Waiting to Import" } } } }, - "Waiting to Import" : { - "comment" : "State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Waiting to Import" + "Waiting to Process": { + "comment": "State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Waiting to Process" } } } }, - "Waiting to Process" : { - "comment" : "State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Waiting to Process" + "Wanted": { + "comment": "Media grid filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Wanted" } } } }, - "Wanted" : { - "comment" : "Media grid filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wanted" + "Warning": { + "comment": "(Short) State of task in queue", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Warning" } } } }, - "Warning" : { - "comment" : "(Short) State of task in queue", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Warning" + "Watch": { + "comment": "Localized name of Apple's Watch app", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Watch" } } } }, - "Watch" : { - "comment" : "Localized name of Apple's Watch app", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Watch" + "Watch Trailer": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Watch Trailer" } } } }, - "Watch Trailer" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Watch Trailer" + "Website": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Website" } } } }, - "Website" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Website" + "Weight": { + "comment": "Release filter", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Weight" } } } }, - "Weight" : { - "comment" : "Release filter", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Weight" + "What happened?": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "What happened?" } } } }, - "What happened?" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "What happened?" + "What's New in %@": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "What's New in %@" } } } }, - "What's New in %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "What's New in %@" + "Whether to ignore the download, or remove it and its file(s) from the download client.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Whether to ignore the download, or remove it and its file(s) from the download client." } } } }, - "Whether to ignore the download, or remove it and its file(s) from the download client." : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Whether to ignore the download, or remove it and its file(s) from the download client." + "Wrong Instance Type": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Wrong Instance Type" } } } }, - "Wrong Instance Type" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Wrong Instance Type" + "Year": { + "comment": "Media grid sorting", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Year" } } } }, - "Year" : { - "comment" : "Media grid sorting", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Year" + "Yes": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Yes" } } } }, - "Yes" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Yes" + "Yesterday": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Yesterday" } } } }, - "Yesterday" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Yesterday" + "Searches": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Searches" } } } } }, - "version" : "1.0" -} \ No newline at end of file + "version": "1.0" +} diff --git a/Ruddarr/Views/ActivityView.swift b/Ruddarr/Views/ActivityView.swift index a5183f7d..455e6571 100644 --- a/Ruddarr/Views/ActivityView.swift +++ b/Ruddarr/Views/ActivityView.swift @@ -6,7 +6,7 @@ struct ActivityView: View { @State var sort: QueueSort = .init() @State var items: [QueueItem] = [] @State private var selectedItem: QueueItem? - @State var segment: ActivitySegment = .downloads + @State var segment: ActivitySegment = .searches @EnvironmentObject var settings: AppSettings @Environment(\.deviceType) private var deviceType @@ -15,19 +15,19 @@ struct ActivityView: View { NavigationStack { VStack(spacing: 0) { Picker("", selection: $segment) { + Text("Searches").tag(ActivitySegment.searches) Text("Downloads").tag(ActivitySegment.downloads) - Text("Tasks").tag(ActivitySegment.tasks) } .pickerStyle(.segmented) .padding(.horizontal) .padding(.top, 8) switch segment { - case .downloads: - downloadsContent - case .tasks: + case .searches: CommandsListView() .environmentObject(settings) + case .downloads: + downloadsContent } } .safeNavigationBarTitleDisplayMode(.inline) @@ -181,8 +181,8 @@ struct ActivityView: View { } enum ActivitySegment: Hashable { + case searches case downloads - case tasks } #Preview { From 4ee7e61cc622234ded897405098d84b50306c916 Mon Sep 17 00:00:00 2001 From: joptimus Date: Tue, 7 Apr 2026 23:26:48 -0500 Subject: [PATCH 16/20] clean up commands code to match existing queue patterns --- Ruddarr.xcodeproj/project.pbxproj | 6 - Ruddarr/Models/Commands/CommandStatus.swift | 104 ------------- Ruddarr/Models/Commands/Commands.swift | 142 ++++++++++++++---- Ruddarr/Views/Activity/CommandListItem.swift | 19 ++- Ruddarr/Views/Activity/CommandSheet.swift | 136 +++++++++++------ Ruddarr/Views/Activity/CommandsListView.swift | 22 +-- Tests/CommandsTests.swift | 130 ---------------- 7 files changed, 229 insertions(+), 330 deletions(-) delete mode 100644 Ruddarr/Models/Commands/CommandStatus.swift delete mode 100644 Tests/CommandsTests.swift diff --git a/Ruddarr.xcodeproj/project.pbxproj b/Ruddarr.xcodeproj/project.pbxproj index e098cd14..6fbc5ead 100644 --- a/Ruddarr.xcodeproj/project.pbxproj +++ b/Ruddarr.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 1AFC24FA2F82B753009FF858 /* Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24F82F82B753009FF858 /* Commands.swift */; }; - 1AFC24FB2F82B753009FF858 /* CommandStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24F92F82B753009FF858 /* CommandStatus.swift */; }; 1AFC24FF2F82B789009FF858 /* CommandSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */; }; 1AFC25002F82B789009FF858 /* CommandsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */; }; 1AFC25012F82B789009FF858 /* CommandListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */; }; @@ -266,11 +265,9 @@ /* Begin PBXFileReference section */ 1AFC24F82F82B753009FF858 /* Commands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Commands.swift; path = Commands/Commands.swift; sourceTree = ""; }; - 1AFC24F92F82B753009FF858 /* CommandStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CommandStatus.swift; path = Commands/CommandStatus.swift; sourceTree = ""; }; 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandListItem.swift; sourceTree = ""; }; 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandSheet.swift; sourceTree = ""; }; 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsListView.swift; sourceTree = ""; }; - 1AFC25022F832036009FF858 /* CommandsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsTests.swift; sourceTree = ""; }; 2B949CE42CC92C970088B1A8 /* sonarr-history.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "sonarr-history.json"; sourceTree = ""; }; 2B949CE62CC92F320088B1A8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = ""; }; @@ -559,7 +556,6 @@ BB000000000000000000AAA4 /* Tests */ = { isa = PBXGroup; children = ( - 1AFC25022F832036009FF858 /* CommandsTests.swift */, BB000000000000000000AAA3 /* RuddarrTests.swift */, ); path = Tests; @@ -932,7 +928,6 @@ isa = PBXGroup; children = ( 1AFC24F82F82B753009FF858 /* Commands.swift */, - 1AFC24F92F82B753009FF858 /* CommandStatus.swift */, BB2370DC2DCE76A600261710 /* Queue */, BBF583C02BACA40D00AFA7FB /* Movies */, BB507D202BD9702B00EC4016 /* Series */, @@ -1240,7 +1235,6 @@ 2B949CEB2CCBC8690088B1A8 /* HistoryView.swift in Sources */, 79159D6E2B5953E800F7F997 /* API.swift in Sources */, 1AFC24FA2F82B753009FF858 /* Commands.swift in Sources */, - 1AFC24FB2F82B753009FF858 /* CommandStatus.swift in Sources */, BB05C9052B86D0EC009B6444 /* Languages.swift in Sources */, BBC136A42B62DD780074C7AA /* Network.swift in Sources */, BB89ABC62B756B91009FB62D /* MovieReleaseRow.swift in Sources */, diff --git a/Ruddarr/Models/Commands/CommandStatus.swift b/Ruddarr/Models/Commands/CommandStatus.swift deleted file mode 100644 index 19f2b8c2..00000000 --- a/Ruddarr/Models/Commands/CommandStatus.swift +++ /dev/null @@ -1,104 +0,0 @@ -import Foundation - -struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { - let commandId: Int - let name: String - let commandName: String? - var message: String? - var status: String - var result: String? - let queued: Date - var started: Date? - var ended: Date? - let trigger: String? - - /// Stamped client-side after decoding so we can group + filter per instance. - var instanceId: Instance.ID? - - /// Stamped client-side at dispatch time with a human-readable subject - /// (e.g. "Breaking Bad — Season 2") so the list row can show something - /// richer than the raw command name. - var subject: String? - - enum CodingKeys: String, CodingKey { - case commandId = "id" - case name, commandName, message, status, result - case queued, started, ended, trigger - } - - /// Composite identity used by SwiftUI `ForEach` / `.sheet(item:)` so two - /// instances that both expose command id 42 don't collide. - var id: String { - "\(instanceId?.uuidString ?? "none")-\(commandId)" - } - - var state: CommandStatusState { - CommandStatusState(rawValue: status) ?? .unknown - } - - var isTerminal: Bool { - switch state { - case .completed, .failed, .aborted, .cancelled, .orphaned: - return true - case .queued, .started, .unknown: - return false - } - } - - var isSearchCommand: Bool { - Self.searchCommandNames.contains(name) - } - - static let searchCommandNames: Set = [ - "MoviesSearch", - "SeriesSearch", - "SeasonSearch", - "EpisodeSearch", - ] - - /// Sort key: most recent first. Uses `started` if available, otherwise `queued`. - var sortDate: Date { - started ?? queued - } - - /// Human-readable title for rows and sheets: client-stamped subject if present, - /// otherwise the server-provided command name, otherwise the raw command key. - var displayTitle: String { - subject ?? commandName ?? name - } -} - -enum CommandStatusState: String, Codable { - case queued - case started - case completed - case failed - case aborted - case cancelled - case orphaned - case unknown - - var label: String { - switch self { - case .queued: String(localized: "Queued", comment: "Command status") - case .started: String(localized: "Running", comment: "Command status") - case .completed: String(localized: "Completed", comment: "Command status") - case .failed: String(localized: "Failed", comment: "Command status") - case .aborted: String(localized: "Aborted", comment: "Command status") - case .cancelled: String(localized: "Cancelled", comment: "Command status") - case .orphaned: String(localized: "Orphaned", comment: "Command status") - case .unknown: String(localized: "Unknown", comment: "Command status") - } - } - - var systemImage: String { - switch self { - case .queued: "clock" - case .started: "arrow.triangle.2.circlepath" - case .completed: "checkmark.circle" - case .failed, .aborted, .orphaned: "exclamationmark.triangle" - case .cancelled: "xmark.circle" - case .unknown: "questionmark.circle" - } - } -} diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index 6dd710b3..2156968a 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -1,43 +1,138 @@ import Foundation +import SwiftUI + +struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { + let commandId: Int + let name: String + let commandName: String? + var message: String? + var status: String + var result: String? + let queued: Date + var started: Date? + var ended: Date? + let trigger: String? + + var instanceId: Instance.ID? + var subject: String? + + enum CodingKeys: String, CodingKey { + case commandId = "id" + case name, commandName, message, status, result + case queued, started, ended, trigger + } + + var id: String { + "\(instanceId?.uuidString ?? "none")-\(commandId)" + } + + var state: CommandStatusState { + CommandStatusState(rawValue: status) ?? .unknown + } + + var isTerminal: Bool { + switch state { + case .completed, .failed, .aborted, .cancelled, .orphaned: + return true + case .queued, .started, .unknown: + return false + } + } + + var isSearchCommand: Bool { + Self.searchCommandNames.contains(name) + } + + static let searchCommandNames: Set = [ + "MoviesSearch", + "SeriesSearch", + "SeasonSearch", + "EpisodeSearch", + ] + + var sortDate: Date { + started ?? queued + } + + var displayTitle: String { + subject ?? commandName ?? name + } +} + +enum CommandStatusState: String, Codable { + case queued + case started + case completed + case failed + case aborted + case cancelled + case orphaned + case unknown + + var label: String { + switch self { + case .queued: String(localized: "Queued", comment: "Command status") + case .started: String(localized: "Running", comment: "Command status") + case .completed: String(localized: "Completed", comment: "Command status") + case .failed: String(localized: "Failed", comment: "Command status") + case .aborted: String(localized: "Aborted", comment: "Command status") + case .cancelled: String(localized: "Cancelled", comment: "Command status") + case .orphaned: String(localized: "Orphaned", comment: "Command status") + case .unknown: String(localized: "Unknown", comment: "Command status") + } + } + + var systemImage: String { + switch self { + case .queued: "clock" + case .started: "arrow.triangle.2.circlepath" + case .completed: "checkmark.circle" + case .failed, .aborted, .orphaned: "exclamationmark.triangle" + case .cancelled: "xmark.circle" + case .unknown: "questionmark.circle" + } + } + + var tint: Color { + switch self { + case .completed: .green + case .failed, .aborted, .orphaned: .red + case .cancelled: .secondary + case .queued, .started: .accentColor + case .unknown: .secondary + } + } +} @MainActor @Observable -final class Commands { +class Commands { static let shared = Commands() private var timer: Timer? var error: API.Error? + var isLoading: Bool = false var performRefresh: Bool = false var instances: [Instance] = [] var items: [Instance.ID: [InstanceCommandStatus]] = [:] - /// Max items to keep per instance. The instance also trims its own - /// history, but we cap locally so long-running sessions don't grow forever. private let perInstanceLimit = 50 - init() { + private init() { let interval: TimeInterval = isRunningIn(.preview) ? 30 : 5 - self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in - Task { @MainActor in - guard let self, self.performRefresh else { return } - await self.fetchAll() + + self.timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in + Task { + if await self.performRefresh { + await self.fetchAll() + } } } } - /// Test-only factory that skips timer scheduling. - static func makeForTesting() -> Commands { - let c = Commands() - c.timer?.invalidate() - c.timer = nil - return c - } - - /// Called from `dispatchSearch` call sites immediately after a command POST - /// so the user sees the new row without waiting for the next poll. func track(_ status: InstanceCommandStatus) { guard let instanceId = status.instanceId else { return } var list = items[instanceId] ?? [] @@ -46,10 +141,6 @@ final class Commands { items[instanceId] = Array(list.prefix(perInstanceLimit)) } - /// Merges a fresh list of statuses fetched from the instance. Existing - /// entries are updated in place (preserving client-side `subject`), - /// unknown entries are inserted, and anything not seen since the last - /// `fetchAll` is left alone (the instance may have trimmed them). func merge(_ incoming: [InstanceCommandStatus], for instanceId: Instance.ID) { var existing = items[instanceId] ?? [] let existingById = Dictionary(existing.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first }) @@ -69,9 +160,9 @@ final class Commands { items[instanceId] = Array(existing.prefix(perInstanceLimit)) } - /// Initial population + pull-to-refresh. func fetchAll() async { guard !isLoading else { return } + error = nil isLoading = true @@ -80,9 +171,10 @@ final class Commands { let statuses = try await dependencies.api.fetchCommands(instance) merge(statuses, for: instance.id) } catch is CancellationError { - // ignore + // do nothing } catch let apiError as API.Error { error = apiError + leaveBreadcrumb(.error, category: "commands", message: "Fetch failed", data: ["error": apiError]) } catch { self.error = API.Error(from: error) @@ -92,8 +184,6 @@ final class Commands { isLoading = false } - /// Returns a flat, sorted list across all instances, respecting the - /// search-only default filter. func filteredItems(showAll: Bool) -> [InstanceCommandStatus] { let all = items.values.flatMap { $0 } let filtered = showAll ? all : all.filter { $0.isSearchCommand } diff --git a/Ruddarr/Views/Activity/CommandListItem.swift b/Ruddarr/Views/Activity/CommandListItem.swift index b8f7d5f8..228cd5b6 100644 --- a/Ruddarr/Views/Activity/CommandListItem.swift +++ b/Ruddarr/Views/Activity/CommandListItem.swift @@ -3,7 +3,7 @@ import SwiftUI struct CommandListItem: View { var command: InstanceCommandStatus - @State private var now = Date() + @State private var time = Date() private let timer = Timer.publish(every: 1, tolerance: 0.5, on: .main, in: .common).autoconnect() var body: some View { @@ -23,7 +23,7 @@ struct CommandListItem: View { Bullet() Text(subline) .monospacedDigit() - .id(now) + .id(time) } } .font(.subheadline) @@ -34,15 +34,17 @@ struct CommandListItem: View { .contentShape(Rectangle()) .onReceive(timer) { _ in if command.state == .started || command.state == .queued { - withAnimation { now = Date() } + withAnimation { + time = Date() + } } } } - private var subline: String? { + var subline: String? { switch command.state { case .started, .queued: - let elapsed = now.timeIntervalSince(command.started ?? command.queued) + let elapsed = time.timeIntervalSince(command.started ?? command.queued) return formatDuration(elapsed) case .completed, .failed, .aborted, .cancelled, .orphaned, .unknown: guard let ended = command.ended else { return nil } @@ -50,3 +52,10 @@ struct CommandListItem: View { } } } + +#Preview { + dependencies.router.selectedTab = .activity + + return ContentView() + .withAppState() +} diff --git a/Ruddarr/Views/Activity/CommandSheet.swift b/Ruddarr/Views/Activity/CommandSheet.swift index fc41453f..786cdbd6 100644 --- a/Ruddarr/Views/Activity/CommandSheet.swift +++ b/Ruddarr/Views/Activity/CommandSheet.swift @@ -9,13 +9,18 @@ struct CommandSheet: View { var body: some View { NavigationStack { ScrollView { - VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading) { header - Divider() + details + .padding(.top) } - .padding() - .frame(maxWidth: .infinity, alignment: .leading) + .scenePadding(.horizontal) + #if os(macOS) + .padding(.top, 24) + #else + .offset(y: -45) + #endif } .toolbar { ToolbarItem(placement: .destructiveAction) { @@ -29,68 +34,99 @@ struct CommandSheet: View { } } - private var header: some View { - VStack(alignment: .leading, spacing: 4) { - Text(command.displayTitle) - .font(.title3) - .fontWeight(.semibold) - - HStack(spacing: 6) { - Image(systemName: command.state.systemImage) - Text(command.state.label) - } - .font(.subheadline) - .foregroundStyle(stateTint) + @ViewBuilder + var header: some View { + HStack(spacing: 6) { + Image(systemName: command.state.systemImage) + Text(command.state.label) } + .foregroundStyle(command.state.tint) + .font(.caption) + .fontWeight(.semibold) + .textCase(.uppercase) + .tracking(1.1) + + Text(command.displayTitle) + .font(.title3.bold()) + .kerning(-0.5) + .fixedSize(horizontal: false, vertical: true) + .padding(.trailing, 56) } - private var details: some View { - VStack(alignment: .leading, spacing: 8) { - row("Instance", instanceLabel) - row("Command", command.commandName ?? command.name) - if let result = command.result { row("Result", result) } - if let message = command.message { row("Message", message) } - row("Queued", command.queued.formatted(date: .abbreviated, time: .shortened)) - if let started = command.started { - row("Started", started.formatted(date: .abbreviated, time: .shortened)) - } - if let ended = command.ended { - row("Ended", ended.formatted(date: .abbreviated, time: .shortened)) - } - if let duration = durationLabel { - row("Duration", duration) + var details: some View { + Section { + VStack(spacing: 6) { + row("Instance", instanceLabel) + + Divider() + row("Command", command.commandName ?? command.name) + + if let result = command.result { + Divider() + row("Result", result) + } + + if let message = command.message { + Divider() + row("Message", message) + } + + Divider() + row("Queued", command.queued.formatted(date: .long, time: .shortened)) + + if let started = command.started { + Divider() + row("Started", started.formatted(date: .long, time: .shortened)) + } + + if let ended = command.ended { + Divider() + row("Ended", ended.formatted(date: .long, time: .shortened)) + } + + if let started = command.started, let ended = command.ended { + Divider() + row("Duration", formatDuration(ended.timeIntervalSince(started))) + } } + .padding(.bottom) + } header: { + Text("Information") + .font(.title2.bold()) } } - private func row(_ label: LocalizedStringKey, _ value: String) -> some View { - HStack(alignment: .firstTextBaseline) { - Text(label).foregroundStyle(.secondary) + func row(_ label: LocalizedStringKey, _ value: String) -> some View { + row(label, Text(value).foregroundStyle(.primary)) + } + + func row(_ label: LocalizedStringKey, _ value: V) -> some View { + HStack(alignment: .top) { + Text(label) + .foregroundStyle(.secondary) + + Spacer() Spacer() - Text(value).multilineTextAlignment(.trailing) + Spacer() + + value + .multilineTextAlignment(.trailing) } - .font(.subheadline) + .font(.callout) + .padding(.vertical, 4) } - private var instanceLabel: String { + var instanceLabel: String { guard let id = command.instanceId, let instance = settings.instances.first(where: { $0.id == id }) else { return "—" } return instance.label } +} - private var durationLabel: String? { - guard let started = command.started, let ended = command.ended else { return nil } - return formatDuration(ended.timeIntervalSince(started)) - } +#Preview { + dependencies.router.selectedTab = .activity - private var stateTint: Color { - switch command.state { - case .completed: .green - case .failed, .aborted, .orphaned: .red - case .cancelled: .secondary - case .queued, .started: .accentColor - case .unknown: .secondary - } - } + return ContentView() + .withAppState() } diff --git a/Ruddarr/Views/Activity/CommandsListView.swift b/Ruddarr/Views/Activity/CommandsListView.swift index 94212cd6..cf25e9a2 100644 --- a/Ruddarr/Views/Activity/CommandsListView.swift +++ b/Ruddarr/Views/Activity/CommandsListView.swift @@ -29,7 +29,7 @@ struct CommandsListView: View { .listRowBackground(Color.card) #endif } header: { - sectionHeader + if !filteredItems.isEmpty { sectionHeader } } } #if os(iOS) @@ -55,6 +55,7 @@ struct CommandsListView: View { .tint(.primary) } } + .onChange(of: commands.items, updateSelected) .onAppear { commands.instances = settings.instances commands.performRefresh = true @@ -76,21 +77,24 @@ struct CommandsListView: View { .presentationBackground(.sheetBackground) .environmentObject(settings) } - .onChange(of: commands.items) { updateSelected() } } - private func updateSelected() { - guard let current = selected else { return } - if let fresh = commands.items[current.instanceId ?? UUID()]?.first(where: { $0.id == current.id }) { - selected = fresh + func updateSelected() { + guard let commandId = selected?.commandId else { return } + guard let instanceId = selected?.instanceId else { return } + + if let command = commands.items[instanceId]?.first(where: { $0.commandId == commandId }) { + selected = command + } else { + selected = nil } } - private var filteredItems: [InstanceCommandStatus] { + var filteredItems: [InstanceCommandStatus] { commands.filteredItems(showAll: showAll) } - private var sectionHeader: some View { + var sectionHeader: some View { HStack(spacing: 6) { Text("\(filteredItems.count) Task") @@ -102,7 +106,7 @@ struct CommandsListView: View { } } - private var empty: some View { + var empty: some View { ContentUnavailableView( "No Recent Tasks", systemImage: "checklist", diff --git a/Tests/CommandsTests.swift b/Tests/CommandsTests.swift deleted file mode 100644 index a681b945..00000000 --- a/Tests/CommandsTests.swift +++ /dev/null @@ -1,130 +0,0 @@ -import Testing -import Foundation -@testable import Ruddarr - -struct CommandsTests { - @Test func decodesCompletedSeriesSearch() throws { - let json = """ - { - "id": 42, - "name": "SeriesSearch", - "commandName": "Series Search", - "message": "Completed", - "status": "completed", - "result": "successful", - "queued": "2026-04-05T10:15:00Z", - "started": "2026-04-05T10:15:01Z", - "ended": "2026-04-05T10:15:04Z", - "trigger": "manual" - } - """.data(using: .utf8)! - - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .iso8601 - - let status = try decoder.decode(InstanceCommandStatus.self, from: json) - - #expect(status.commandId == 42) - #expect(status.name == "SeriesSearch") - #expect(status.state == .completed) - #expect(status.message == "Completed") - #expect(status.isSearchCommand == true) - #expect(status.isTerminal == true) - } - - @Test func decodesQueuedCommandWithoutEndedDate() throws { - let json = """ - { - "id": 7, - "name": "MoviesSearch", - "status": "queued", - "queued": "2026-04-05T10:00:00Z", - "trigger": "manual" - } - """.data(using: .utf8)! - - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .iso8601 - - let status = try decoder.decode(InstanceCommandStatus.self, from: json) - - #expect(status.state == .queued) - #expect(status.ended == nil) - #expect(status.isTerminal == false) - } - - @Test func unknownStateFallsBack() throws { - let json = """ - { "id": 1, "name": "Foo", "status": "warp-driving", "queued": "2026-04-05T10:00:00Z" } - """.data(using: .utf8)! - - let decoder = JSONDecoder() - decoder.dateDecodingStrategy = .iso8601 - - let status = try decoder.decode(InstanceCommandStatus.self, from: json) - #expect(status.state == .unknown) - #expect(status.isSearchCommand == false) - } - - @Test @MainActor func trackInsertsCommandAtFront() async { - let commands = Commands.makeForTesting() - let instanceId = UUID() - - let status = InstanceCommandStatus( - commandId: 1, name: "SeriesSearch", commandName: nil, message: nil, - status: "queued", result: nil, - queued: Date(), started: nil, ended: nil, trigger: "manual", - instanceId: instanceId, subject: "Breaking Bad" - ) - commands.track(status) - - #expect(commands.items[instanceId]?.count == 1) - #expect(commands.items[instanceId]?.first?.subject == "Breaking Bad") - } - - @Test @MainActor func mergeReplacesByIdAndKeepsSubject() async { - let commands = Commands.makeForTesting() - let instanceId = UUID() - - let queued = InstanceCommandStatus( - commandId: 9, name: "MoviesSearch", commandName: nil, message: nil, - status: "queued", result: nil, - queued: Date(), started: nil, ended: nil, trigger: "manual", - instanceId: instanceId, subject: "Inception" - ) - commands.track(queued) - - var completed = queued - completed.status = "completed" - completed.ended = Date() - completed.subject = nil // server won't know the subject - commands.merge([completed], for: instanceId) - - let stored = commands.items[instanceId]?.first - #expect(stored?.state == .completed) - #expect(stored?.subject == "Inception") // preserved from local track - } - - @Test @MainActor func defaultFilterKeepsOnlySearchCommands() async { - let commands = Commands.makeForTesting() - let instanceId = UUID() - - let search = InstanceCommandStatus( - commandId: 1, name: "SeriesSearch", commandName: nil, message: nil, - status: "queued", result: nil, - queued: Date(), started: nil, ended: nil, trigger: "manual", - instanceId: instanceId, subject: nil - ) - let rss = InstanceCommandStatus( - commandId: 2, name: "RssSync", commandName: nil, message: nil, - status: "queued", result: nil, - queued: Date(), started: nil, ended: nil, trigger: "scheduled", - instanceId: instanceId, subject: nil - ) - - commands.merge([search, rss], for: instanceId) - - #expect(commands.filteredItems(showAll: false).count == 1) - #expect(commands.filteredItems(showAll: true).count == 2) - } -} From 5746b6753226abbd885bfbf9488fc1ba38bd402b Mon Sep 17 00:00:00 2001 From: joptimus Date: Wed, 8 Apr 2026 12:18:34 -0500 Subject: [PATCH 17/20] merged commands into Activity list and fix episode subject labels --- Ruddarr.xcodeproj/project.pbxproj | 4 - Ruddarr/Models/Commands/Commands.swift | 25 +++ Ruddarr/Models/Series/Episode.swift | 11 - .../Views/Activity/ActivityView+Toolbar.swift | 20 +- Ruddarr/Views/Activity/CommandsListView.swift | 116 ---------- Ruddarr/Views/ActivityView.swift | 205 +++++++++++------- Ruddarr/Views/Series/EpisodeContextMenu.swift | 4 +- Ruddarr/Views/Series/EpisodeView.swift | 4 +- 8 files changed, 161 insertions(+), 228 deletions(-) delete mode 100644 Ruddarr/Views/Activity/CommandsListView.swift diff --git a/Ruddarr.xcodeproj/project.pbxproj b/Ruddarr.xcodeproj/project.pbxproj index 7b1a4c21..ec6ef08c 100644 --- a/Ruddarr.xcodeproj/project.pbxproj +++ b/Ruddarr.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 1AFC24FA2F82B753009FF858 /* Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24F82F82B753009FF858 /* Commands.swift */; }; 1AFC24FF2F82B789009FF858 /* CommandSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */; }; - 1AFC25002F82B789009FF858 /* CommandsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */; }; 1AFC25012F82B789009FF858 /* CommandListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */; }; 2B949CE52CC92CA20088B1A8 /* sonarr-history.json in Resources */ = {isa = PBXBuildFile; fileRef = 2B949CE42CC92C970088B1A8 /* sonarr-history.json */; }; 2B949CE72CC92F370088B1A8 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B949CE62CC92F320088B1A8 /* History.swift */; }; @@ -267,7 +266,6 @@ 1AFC24F82F82B753009FF858 /* Commands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Commands.swift; path = Commands/Commands.swift; sourceTree = ""; }; 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandListItem.swift; sourceTree = ""; }; 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandSheet.swift; sourceTree = ""; }; - 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandsListView.swift; sourceTree = ""; }; 2B949CE42CC92C970088B1A8 /* sonarr-history.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "sonarr-history.json"; sourceTree = ""; }; 2B949CE62CC92F320088B1A8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = ""; }; @@ -783,7 +781,6 @@ children = ( 1AFC24FC2F82B789009FF858 /* CommandListItem.swift */, 1AFC24FD2F82B789009FF858 /* CommandSheet.swift */, - 1AFC24FE2F82B789009FF858 /* CommandsListView.swift */, 2B949CEA2CCBC8600088B1A8 /* HistoryView.swift */, BB50F2282C3B3322005E14CA /* ActivityView+Toolbar.swift */, BBDBBC682C13A0600087C844 /* QueueSort.swift */, @@ -1299,7 +1296,6 @@ BBA50F4F2D760CAA008A16FA /* SettingsIconLabelStyle.swift in Sources */, BBE1E43F2B51F61700946222 /* MovieLookup.swift in Sources */, 1AFC24FF2F82B789009FF858 /* CommandSheet.swift in Sources */, - 1AFC25002F82B789009FF858 /* CommandsListView.swift in Sources */, 1AFC25012F82B789009FF858 /* CommandListItem.swift in Sources */, BBE564DF2DC99A8C005C26B6 /* MovieGridCard.swift in Sources */, 2B949CE72CC92F370088B1A8 /* History.swift in Sources */, diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index 2156968a..41fdc803 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -50,6 +50,28 @@ struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { "EpisodeSearch", ] + static let visibleCommandNames: Set = [ + "MoviesSearch", + "MissingMoviesSearch", + "CutoffUnmetMoviesSearch", + "EpisodeSearch", + "SeasonSearch", + "SeriesSearch", + "MissingEpisodeSearch", + "CutoffUnmetEpisodeSearch", + "RefreshMovie", + "RefreshSeries", + "RefreshCollections", + "RssSync", + "ManualImport", + "ImportListSync", + "RenameFiles", + "RenameMovie", + "RenameSeries", + "RescanMovie", + "RescanSeries", + ] + var sortDate: Date { started ?? queued } @@ -120,6 +142,7 @@ class Commands { var items: [Instance.ID: [InstanceCommandStatus]] = [:] private let perInstanceLimit = 50 + private let sessionStart = Date() private init() { let interval: TimeInterval = isRunningIn(.preview) ? 30 : 5 @@ -186,6 +209,8 @@ class Commands { func filteredItems(showAll: Bool) -> [InstanceCommandStatus] { let all = items.values.flatMap { $0 } + .filter { InstanceCommandStatus.visibleCommandNames.contains($0.name) } + .filter { !$0.isTerminal || $0.queued >= sessionStart } let filtered = showAll ? all : all.filter { $0.isSearchCommand } return filtered.sorted { $0.sortDate > $1.sortDate } } diff --git a/Ruddarr/Models/Series/Episode.swift b/Ruddarr/Models/Series/Episode.swift index 05146cb9..758a57b5 100644 --- a/Ruddarr/Models/Series/Episode.swift +++ b/Ruddarr/Models/Series/Episode.swift @@ -203,17 +203,6 @@ enum EpisodeReleaseType: String, Equatable, Codable { } } -extension Episode { - /// Formatted subject for Activity / Commands rows, e.g. "Breaking Bad — 1x03". - /// Uses the existing `episodeLabel` format for numbering consistency. - var subjectLabel: String { - if let seriesTitle = series?.title, !seriesTitle.isEmpty { - return "\(seriesTitle) — \(episodeLabel)" - } - return episodeLabel - } -} - extension Episode { static var void: Self { .init( diff --git a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift index bdc6322f..98754f8f 100644 --- a/Ruddarr/Views/Activity/ActivityView+Toolbar.swift +++ b/Ruddarr/Views/Activity/ActivityView+Toolbar.swift @@ -30,18 +30,16 @@ extension ActivityView { @ToolbarContentBuilder var toolbarButtons: some ToolbarContent { - if segment == .downloads { - ToolbarItem(placement: .navigation) { - toolbarFilterButton - .tint(.primary) - .menuIndicator(.hidden) - } + ToolbarItem(placement: .navigation) { + toolbarFilterButton + .tint(.primary) + .menuIndicator(.hidden) + } - ToolbarItem(placement: .navigation) { - toolbarSortingButton - .tint(.primary) - .menuIndicator(.hidden) - } + ToolbarItem(placement: .navigation) { + toolbarSortingButton + .tint(.primary) + .menuIndicator(.hidden) } #if os(iOS) diff --git a/Ruddarr/Views/Activity/CommandsListView.swift b/Ruddarr/Views/Activity/CommandsListView.swift deleted file mode 100644 index cf25e9a2..00000000 --- a/Ruddarr/Views/Activity/CommandsListView.swift +++ /dev/null @@ -1,116 +0,0 @@ -import SwiftUI - -struct CommandsListView: View { - @State var commands = Commands.shared - @State private var selected: InstanceCommandStatus? - @State private var showAll: Bool = false - - @EnvironmentObject var settings: AppSettings - @Environment(\.deviceType) private var deviceType - - var body: some View { - Group { - if settings.configuredInstances.isEmpty { - NoInstance() - } else { - List { - Section { - ForEach(filteredItems) { command in - Button { - selected = command - } label: { - CommandListItem(command: command) - } - .buttonStyle(.plain) - } - #if os(macOS) - .padding(.vertical, 4) - #else - .listRowBackground(Color.card) - #endif - } header: { - if !filteredItems.isEmpty { sectionHeader } - } - } - #if os(iOS) - .background(.systemBackground) - #endif - .scrollContentBackground(.hidden) - .overlay { - if filteredItems.isEmpty { - empty - } - } - } - } - .toolbar { - ToolbarItem(placement: .primaryAction) { - Toggle(isOn: $showAll) { - Label( - "Show All Tasks", - systemImage: showAll ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease.circle" - ) - } - .toggleStyle(.button) - .tint(.primary) - } - } - .onChange(of: commands.items, updateSelected) - .onAppear { - commands.instances = settings.instances - commands.performRefresh = true - } - .onDisappear { - commands.performRefresh = false - } - .task { - await commands.fetchAll() - } - .refreshable { - await Task { await commands.fetchAll() }.value - } - .sheet(item: $selected) { command in - CommandSheet(command: command) - .presentationDetents(dynamic: [ - deviceType == .phone ? .fraction(0.7) : .large - ]) - .presentationBackground(.sheetBackground) - .environmentObject(settings) - } - } - - func updateSelected() { - guard let commandId = selected?.commandId else { return } - guard let instanceId = selected?.instanceId else { return } - - if let command = commands.items[instanceId]?.first(where: { $0.commandId == commandId }) { - selected = command - } else { - selected = nil - } - } - - var filteredItems: [InstanceCommandStatus] { - commands.filteredItems(showAll: showAll) - } - - var sectionHeader: some View { - HStack(spacing: 6) { - Text("\(filteredItems.count) Task") - - if commands.isLoading { - ProgressView() - .controlSize(.small) - .tint(.secondary) - } - } - } - - var empty: some View { - ContentUnavailableView( - "No Recent Tasks", - systemImage: "checklist", - description: Text("Automatic searches and other commands will appear here.") - ) - } -} diff --git a/Ruddarr/Views/ActivityView.swift b/Ruddarr/Views/ActivityView.swift index 455e6571..c9de0130 100644 --- a/Ruddarr/Views/ActivityView.swift +++ b/Ruddarr/Views/ActivityView.swift @@ -2,104 +2,137 @@ import SwiftUI struct ActivityView: View { @State var queue = Queue.shared + @State var commands = Commands.shared @State var sort: QueueSort = .init() @State var items: [QueueItem] = [] @State private var selectedItem: QueueItem? - @State var segment: ActivitySegment = .searches + @State private var selectedCommand: InstanceCommandStatus? @EnvironmentObject var settings: AppSettings @Environment(\.deviceType) private var deviceType var body: some View { NavigationStack { - VStack(spacing: 0) { - Picker("", selection: $segment) { - Text("Searches").tag(ActivitySegment.searches) - Text("Downloads").tag(ActivitySegment.downloads) - } - .pickerStyle(.segmented) - .padding(.horizontal) - .padding(.top, 8) - - switch segment { - case .searches: - CommandsListView() - .environmentObject(settings) - case .downloads: - downloadsContent + // swiftlint:disable:next closure_body_length + Group { + if settings.configuredInstances.isEmpty { + NoInstance() + } else { + List { + if !commandItems.isEmpty { + Section { + ForEach(commandItems) { command in + Button { + selectedCommand = command + } label: { + CommandListItem(command: command) + } + .buttonStyle(.plain) + } + #if os(macOS) + .padding(.vertical, 4) + #else + .listRowBackground(Color.card) + #endif + } header: { + commandsSectionHeader + } + } + + Section { + ForEach(items) { item in + Button { + selectedItem = item + } label: { + QueueListItem(item: item) + } + .buttonStyle(.plain) + } + #if os(macOS) + .padding(.vertical, 4) + #else + .listRowBackground(Color.card) + #endif + } header: { + if !items.isEmpty { queueSectionHeader } + } + } + #if os(iOS) + .background(.systemBackground) + #endif + .scrollContentBackground(.hidden) + .overlay { + if items.isEmpty && commandItems.isEmpty { + queueEmpty + } + } } } .safeNavigationBarTitleDisplayMode(.inline) .toolbar { toolbarButtons } + .onChange(of: sort.option, updateSortDirection) + .onChange(of: sort, updateDisplayedItems) + .onChange(of: queue.items, updateDisplayedItems) + .onChange(of: queue.items, updateSelectedItem) + .onChange(of: commands.items, updateSelectedCommand) + .onAppear { + queue.instances = settings.instances + queue.performRefresh = true + commands.instances = settings.instances + commands.performRefresh = true + updateDisplayedItems() + } + .onDisappear { + queue.performRefresh = false + commands.performRefresh = false + } + .task { + await queue.fetchTasks() + } + .task { + await commands.fetchAll() + } + .refreshable { + Task { await queue.refreshDownloadClients() } + Task { await commands.fetchAll() } + await Task { await queue.fetchTasks() }.value + } + .sheet(item: $selectedItem) { item in + QueueItemSheet(item: item) + .presentationDetents(dynamic: [ + deviceType == .phone ? .fraction(0.7) : .large + ]) + .presentationBackground(.sheetBackground) + .environmentObject(settings) + } + .sheet(item: $selectedCommand) { command in + CommandSheet(command: command) + .presentationDetents(dynamic: [ + deviceType == .phone ? .fraction(0.7) : .large + ]) + .presentationBackground(.sheetBackground) + .environmentObject(settings) + } } } - // swiftlint:disable:next closure_body_length - private var downloadsContent: some View { - Group { - if settings.configuredInstances.isEmpty { - NoInstance() - } else { - List { - Section { - ForEach(items) { item in - Button { - selectedItem = item - } label: { - QueueListItem(item: item) - } - .buttonStyle(.plain) - } - #if os(macOS) - .padding(.vertical, 4) - #else - .listRowBackground(Color.card) - #endif - } header: { - if !items.isEmpty { sectionHeader } - } - } - #if os(iOS) - .background(.systemBackground) - #endif - .scrollContentBackground(.hidden) - .overlay { - if items.isEmpty { - queueEmpty - } - } + var commandItems: [InstanceCommandStatus] { + commands.filteredItems(showAll: true) + } + + var commandsSectionHeader: some View { + HStack(spacing: 6) { + Text("\(commandItems.count) Running") + + if commands.isLoading { + ProgressView() + .controlSize(.small) + .tint(.secondary) } } - .onChange(of: sort.option, updateSortDirection) - .onChange(of: sort, updateDisplayedItems) - .onChange(of: queue.items, updateDisplayedItems) - .onChange(of: queue.items, updateSelectedItem) - .onAppear { - queue.instances = settings.instances - queue.performRefresh = true - updateDisplayedItems() - } - .onDisappear { - queue.performRefresh = false - } - .task { - await queue.fetchTasks() - } - .refreshable { - Task { await queue.refreshDownloadClients() } - await Task { await queue.fetchTasks() }.value - } - .sheet(item: $selectedItem) { item in - QueueItemSheet(item: item) - .presentationDetents(dynamic: [ - deviceType == .phone ? .fraction(0.7) : .large - ]) - .presentationBackground(.sheetBackground) - .environmentObject(settings) - } } var queueEmpty: some View { @@ -110,7 +143,7 @@ struct ActivityView: View { ) } - var sectionHeader: some View { + var queueSectionHeader: some View { HStack(spacing: 6) { Text("\(items.count) Task") @@ -137,6 +170,17 @@ struct ActivityView: View { } } + func updateSelectedCommand() { + guard let commandId = selectedCommand?.commandId else { return } + guard let instanceId = selectedCommand?.instanceId else { return } + + if let command = commands.items[instanceId]?.first(where: { $0.commandId == commandId }) { + selectedCommand = command + } else { + selectedCommand = nil + } + } + func updateDisplayedItems() { let grouped: [String: [QueueItem]] = Dictionary( grouping: queue.items.flatMap { $0.value }, @@ -180,11 +224,6 @@ struct ActivityView: View { } } -enum ActivitySegment: Hashable { - case searches - case downloads -} - #Preview { dependencies.router.selectedTab = .activity diff --git a/Ruddarr/Views/Series/EpisodeContextMenu.swift b/Ruddarr/Views/Series/EpisodeContextMenu.swift index 52947752..3277b263 100644 --- a/Ruddarr/Views/Series/EpisodeContextMenu.swift +++ b/Ruddarr/Views/Series/EpisodeContextMenu.swift @@ -3,6 +3,7 @@ import TelemetryDeck struct EpisodeContextMenu: View { var episode: Episode + var seriesTitle: String? @Environment(SonarrInstance.self) var instance var body: some View { @@ -32,7 +33,8 @@ struct EpisodeContextMenu: View { return } - status.subject = episode.subjectLabel + let title = seriesTitle ?? episode.series?.title + status.subject = title != nil ? "\(title!) — \(episode.episodeLabel)" : episode.episodeLabel Commands.shared.track(status) dependencies.toast.show(.episodeSearchQueued) diff --git a/Ruddarr/Views/Series/EpisodeView.swift b/Ruddarr/Views/Series/EpisodeView.swift index e2fb8d31..5787c886 100644 --- a/Ruddarr/Views/Series/EpisodeView.swift +++ b/Ruddarr/Views/Series/EpisodeView.swift @@ -178,7 +178,7 @@ struct EpisodeView: View { ToolbarItem(placement: .primaryAction) { Menu { Section { - EpisodeContextMenu(episode: episode) + EpisodeContextMenu(episode: episode, seriesTitle: series.title) } if episodeFile != nil { @@ -335,7 +335,7 @@ extension EpisodeView { return } - status.subject = episode.subjectLabel + status.subject = "\(series.title) — \(episode.episodeLabel)" Commands.shared.track(status) dependencies.toast.show(.episodeSearchQueued) From 91895838636c98bf948f58456b2369f74d5fa30f Mon Sep 17 00:00:00 2001 From: joptimus Date: Wed, 8 Apr 2026 12:20:09 -0500 Subject: [PATCH 18/20] remove localization file changes --- Ruddarr/Localizable.xcstrings | 7075 ++++++++++++++++----------------- 1 file changed, 3459 insertions(+), 3616 deletions(-) diff --git a/Ruddarr/Localizable.xcstrings b/Ruddarr/Localizable.xcstrings index 0d32d976..0e13d4d2 100644 --- a/Ruddarr/Localizable.xcstrings +++ b/Ruddarr/Localizable.xcstrings @@ -1,22 +1,21 @@ { - "sourceLanguage": "en", - "strings": { - "": {}, - "(%lld Issue)": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "(%lld Issue)" + "sourceLanguage" : "en", + "strings" : { + "(%lld Issue)" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "(%lld Issue)" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "(%lld Issues)" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "(%lld Issues)" } } } @@ -24,83 +23,83 @@ } } }, - "%.1f years": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%.1f years" + "%.1f years" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%.1f years" } } } }, - "%@ at %@": { - "comment": "(Today/Tomorrow/Yesterday) at (time)", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%1$@ at %2$@" + "%@ at %@" : { + "comment" : "(Today/Tomorrow/Yesterday) at (time)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@ at %2$@" } } } }, - "%@ does not start an automatic search when adding media, but you can.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ does not start an automatic search when adding media, but you can." + "%@ does not start an automatic search when adding media, but you can." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ does not start an automatic search when adding media, but you can." } } } }, - "%@.": { - "comment": "Prefix for episode title (episode number)", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@." + "%@." : { + "comment" : "Prefix for episode title (episode number)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@." } } } }, - "%1$@ downloaded successfully and imported from %2$@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%1$@ downloaded successfully and imported from %2$@." + "%1$@ downloaded successfully and imported from %2$@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@ downloaded successfully and imported from %2$@." } } } }, - "%1$@ grabbed from %2$@ and sent to %3$@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%1$@ grabbed from %2$@ and sent to %3$@." + "%1$@ grabbed from %2$@ and sent to %3$@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@ grabbed from %2$@ and sent to %3$@." } } } }, - "%d days": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%d day" + "%d days" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d day" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%d days" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d days" } } } @@ -108,21 +107,21 @@ } } }, - "%d hours": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%d hour" + "%d hours" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d hour" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%d hours" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d hours" } } } @@ -130,21 +129,21 @@ } } }, - "%d minutes": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%d minute" + "%d minutes" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d minute" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%d minutes" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d minutes" } } } @@ -152,21 +151,21 @@ } } }, - "%d months": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%d month" + "%d months" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d month" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%d months" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d months" } } } @@ -174,31 +173,31 @@ } } }, - "%d years": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%d years" + "%d years" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%d years" } } } }, - "%lld Season": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld Season" + "%lld Season" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Season" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%lld Seasons" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Seasons" } } } @@ -206,21 +205,21 @@ } } }, - "%lld Seasons": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld Season" + "%lld Seasons" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Season" } }, - "other": { - "stringUnit": { - "state": "new", - "value": "%lld Seasons" + "other" : { + "stringUnit" : { + "state" : "new", + "value" : "%lld Seasons" } } } @@ -228,21 +227,21 @@ } } }, - "%lld Tag": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld Tag" + "%lld Tag" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Tag" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%lld Tags" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Tags" } } } @@ -250,21 +249,21 @@ } } }, - "%lld Task": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld Task" + "%lld Task" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Task" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%lld Tasks" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Tasks" } } } @@ -272,21 +271,21 @@ } } }, - "+%lld more...": { - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "+%lld more..." + "+%lld more..." : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld more..." } }, - "other": { - "stringUnit": { - "state": "new", - "value": "+%lld more..." + "other" : { + "stringUnit" : { + "state" : "new", + "value" : "+%lld more..." } } } @@ -294,4302 +293,4176 @@ } } }, - "Aborted": { - "comment": "Command status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Aborted" + "About" : { + "comment" : "Preferences section title", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "About" } } } }, - "About": { - "comment": "Preferences section title", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "About" + "Accent Color" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accent Color" } } } }, - "Accent Color": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Accent Color" + "Active" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Active" } } } }, - "Active": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Active" + "Activity" : { + "comment" : "Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activity" } } } }, - "Activity": { - "comment": "Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Activity" + "Add Authentication" : { + "comment" : "Add Basic HTTP Authentication to instance", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Authentication" } } } }, - "Add Authentication": { - "comment": "Add Basic HTTP Authentication to instance", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Authentication" + "Add Exclusion" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Exclusion" } } } }, - "Add Exclusion": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Exclusion" + "Add Header" : { + "comment" : "Add HTTP Header to instance", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Header" } } } }, - "Add Header": { - "comment": "Add HTTP Header to instance", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Header" + "Add Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Instance" } } } }, - "Add Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Instance" + "Add Movie" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Movie" } } } }, - "Add Movie": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Movie" + "Add Series" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add Series" } } } }, - "Add Series": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add Series" + "Added" : { + "comment" : "Media grid sorting", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Added" } } } }, - "Added": { - "comment": "Media grid sorting", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Added" + "Age" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Age" } } } }, - "Age": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Age" + "Airing" : { + "comment" : "The time the next episode airs", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Airing" } } } }, - "Airing": { - "comment": "The time the next episode airs", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Airing" + "Alias" : { + "comment" : "Match type of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alias" } } } }, - "Alias": { - "comment": "Match type of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Alias" + "All Episodes" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All Episodes" } } } }, - "All Episodes": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All Episodes" + "All Events" : { + "comment" : "(Short) History event filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All Events" } } } }, - "All Events": { - "comment": "(Short) History event filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All Events" + "All instance queues are empty." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All instance queues are empty." } } } }, - "All instance queues are empty.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All instance queues are empty." + "All Movies" : { + "comment" : "Media grid filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All Movies" } } } }, - "All Movies": { - "comment": "Media grid filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All Movies" + "All TV Series" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All TV Series" } } } }, - "All TV Series": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All TV Series" + "Alternatively, %@ comes with many notification integrations that can be self-hosted." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alternatively, %@ comes with many notification integrations that can be self-hosted." } } } }, - "Alternatively, %@ comes with many notification integrations that can be self-hosted.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Alternatively, %@ comes with many notification integrations that can be self-hosted." + "An error occurred." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An error occurred." } } } }, - "An error occurred.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An error occurred." + "An unexpected error occurred." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An unexpected error occurred." } } } }, - "An unexpected error occurred.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An unexpected error occurred." + "An unknown error occurred: %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An unknown error occurred: %@" } } } }, - "An unknown error occurred: %@": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An unknown error occurred: %@" + "Anime" : { + "comment" : "Series type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anime" } } } }, - "Anime": { - "comment": "Series type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Anime" + "Announced" : { + "comment" : "Media status label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Announced" } } } }, - "Announced": { - "comment": "Media status label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Announced" + "Any" : { + "comment" : "Season pack or single episode option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any" } } } }, - "Any": { - "comment": "Season pack or single episode option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any" + "Any Client" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Client" } } } }, - "Any Client": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Client" + "Any Folder" : { + "comment" : "Short spelling of Root Folder", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Folder" } } } }, - "Any Folder": { - "comment": "Short spelling of Root Folder", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Folder" + "Any Format" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Format" } } } }, - "Any Format": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Format" + "Any Indexer" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Indexer" } } } }, - "Any Indexer": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Indexer" + "Any Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Instance" } } } }, - "Any Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Instance" + "Any Language" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Language" } } } }, - "Any Language": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Language" + "Any Protocol" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Protocol" } } } }, - "Any Protocol": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Protocol" + "Any Quality" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Any Quality" } } } }, - "Any Quality": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Any Quality" + "API Key" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "API Key" } } } }, - "API Key": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "API Key" + "App Icon" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "App Icon" } } } }, - "App Icon": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "App Icon" + "Appearance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appearance" } } } }, - "Appearance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Appearance" + "Application Updated" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Application Updated" } } } }, - "Application Updated": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Application Updated" + "Approved" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Approved" } } } }, - "Approved": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Approved" + "Are you attempting to connect to a private IP address from outside its network?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Are you attempting to connect to a private IP address from outside its network?" } } } }, - "Are you attempting to connect to a private IP address from outside its network?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Are you attempting to connect to a private IP address from outside its network?" + "Are you sure you want to delete the instance?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Are you sure you want to delete the instance?" } } } }, - "Are you sure you want to delete the instance?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Are you sure you want to delete the instance?" + "Are you sure you want to erase all settings?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Are you sure you want to erase all settings?" } } } }, - "Are you sure you want to erase all settings?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Are you sure you want to erase all settings?" + "Are you sure?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Are you sure?" } } } }, - "Are you sure?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Are you sure?" + "Ascending" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ascending" } } } }, - "Ascending": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Ascending" + "At least you're not on hold." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "At least you're not on hold." } } } }, - "At least you're not on hold.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "At least you're not on hold." + "Audio" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Audio" } } } }, - "Audio": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Audio" + "Authentication" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Authentication" } } } }, - "Authentication": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Authentication" + "Automatic" : { + "comment" : "Appearance that adapts to the system", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatic" } } } }, - "Automatic": { - "comment": "Appearance that adapts to the system", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Automatic" + "Automatic Search" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatic Search" } } } }, - "Automatic Search": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Automatic Search" + "Availability" : { + "comment" : "Very short version of Minimum Availability", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Availability" } } } }, - "Automatic searches and other commands will appear here.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Automatic searches and other commands will appear here." + "Bad status code: %lld" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bad status code: %lld" } } } }, - "Availability": { - "comment": "Very short version of Minimum Availability", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Availability" + "Barbie" : { + "comment" : "Localized name of the Barbie brand", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Barbie" } } } }, - "Bad status code: %lld": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Bad status code: %lld" + "Basic Authentication" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Basic Authentication" } } } }, - "Barbie": { - "comment": "Localized name of the Barbie brand", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Barbie" + "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." } } } }, - "Basic Authentication": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Basic Authentication" + "Bitrate" : { + "comment" : "Audio/video bitrate", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bitrate" } } } }, - "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Basic Authentication is for advanced server management tools and will not work with regular %@ login credentials." + "Blocklist Release" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Blocklist Release" } } } }, - "Bitrate": { - "comment": "Audio/video bitrate", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Bitrate" + "Blocks this release from being redownloaded via Automatic Search or RSS." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Blocks this release from being redownloaded via Automatic Search or RSS." } } } }, - "Blocklist Release": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Blocklist Release" + "Books" : { + "comment" : "Localized name of Apple's Books app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Books" } } } }, - "Blocks this release from being redownloaded via Automatic Search or RSS.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Blocks this release from being redownloaded via Automatic Search or RSS." + "Bug Report Sent" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bug Report Sent" } } } }, - "Books": { - "comment": "Localized name of Apple's Books app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Books" + "Calendar" : { + "comment" : "Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calendar" } } } }, - "Bug Report Sent": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Bug Report Sent" + "Cancel" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancel" } } } }, - "Calendar": { - "comment": "Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Calendar" + "Cards" : { + "comment" : "Grid item display style", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cards" } } } }, - "Cancel": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancel" + "Channels" : { + "comment" : "Audio channel count", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Channels" } } } }, - "Cancelled": { - "comment": "Command status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancelled" + "Check the spelling or try [adding the movie](%@)." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Check the spelling or try [adding the movie](%@)." } } } }, - "Cards": { - "comment": "Grid item display style", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cards" + "Check the spelling or try [adding the series](%@)." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Check the spelling or try [adding the series](%@)." } } } }, - "Channels": { - "comment": "Audio channel count", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Channels" + "Clear Filters" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clear Filters" } } } }, - "Check the spelling or try [adding the movie](%@).": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Check the spelling or try [adding the movie](%@)." + "Clear Image Cache" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clear Image Cache" } } } }, - "Check the spelling or try [adding the series](%@).": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Check the spelling or try [adding the series](%@)." + "Client" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Client" } } } }, - "Clear Filters": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Clear Filters" + "Close" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Close" } } } }, - "Clear Image Cache": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Clear Image Cache" + "Codec" : { + "comment" : "Audio/video codec", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Codec" } } } }, - "Client": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Client" + "Color Depth" : { + "comment" : "Video color depth", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Color Depth" } } } }, - "Close": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Close" + "Connect a %@ instance under %@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connect a %1$@ instance under %2$@." } } } }, - "Codec": { - "comment": "Audio/video codec", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Codec" + "Connected" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connected" } } } }, - "Color Depth": { - "comment": "Video color depth", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Color Depth" + "Connecting..." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connecting..." } } } }, - "Command": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Command" + "Connection Failed" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connection Failed" } } } }, - "Completed": { - "comment": "Command status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Completed" + "Connection Failure" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connection Failure" } } } }, - "Connect a %@ instance under %@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Connect a %1$@ instance under %2$@." + "Continue" : { + "comment" : "Button to close whats new sheet", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Continue" } } } }, - "Connected": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Connected" + "Continuing" : { + "comment" : "(Single word) Series status", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Continuing" } } } }, - "Connecting...": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Connecting..." + "Contribute on GitHub" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contribute on GitHub" } } } }, - "Connection Failed": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Connection Failed" + "Copy Link" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copy Link" } } } }, - "Connection Failure": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Connection Failure" + "Custom Format" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Custom Format" } } } }, - "Continue": { - "comment": "Button to close whats new sheet", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Continue" + "Custom Formats" : { + "comment" : "Custom formats of media file", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Custom Formats" } } } }, - "Continuing": { - "comment": "(Single word) Series status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Continuing" + "Custom Headers can be used to access instances protected by Zero Trust services." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Custom Headers can be used to access instances protected by Zero Trust services." } } } }, - "Contribute on GitHub": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Contribute on GitHub" + "Custom Score" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Custom Score" } } } }, - "Copy Link": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Copy Link" + "Daily" : { + "comment" : "Series type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Daily" } } } }, - "Custom Format": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Custom Format" + "Dangling" : { + "comment" : "Media grid filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dangling" } } } }, - "Custom Formats": { - "comment": "Custom formats of media file", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Custom Formats" + "Dark" : { + "comment" : "Dark appearance/mode", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dark" } } } }, - "Custom Headers can be used to access instances protected by Zero Trust services.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Custom Headers can be used to access instances protected by Zero Trust services." + "Default" : { + "comment" : "Default app icon name", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Default" } } } }, - "Custom Score": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Custom Score" + "Delete" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete" } } } }, - "Daily": { - "comment": "Series type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Daily" + "Delete File" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete File" } } } }, - "Dangling": { - "comment": "Media grid filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dangling" + "Delete Files" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete Files" } } } }, - "Dark": { - "comment": "Dark appearance/mode", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dark" + "Delete Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete Instance" } } } }, - "Default": { - "comment": "Default app icon name", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Default" + "Delete Movie" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete Movie" } } } }, - "Delete": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete" + "Delete Series" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete Series" } } } }, - "Delete File": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete File" + "Delete Spotlight Index" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete Spotlight Index" } } } }, - "Delete Files": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete Files" + "Deleted" : { + "comment" : "(Short) History event filter\n(Short) Title of history event\n(Single word) Series status\nMedia status label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deleted" } } } }, - "Delete Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete Instance" + "Deleting Files" : { + "comment" : "Title of a tip, not a status", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deleting Files" } } } }, - "Delete Movie": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete Movie" + "Descending" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Descending" } } } }, - "Delete Series": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete Series" + "Details" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Details" } } } }, - "Delete Spotlight Index": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete Spotlight Index" + "Digital Release" : { + "comment" : "Media grid sorting", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Digital Release" } } } }, - "Deleted": { - "comment": "(Short) History event filter\n(Short) Title of history event\n(Single word) Series status\nMedia status label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Deleted" + "Direction" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Direction" } } } }, - "Deleting Files": { - "comment": "Title of a tip, not a status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Deleting Files" + "Discovering new ways of making you wait." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Discovering new ways of making you wait." } } } }, - "Descending": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Descending" + "Display" : { + "comment" : "Preferences section title", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Display" } } } }, - "Details": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Details" + "Download" : { + "comment" : "Short version of Download Release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download" } } } }, - "Digital Release": { - "comment": "Media grid sorting", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Digital Release" + "download client" : { + "comment" : "Fallback for download client name within mid-sentence", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "download client" } } } }, - "Direction": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Direction" + "Download Client Unavailable" : { + "comment" : "Status of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Client Unavailable" } } } }, - "Discovering new ways of making you wait.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Discovering new ways of making you wait." + "Download Client Warning" : { + "comment" : "Status of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Client Warning" } } } }, - "Display": { - "comment": "Preferences section title", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Display" + "Download Failed" : { + "comment" : "Status of task in queue\nTitle of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Failed" } } } }, - "Download": { - "comment": "Short version of Download Release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download" + "Download Ignored" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Ignored" } } } }, - "download client": { - "comment": "Fallback for download client name within mid-sentence", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "download client" + "Download Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Queued" } } } }, - "Download Client Unavailable": { - "comment": "Status of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Client Unavailable" + "Download Release" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Download Release" } } } }, - "Download Client Warning": { - "comment": "Status of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Client Warning" + "Downloaded" : { + "comment" : "(Single word) Episode status label\nMedia grid filter\nState of media item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloaded" } } } }, - "Download Failed": { - "comment": "Status of task in queue\nTitle of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Failed" + "Downloading" : { + "comment" : "(Short) State of task in queue\nState of task in queue\nStatus of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloading" } } } }, - "Download Ignored": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Ignored" + "Dynamic Range" : { + "comment" : "Video file dynamic range", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dynamic Range" } } } }, - "Download Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Queued" + "Edit" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Edit" } } } }, - "Download Release": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Download Release" + "Email" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Email" } } } }, - "Downloaded": { - "comment": "(Single word) Episode status label\nMedia grid filter\nState of media item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Downloaded" + "Enable Notifications" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enable Notifications" } } } }, - "Downloading": { - "comment": "(Short) State of task in queue\nState of task in queue\nStatus of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Downloading" + "Ended" : { + "comment" : "(Single word) Series status", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ended" } } } }, - "Downloads": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Downloads" + "Enter a valid URL." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enter a valid URL." } } } }, - "Duration": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Duration" + "Enter an instance label." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enter an instance label." } } } }, - "Dynamic Range": { - "comment": "Video file dynamic range", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dynamic Range" + "Episode" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode" } } } }, - "Edit": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Edit" + "Episode Deleted" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Deleted" } } } }, - "Email": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Email" + "Episode file was renamed." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode file was renamed." } } } }, - "Enable Notifications": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enable Notifications" + "Episode Renamed" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Renamed" } } } }, - "Ended": { - "comment": "(Single word) Series status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Ended" + "Episode Search Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Search Queued" } } } }, - "Enter a valid URL.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enter a valid URL." + "Episodes" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episodes" } } } }, - "Enter an instance label.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enter an instance label." + "Error" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Error" } } } }, - "Episode": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode" + "Event Type" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Event Type" } } } }, - "Episode Deleted": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Deleted" + "Everything" : { + "comment" : "Movies and series filter option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Everything" } } } }, - "Episode file was renamed.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode file was renamed." + "Existing Episodes" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Existing Episodes" } } } }, - "Episode Renamed": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Renamed" + "Expired" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Expired" } } } }, - "Episode Search Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Search Queued" + "Failed" : { + "comment" : "(Short) History event filter\n(Short) State of task in queue\n(Short) Title of history event", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Failed" } } } }, - "Episodes": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episodes" + "File" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File" } } } }, - "Error": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Error" + "File Deleted" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File Deleted" } } } }, - "Event Type": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Event Type" + "File Imported" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File Imported" } } } }, - "Everything": { - "comment": "Movies and series filter option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Everything" + "File Size" : { + "comment" : "Media grid sorting\nRelease filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File Size" } } } }, - "Existing Episodes": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Existing Episodes" + "File Upgraded" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File Upgraded" } } } }, - "Expired": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Expired" + "File was deleted either manually or by a client through the API." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File was deleted either manually or by a client through the API." } } } }, - "Failed": { - "comment": "(Short) History event filter\n(Short) State of task in queue\n(Short) Title of history event\nCommand status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Failed" + "File was deleted to import an upgrade." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File was deleted to import an upgrade." } } } }, - "File": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File" + "File was not found on disk so it was unlinked from the episode in the database." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File was not found on disk so it was unlinked from the episode in the database." } } } }, - "File Deleted": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File Deleted" + "File was not found on disk so it was unlinked from the movie in the database." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "File was not found on disk so it was unlinked from the movie in the database." } } } }, - "File Imported": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File Imported" + "Files" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Files" } } } }, - "File Size": { - "comment": "Media grid sorting\nRelease filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File Size" + "Files & History" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Files & History" } } } }, - "File Upgraded": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File Upgraded" + "Filter" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Filter" } } } }, - "File was deleted either manually or by a client through the API.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File was deleted either manually or by a client through the API." + "First Season" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "First Season" } } } }, - "File was deleted to import an upgrade.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File was deleted to import an upgrade." + "Fitness" : { + "comment" : "Localized name of Apple's Fitness app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fitness" } } } }, - "File was not found on disk so it was unlinked from the episode in the database.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File was not found on disk so it was unlinked from the episode in the database." + "Flags" : { + "comment" : "Indexer flags", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Flags" } } } }, - "File was not found on disk so it was unlinked from the movie in the database.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "File was not found on disk so it was unlinked from the movie in the database." + "Folder Imported" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Folder Imported" } } } }, - "Files": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Files" + "Framerate" : { + "comment" : "Video frame rate", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Framerate" } } } }, - "Files & History": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Files & History" + "FreeLeech" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "FreeLeech" } } } }, - "Filter": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Filter" + "Future Episodes" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Future Episodes" } } } }, - "First Season": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "First Season" + "Genre" : { + "comment" : "Genres of the movie/series", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Genre" } } } }, - "Fitness": { - "comment": "Localized name of Apple's Fitness app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fitness" + "Grab Release" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grab Release" } } } }, - "Flags": { - "comment": "Indexer flags", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Flags" + "Grabbed" : { + "comment" : "(Short) History event filter\n(Short) Title of history event\nMedia grid sorting", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grabbed" } } } }, - "Folder Imported": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Folder Imported" + "Grid" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grid" } } } }, - "Framerate": { - "comment": "Video frame rate", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Framerate" + "Header name" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Header name" } } } }, - "FreeLeech": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "FreeLeech" + "Header value" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Header value" } } } }, - "Future Episodes": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Future Episodes" + "Headers" : { + "comment" : "HTTP Headers", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Headers" } } } }, - "Genre": { - "comment": "Genres of the movie/series", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Genre" + "Health Issue" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Health Issue" } } } }, - "Grab Release": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Grab Release" + "Health Restored" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Health Restored" } } } }, - "Grabbed": { - "comment": "(Short) History event filter\n(Short) Title of history event\nMedia grid sorting", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Grabbed" + "Hide Specials" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hide Specials" } } } }, - "Grid": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Grid" + "History" : { + "comment" : "Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "History" } } } }, - "Header name": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Header name" + "Hold on, this may take a moment." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hold on, this may take a moment." } } } }, - "Header value": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Header value" + "Home" : { + "comment" : "(Preferences) Home tab", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Home" } } } }, - "Headers": { - "comment": "HTTP Headers", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Headers" + "Icons" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Icons" } } } }, - "Health Issue": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Health Issue" + "Identifier" : { + "comment" : "Match type of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Identifier" } } } }, - "Health Restored": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Health Restored" + "Ignored" : { + "comment" : "(Short) History event filter\n(Short) Title of history event", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ignored" } } } }, - "Hide Specials": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Hide Specials" + "Import" : { + "comment" : "(Short) Importing a queue task", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import" } } } }, - "History": { - "comment": "Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "History" + "Import Blocked" : { + "comment" : "(Short) State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import Blocked" } } } }, - "Hold on, this may take a moment.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Hold on, this may take a moment." + "Import Completed" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import Completed" } } } }, - "Home": { - "comment": "(Preferences) Home tab", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Home" + "Import Pending" : { + "comment" : "(Short) State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import Pending" } } } }, - "Icons": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Icons" + "Import Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import Queued" } } } }, - "Identifier": { - "comment": "Match type of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Identifier" + "Imported" : { + "comment" : "(Short) History event filter\n(Short) Title of history event", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Imported" } } } }, - "Ignored": { - "comment": "(Short) History event filter\n(Short) Title of history event", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Ignored" + "Importing" : { + "comment" : "(Short) State of task in queue\nState of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importing" } } } }, - "Import": { - "comment": "(Short) Importing a queue task", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import" + "In Cinemas" : { + "comment" : "Media status label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "In Cinemas" } } } }, - "Import Blocked": { - "comment": "(Short) State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import Blocked" + "Inactive" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inactive" } } } }, - "Import Completed": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import Completed" + "Include Warnings" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Include Warnings" } } } }, - "Import Pending": { - "comment": "(Short) State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import Pending" + "indexer" : { + "comment" : "Fallback for indexer name within mid-sentence", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "indexer" } } } }, - "Import Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import Queued" + "Indexer" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indexer" } } } }, - "Imported": { - "comment": "(Short) History event filter\n(Short) Title of history event", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Imported" + "Information" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Information" } } } }, - "Importing": { - "comment": "(Short) State of task in queue\nState of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Importing" + "Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instance" } } } }, - "In Cinemas": { - "comment": "Media status label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "In Cinemas" + "Instance URL is not valid: %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instance URL is not valid: %@" } } } }, - "Inactive": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Inactive" + "Instances" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Instances" } } } }, - "Include Warnings": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Include Warnings" + "Integrations" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Integrations" } } } }, - "indexer": { - "comment": "Fallback for indexer name within mid-sentence", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "indexer" + "Interactive" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Interactive" } } } }, - "Indexer": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Indexer" + "Interactive Search" : { + "comment" : "Source of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Interactive Search" } } } }, - "Information": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Information" + "Invalid Instance Label" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Invalid Instance Label" } } } }, - "Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Instance" + "Invalid URL" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Invalid URL" } } } }, - "Instance URL is not valid: %@": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Instance URL is not valid: %@" + "Is this running on Windows?" : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Is this running on Windows?" } } } }, - "Instances": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Instances" + "Issues" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Issues" } } } }, - "Integrations": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Integrations" + "Join the Discord" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Join the Discord" } } } }, - "Interactive": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Interactive" + "Just now" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Just now" } } } }, - "Interactive Search": { - "comment": "Source of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Interactive Search" + "Just testing your patience." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Just testing your patience." } } } }, - "Invalid Instance Label": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Invalid Instance Label" + "Label" : { + "comment" : "Instance label/name", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Label" } } } }, - "Invalid URL": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Invalid URL" + "Language" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Language" } } } }, - "Is this running on Windows?": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Is this running on Windows?" + "Languages" : { + "comment" : "Metadata row label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Languages" } } } }, - "Issues": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Issues" + "Last Season" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Last Season" } } } }, - "Join the Discord": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Join the Discord" + "Latest" : { + "comment" : "Media search scope", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Latest" } } } }, - "Just now": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Just now" + "Leave a Review" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Leave a Review" } } } }, - "Just testing your patience.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Just testing your patience." + "Let's hope it's worth the wait." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Let's hope it's worth the wait." } } } }, - "Label": { - "comment": "Instance label/name", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Label" + "Light" : { + "comment" : "Light appearance/mode", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Light" } } } }, - "Language": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Language" + "Link" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Link" } } } }, - "Languages": { - "comment": "Metadata row label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Languages" + "Link Copied" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Link Copied" } } } }, - "Last Season": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Last Season" + "Load More" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Load More" } } } }, - "Latest": { - "comment": "Media search scope", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Latest" + "Loading..." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Loading..." } } } }, - "Leave a Review": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Leave a Review" + "Local Network Access Denied" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local Network Access Denied" } } } }, - "Let's hope it's worth the wait.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Let's hope it's worth the wait." + "Local network access must be granted in %@ to connect to instances using private IP addresses." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local network access must be granted in %@ to connect to instances using private IP addresses." } } } }, - "Light": { - "comment": "Light appearance/mode", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Light" + "Local network access must be granted in System Settings to connect to instances on private IP addresses." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Local network access must be granted in System Settings to connect to instances on private IP addresses." } } } }, - "Link": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Link" + "Long-press any file to delete it." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Long-press any file to delete it." } } } }, - "Link Copied": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Link Copied" + "Looking to [add a new movie](%@)?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Looking to [add a new movie](%@)?" } } } }, - "Load More": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Load More" + "Looking to [add a new series](%@)?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Looking to [add a new series](%@)?" } } } }, - "Loading...": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Loading..." + "Mail" : { + "comment" : "Localized name of Apple's Mail app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mail" } } } }, - "Local Network Access Denied": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Local Network Access Denied" + "Manual Import" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manual Import" } } } }, - "Local network access must be granted in %@ to connect to instances using private IP addresses.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Local network access must be granted in %@ to connect to instances using private IP addresses." + "Manual Interaction Required" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manual Interaction Required" } } } }, - "Local network access must be granted in System Settings to connect to instances on private IP addresses.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Local network access must be granted in System Settings to connect to instances on private IP addresses." + "Match Type" : { + "comment" : "Release match type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Match Type" } } } }, - "Long-press any file to delete it.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Long-press any file to delete it." + "Media Type" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Media Type" } } } }, - "Looking to [add a new movie](%@)?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Looking to [add a new movie](%@)?" + "Metadata" : { + "comment" : "Type of the extra movie file", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metadata" } } } }, - "Looking to [add a new series](%@)?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Looking to [add a new series](%@)?" + "Midseason Finale" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Midseason Finale" } } } }, - "Mail": { - "comment": "Localized name of Apple's Mail app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Mail" + "Min. Availability" : { + "comment" : "Shorter version of Minimum Availability", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Min. Availability" } } } }, - "Manual Import": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Manual Import" + "Minimum Availability" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Minimum Availability" } } } }, - "Manual Interaction Required": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Manual Interaction Required" + "Missing" : { + "comment" : "(Single word) Episode status label\nMedia grid filter\nState of media item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Missing" } } } }, - "Match Type": { - "comment": "Release match type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Match Type" + "Missing Episodes" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Missing Episodes" } } } }, - "Media Type": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Media Type" + "Monitor" : { + "comment" : "Label of picker of what to monitor (movie, collection, episodes, etc.)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monitor" } } } }, - "Message": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Message" + "Monitor New Seasons" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monitor New Seasons" } } } }, - "Metadata": { - "comment": "Type of the extra movie file", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Metadata" + "Monitor Specials" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monitor Specials" } } } }, - "Midseason Finale": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Midseason Finale" + "Monitored" : { + "comment" : "Media grid filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monitored" } } } }, - "Min. Availability": { - "comment": "Shorter version of Minimum Availability", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Min. Availability" + "Monitored Search Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monitored Search Queued" } } } }, - "Minimum Availability": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Minimum Availability" + "Monochrome" : { + "comment" : "Name of the 'Monochrome' theme", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Monochrome" } } } }, - "Missing": { - "comment": "(Single word) Episode status label\nMedia grid filter\nState of media item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Missing" + "Move Files" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Move Files" } } } }, - "Missing Episodes": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Missing Episodes" + "Move the movie files to \"%@\"?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Move the movie files to \"%@\"?" } } } }, - "Monitor": { - "comment": "Label of picker of what to monitor (movie, collection, episodes, etc.)", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monitor" + "Move the series files to \"%@\"?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Move the series files to \"%@\"?" } } } }, - "Monitor New Seasons": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monitor New Seasons" + "Movie" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie" } } } }, - "Monitor Specials": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monitor Specials" + "Movie + Collection" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie + Collection" } } } }, - "Monitored": { - "comment": "Media grid filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monitored" + "Movie Added" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Added" } } } }, - "Monitored Search Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monitored Search Queued" + "Movie Deleted" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Deleted" } } } }, - "Monochrome": { - "comment": "Name of the 'Monochrome' theme", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Monochrome" + "Movie Downloading" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Downloading" } } } }, - "Move Files": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Move Files" + "Movie File Deleted" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie File Deleted" } } } }, - "Move the movie files to \"%@\"?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Move the movie files to \"%@\"?" + "Movie file was renamed." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie file was renamed." } } } }, - "Move the series files to \"%@\"?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Move the series files to \"%@\"?" + "Movie has no files." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie has no files." } } } }, - "Movie": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie" + "Movie has no history." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie has no history." } } } }, - "Movie + Collection": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie + Collection" + "Movie Imported" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Imported" } } } }, - "Movie Added": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Added" + "Movie imported from folder." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie imported from folder." } } } }, - "Movie Deleted": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Deleted" + "Movie Renamed" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Renamed" } } } }, - "Movie Downloading": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Downloading" + "Movie Search Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Search Queued" } } } }, - "Movie File Deleted": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie File Deleted" + "Movie Upgraded" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Upgraded" } } } }, - "Movie file was renamed.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie file was renamed." + "Movies" : { + "comment" : "Plural. Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movies" } } } }, - "Movie has no files.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie has no files." + "Multi-Episode" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Multi-Episode" } } } }, - "Movie has no history.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie has no history." + "Multilingual" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Multilingual" } } } }, - "Movie Imported": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Imported" + "Music" : { + "comment" : "Localized name of Apple's Music app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Music" } } } }, - "Movie imported from folder.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie imported from folder." + "Network" : { + "comment" : "The network that airs the show", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Network" } } } }, - "Movie Renamed": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Renamed" + "New Seasons" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Seasons" } } } }, - "Movie Search Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Search Queued" + "Next Airing" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Next Airing" } } } }, - "Movie Upgraded": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Upgraded" + "No" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No" } } } }, - "Movies": { - "comment": "Plural. Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movies" + "No %@ Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No %@ Instance" } } } }, - "Multi-Episode": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Multi-Episode" + "No Automatic Search" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Automatic Search" } } } }, - "Multilingual": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Multilingual" + "No Events" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Events" } } } }, - "Music": { - "comment": "Localized name of Apple's Music app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Music" + "No Events Match" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Events Match" } } } }, - "Network": { - "comment": "The network that airs the show", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Network" + "No events match the selected filters." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No events match the selected filters." } } } }, - "New Seasons": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Seasons" + "No importable files found." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No importable files found." } } } }, - "Next Airing": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Next Airing" + "No Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Instance" } } } }, - "No": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No" + "No Internet Connection" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Internet Connection" } } } }, - "No %@ Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No %@ Instance" + "No Movies Match" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Movies Match" } } } }, - "No Automatic Search": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Automatic Search" + "No movies match the selected filters." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No movies match the selected filters." } } } }, - "No Events": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Events" + "No Releases Found" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Releases Found" } } } }, - "No Events Match": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Events Match" + "No releases found for \"%@\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No releases found for \"%@\"." } } } }, - "No events match the selected filters.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No events match the selected filters." + "No Releases Match" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Releases Match" } } } }, - "No importable files found.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No importable files found." + "No releases match \"%@\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No releases match \"%@\"." } } } }, - "No Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Instance" + "No releases match the selected filters and \"%@\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No releases match the selected filters and \"%@\"." } } } }, - "No Internet Connection": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Internet Connection" + "No releases match the selected filters." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No releases match the selected filters." } } } }, - "No Movies Match": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Movies Match" + "No Results for \"%@\"" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Results for \"%@\"" } } } }, - "No movies match the selected filters.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No movies match the selected filters." + "No Series Match" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Series Match" } } } }, - "No Recent Tasks": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Recent Tasks" + "No series match the selected filters." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No series match the selected filters." } } } }, - "No Releases Found": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Releases Found" + "None" : { + "comment" : "Movie monitoring option\nSeries monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "None" } } } }, - "No releases found for \"%@\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No releases found for \"%@\"." + "Not Subscribed" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Not Subscribed" } } } }, - "No Releases Match": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Releases Match" + "Notes" : { + "comment" : "Localized name of Apple's Notes app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notes" } } } }, - "No releases match \"%@\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No releases match \"%@\"." + "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." } } } }, - "No releases match the selected filters and \"%@\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No releases match the selected filters and \"%@\"." + "NOTIFICATION_APPLICATION_UPDATE" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Updated" } } } }, - "No releases match the selected filters.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No releases match the selected filters." + "NOTIFICATION_EPISODE_DOWNLOAD" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Downloaded on %@" } } } }, - "No Results for \"%@\"": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Results for \"%@\"" + "NOTIFICATION_EPISODE_DOWNLOAD_BODY" : { + "comment" : "Notification body (series, season, episode)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (S%@ E%@)" } } } }, - "No Series Match": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No Series Match" + "NOTIFICATION_EPISODE_FILE_DELETED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode File Deleted on %@" } } } }, - "No series match the selected filters.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No series match the selected filters." + "NOTIFICATION_EPISODE_FILE_DELETED_BODY" : { + "comment" : "Notification body (series, season, episode)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (S%@ E%@)" } } } }, - "None": { - "comment": "Movie monitoring option\nSeries monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "None" + "NOTIFICATION_EPISODE_GRAB" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Downloading on %@" } } } }, - "Not Subscribed": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Not Subscribed" + "NOTIFICATION_EPISODE_GRAB_SUBTITLE" : { + "comment" : "Notification subtitle (series, season, episode)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (S%@ E%@)" } } } }, - "Notes": { - "comment": "Localized name of Apple's Notes app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notes" + "NOTIFICATION_EPISODE_UPGRADE" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Episode Upgraded on %@" } } } }, - "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notification settings for each instance are shared between devices. To disable notifications for a specific device go to %@." + "NOTIFICATION_EPISODE_UPGRADE_BODY" : { + "comment" : "Notification body (old quality, new quality)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upgraded from %1$@ to %2$@" } } } }, - "NOTIFICATION_APPLICATION_UPDATE": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ Updated" + "NOTIFICATION_EPISODE_UPGRADE_SUBTITLE" : { + "comment" : "Notification subtitle (series, season, episode)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (S%@ E%@)" } } } }, - "NOTIFICATION_EPISODE_DOWNLOAD": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Downloaded on %@" + "NOTIFICATION_EPISODES_DOWNLOAD" : { + "comment" : "Notification title (instance name, episode count)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%2$@ Episodes Downloaded on %1$@" } } } }, - "NOTIFICATION_EPISODE_DOWNLOAD_BODY": { - "comment": "Notification body (series, season, episode)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (S%@ E%@)" + "NOTIFICATION_EPISODES_DOWNLOAD_BODY" : { + "comment" : "Notification body (series, season)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (Season %@)" } } } }, - "NOTIFICATION_EPISODE_FILE_DELETED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode File Deleted on %@" + "NOTIFICATION_EPISODES_GRAB" : { + "comment" : "Notification title (instance name, episode count)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%2$@ Episodes Downloading on %1$@" } } } }, - "NOTIFICATION_EPISODE_FILE_DELETED_BODY": { - "comment": "Notification body (series, season, episode)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (S%@ E%@)" + "NOTIFICATION_EPISODES_GRAB_BODY" : { + "comment" : "Notification body (quality, indexer)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloading %@ from %@" } } } }, - "NOTIFICATION_EPISODE_GRAB": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Downloading on %@" + "NOTIFICATION_EPISODES_GRAB_SUBTITLE" : { + "comment" : "Notification subtitle (series, season)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (Season %@)" } } } }, - "NOTIFICATION_EPISODE_GRAB_SUBTITLE": { - "comment": "Notification subtitle (series, season, episode)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (S%@ E%@)" + "NOTIFICATION_HEALTH" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Health Issue on %@" } } } }, - "NOTIFICATION_EPISODE_UPGRADE": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Episode Upgraded on %@" + "NOTIFICATION_HEALTH_RESTORED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Health Issue Resolved on %@" } } } }, - "NOTIFICATION_EPISODE_UPGRADE_BODY": { - "comment": "Notification body (old quality, new quality)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Upgraded from %1$@ to %2$@" + "NOTIFICATION_MANUAL_INTERACTION_REQUIRED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manual Interaction Required on %@" } } } }, - "NOTIFICATION_EPISODE_UPGRADE_SUBTITLE": { - "comment": "Notification subtitle (series, season, episode)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (S%@ E%@)" + "NOTIFICATION_MOVIE_ADDED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Added on %@" } } } }, - "NOTIFICATION_EPISODES_DOWNLOAD": { - "comment": "Notification title (instance name, episode count)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%2$@ Episodes Downloaded on %1$@" + "NOTIFICATION_MOVIE_ADDED_BODY" : { + "comment" : "Notification body (title, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_EPISODES_DOWNLOAD_BODY": { - "comment": "Notification body (series, season)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (Season %@)" + "NOTIFICATION_MOVIE_DELETED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Deleted on %@" } } } }, - "NOTIFICATION_EPISODES_GRAB": { - "comment": "Notification title (instance name, episode count)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%2$@ Episodes Downloading on %1$@" + "NOTIFICATION_MOVIE_DELETED_BODY" : { + "comment" : "Notification body (title, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_EPISODES_GRAB_BODY": { - "comment": "Notification body (quality, indexer)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Downloading %@ from %@" + "NOTIFICATION_MOVIE_DOWNLOAD" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Downloaded on %@" } } } }, - "NOTIFICATION_EPISODES_GRAB_SUBTITLE": { - "comment": "Notification subtitle (series, season)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (Season %@)" + "NOTIFICATION_MOVIE_DOWNLOAD_BODY" : { + "comment" : "Notification body (title, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_HEALTH": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Health Issue on %@" + "NOTIFICATION_MOVIE_FILE_DELETED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie File Deleted on %@" } } } }, - "NOTIFICATION_HEALTH_RESTORED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Health Issue Resolved on %@" + "NOTIFICATION_MOVIE_FILE_DELETED_BODY" : { + "comment" : "Notification body (movie, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_MANUAL_INTERACTION_REQUIRED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Manual Interaction Required on %@" + "NOTIFICATION_MOVIE_GRAB" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Downloading on %@" } } } }, - "NOTIFICATION_MOVIE_ADDED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Added on %@" + "NOTIFICATION_MOVIE_GRAB_BODY" : { + "comment" : "Notification body (quality, indexer)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Downloading %@ from %@" } } } }, - "NOTIFICATION_MOVIE_ADDED_BODY": { - "comment": "Notification body (title, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "NOTIFICATION_MOVIE_GRAB_SUBTITLE" : { + "comment" : "Notification subtitle (movie, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_DELETED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Deleted on %@" + "NOTIFICATION_MOVIE_UPGRADE" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Movie Upgraded on %@" } } } }, - "NOTIFICATION_MOVIE_DELETED_BODY": { - "comment": "Notification body (title, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "NOTIFICATION_MOVIE_UPGRADE_BODY" : { + "comment" : "Notification body (old quality, new quality)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upgraded from %1$@ to %2$@" } } } }, - "NOTIFICATION_MOVIE_DOWNLOAD": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Downloaded on %@" + "NOTIFICATION_MOVIE_UPGRADE_SUBTITLE" : { + "comment" : "Notification subtitle (movie, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_DOWNLOAD_BODY": { - "comment": "Notification body (title, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "NOTIFICATION_SERIES_ADDED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Added on %@" } } } }, - "NOTIFICATION_MOVIE_FILE_DELETED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie File Deleted on %@" + "NOTIFICATION_SERIES_ADDED_BODY" : { + "comment" : "Notification body (movie, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_FILE_DELETED_BODY": { - "comment": "Notification body (movie, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "NOTIFICATION_SERIES_DELETED" : { + "comment" : "Notification title (instance name)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Deleted on %@" } } } }, - "NOTIFICATION_MOVIE_GRAB": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Downloading on %@" + "NOTIFICATION_SERIES_DELETED_BODY" : { + "comment" : "Notification body (series, year)", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ (%@)" } } } }, - "NOTIFICATION_MOVIE_GRAB_BODY": { - "comment": "Notification body (quality, indexer)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Downloading %@ from %@" + "NOTIFICATION_TEST" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Test Notification" } } } }, - "NOTIFICATION_MOVIE_GRAB_SUBTITLE": { - "comment": "Notification subtitle (movie, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "NOTIFICATION_TEST_BODY" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This is a test notification." } } } }, - "NOTIFICATION_MOVIE_UPGRADE": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Movie Upgraded on %@" + "Notifications" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications" } } } }, - "NOTIFICATION_MOVIE_UPGRADE_BODY": { - "comment": "Notification body (old quality, new quality)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Upgraded from %1$@ to %2$@" + "Notifications are disabled, please enable them in %@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications are disabled, please enable them in %@." } } } }, - "NOTIFICATION_MOVIE_UPGRADE_SUBTITLE": { - "comment": "Notification subtitle (movie, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "Notifications require a subscription to %@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications require a subscription to %@." } } } }, - "NOTIFICATION_SERIES_ADDED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Added on %@" + "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." : { + "comment" : "1 = CloudKit status", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." } } } }, - "NOTIFICATION_SERIES_ADDED_BODY": { - "comment": "Notification body (movie, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." } } } }, - "NOTIFICATION_SERIES_DELETED": { - "comment": "Notification title (instance name)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Deleted on %@" + "OK" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" } } } }, - "NOTIFICATION_SERIES_DELETED_BODY": { - "comment": "Notification body (series, year)", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ (%@)" + "Open %@" : { + "comment" : "Open (app name)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open %@" } } } }, - "NOTIFICATION_TEST": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Test Notification" + "Open ${target}" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open ${target}" } } } }, - "NOTIFICATION_TEST_BODY": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This is a test notification." + "Open in %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open in %@" } } } }, - "Notifications": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications" + "Open In..." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open In..." } } } }, - "Notifications are disabled, please enable them in %@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications are disabled, please enable them in %@." + "Open Ruddarr" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open Ruddarr" } } } }, - "Notifications require a subscription to %@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications require a subscription to %@." + "Open Website" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open Website" } } } }, - "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@).": { - "comment": "1 = CloudKit status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications require an Apple Account. Please sign in, or enable iCloud Drive in the iCloud settings (%1$@)." + "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." } } } }, - "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications will not route reliably until each instance has been given a unique \"Instance Name\" in the web interface under \"Settings > General\"." + "Original" : { + "comment" : "Release filter (original language)", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Original" } } } }, - "OK": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "OK" + "Other" : { + "comment" : "Type of the extra movie file", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Other" } } } }, - "Open %@": { - "comment": "Open (app name)", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open %@" + "Password" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Password" } } } }, - "Open ${target}": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open ${target}" + "Paste" : { + "comment" : "Paste from clipboard", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paste" } } } }, - "Open in %@": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open in %@" + "Paused" : { + "comment" : "(Short) State of task in queue\nStatus of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paused" } } } }, - "Open In...": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open In..." + "Peers" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Peers" } } } }, - "Open Ruddarr": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open Ruddarr" + "Pending" : { + "comment" : "(Short) State of task in queue\nStatus of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pending" } } } }, - "Open Website": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open Website" + "Permanently erase the folder and its contents." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Permanently erase the folder and its contents." } } } }, - "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Optimizes API calls for instances that load unusually slowly and encounter timeouts frequently." + "Physical Release" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Physical Release" } } } }, - "Original": { - "comment": "Release filter (original language)", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Original" + "Pilot Episode" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pilot Episode" } } } }, - "Orphaned": { - "comment": "Command status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Orphaned" + "Please check your internet connection and try again." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Please check your internet connection and try again." } } } }, - "Other": { - "comment": "Type of the extra movie file", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Other" + "Podcasts" : { + "comment" : "Localized name of Apple's Podcasts app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Podcasts" } } } }, - "Password": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Password" + "Popular This Week" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Popular This Week" } } } }, - "Paste": { - "comment": "Paste from clipboard", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Paste" + "Posters" : { + "comment" : "Grid item display style", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Posters" } } } }, - "Paused": { - "comment": "(Short) State of task in queue\nStatus of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Paused" + "Preferences" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preferences" } } } }, - "Peers": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Peers" + "Preferred language and other app-related settings can be configured in the [System Settings](#link)." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preferred language and other app-related settings can be configured in the [System Settings](#link)." } } } }, - "Pending": { - "comment": "(Short) State of task in queue\nStatus of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pending" + "Premieres" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Premieres" } } } }, - "Permanently erase the folder and its contents.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Permanently erase the folder and its contents." + "Preserve" : { + "comment" : "(Preferences) Preserve release filters", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preserve" } } } }, - "Physical Release": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Physical Release" + "Prevent from being readded to library by lists." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prevent from being readded to library by lists." } } } }, - "Pilot Episode": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pilot Episode" + "Previous Airing" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Previous Airing" } } } }, - "Please check your internet connection and try again.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Please check your internet connection and try again." + "Proper" : { + "comment" : "The PROPER flag", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Proper" } } } }, - "Podcasts": { - "comment": "Localized name of Apple's Podcasts app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Podcasts" + "Protocol" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Protocol" } } } }, - "Popular This Week": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Popular This Week" + "Provide a detailed description of the issue along with the exact steps to reproduce it." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Provide a detailed description of the issue along with the exact steps to reproduce it." } } } }, - "Posters": { - "comment": "Grid item display style", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Posters" + "Published" : { + "comment" : "Release publish date", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Published" } } } }, - "Preferences": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Preferences" + "Quality" : { + "comment" : "Release filter\nShort version of Quality Profile", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quality" } } } }, - "Preferred language and other app-related settings can be configured in the [System Settings](#link).": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Preferred language and other app-related settings can be configured in the [System Settings](#link)." + "Quality Profile" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quality Profile" } } } }, - "Premieres": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Premieres" + "Queued" : { + "comment" : "(Short) State of task in queue\nStatus of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Queued" } } } }, - "Preserve": { - "comment": "(Preferences) Preserve release filters", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Preserve" + "Queues Empty" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Queues Empty" } } } }, - "Prevent from being readded to library by lists.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Prevent from being readded to library by lists." + "Rating" : { + "comment" : "Media grid sorting\nMedia search scope", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rating" } } } }, - "Previous Airing": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Previous Airing" + "Recent Episodes" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recent Episodes" } } } }, - "Proper": { - "comment": "The PROPER flag", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Proper" + "Refresh" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refresh" } } } }, - "Protocol": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Protocol" + "Refresh Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refresh Queued" } } } }, - "Provide a detailed description of the issue along with the exact steps to reproduce it.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Provide a detailed description of the issue along with the exact steps to reproduce it." + "Release Downloading" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Downloading" } } } }, - "Published": { - "comment": "Release publish date", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Published" + "Release Filters" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Filters" } } } }, - "Quality": { - "comment": "Release filter\nShort version of Quality Profile", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Quality" + "Release Grabbed" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Grabbed" } } } }, - "Quality Profile": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Quality Profile" + "Release Group" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Group" } } } }, - "Queued": { - "comment": "(Short) State of task in queue\nCommand status\nStatus of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Queued" + "Release Notes" : { + "comment" : "Also know as changelog", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Notes" } } } }, - "Queues Empty": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Queues Empty" + "Release Push" : { + "comment" : "Source of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Push" } } } }, - "Rating": { - "comment": "Media grid sorting\nMedia search scope", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Rating" + "Release Rejected" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Rejected" } } } }, - "Recent Episodes": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Recent Episodes" + "Release Type" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Release Type" } } } }, - "Refresh": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Refresh" + "Released" : { + "comment" : "Media status label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Released" } } } }, - "Refresh Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Refresh Queued" + "Relevant" : { + "comment" : "Media search scope", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Relevant" } } } }, - "Release Downloading": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Downloading" + "Remove" : { + "comment" : "(Short) Removing a queue task", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove" } } } }, - "Release Filters": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Filters" + "Remove from Client" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove from Client" } } } }, - "Release Grabbed": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Grabbed" + "Remove Task" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove Task" } } } }, - "Release Group": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Group" + "Renamed" : { + "comment" : "(Short) History event filter\n(Short) Title of history event", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Renamed" } } } }, - "Release Notes": { - "comment": "Also know as changelog", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Notes" + "Repack" : { + "comment" : "The REPACK flag", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repack" } } } }, - "Release Push": { - "comment": "Source of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Push" + "Report an Issue" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Report an Issue" } } } }, - "Release Rejected": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Rejected" + "Reset" : { + "comment" : "(Preferences) Reset release filters", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset" } } } }, - "Release Type": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Release Type" + "Reset All Settings" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset All Settings" } } } }, - "Released": { - "comment": "Media status label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Released" + "Resolution" : { + "comment" : "Video file resolution", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resolution" } } } }, - "Relevant": { - "comment": "Media search scope", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Relevant" + "Response Decoding Error" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Response Decoding Error" } } } }, - "Remove": { - "comment": "(Short) Removing a queue task", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Remove" + "Retry" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Retry" } } } }, - "Remove from Client": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Remove from Client" + "Revoked" : { + "comment" : "Status of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Revoked" } } } }, - "Remove Task": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Remove Task" + "Root Folder" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Root Folder" } } } }, - "Renamed": { - "comment": "(Short) History event filter\n(Short) Title of history event", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Renamed" + "Runtime" : { + "comment" : "Video runtime", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Runtime" } } } }, - "Repack": { - "comment": "The REPACK flag", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Repack" + "Save" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Save" } } } }, - "Report an Issue": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Report an Issue" + "Scan Type" : { + "comment" : "Video scan Type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Scan Type" } } } }, - "Reset": { - "comment": "(Preferences) Reset release filters", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset" + "Score" : { + "comment" : "Custom score of media file", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Score" } } } }, - "Reset All Settings": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset All Settings" + "Search" : { + "comment" : "Source of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search" } } } }, - "Resolution": { - "comment": "Video file resolution", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Resolution" + "Search for Movie" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for Movie" } } } }, - "Response Decoding Error": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Response Decoding Error" + "Search for movie with ${name}" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for movie with ${name}" } } } }, - "Result": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Result" + "Search for Replacement" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for Replacement" } } } }, - "Retry": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Retry" + "Search for TV Series" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for TV Series" } } } }, - "Revoked": { - "comment": "Status of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Revoked" + "Search for TV series with ${name}" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for TV series with ${name}" } } } }, - "Root Folder": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Root Folder" + "Search Monitored" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search Monitored" } } } }, - "Running": { - "comment": "Command status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Running" + "Searching..." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Searching..." } } } }, - "Runtime": { - "comment": "Video runtime", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Runtime" - } - } - } - }, - "Save": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Save" - } - } - } - }, - "Scan Type": { - "comment": "Video scan Type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Scan Type" - } - } - } - }, - "Score": { - "comment": "Custom score of media file", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Score" - } - } - } - }, - "Search": { - "comment": "Source of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search" - } - } - } - }, - "Search for Movie": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search for Movie" - } - } - } - }, - "Search for movie with ${name}": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search for movie with ${name}" - } - } - } - }, - "Search for Replacement": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search for Replacement" - } - } - } - }, - "Search for TV Series": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search for TV Series" - } - } - } - }, - "Search for TV series with ${name}": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search for TV series with ${name}" - } - } - } - }, - "Search Monitored": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search Monitored" - } - } - } - }, - "Searching...": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Searching..." - } - } - } - }, - "Season %lld": { - "comment": "Season number for command subject", - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "Season %lld" + "Season %lld" : { + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season %lld" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "Season %lld" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season %lld" } } } @@ -4597,1157 +4470,1127 @@ } } }, - "Season Files Deleted": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Files Deleted" - } - } - } - }, - "Season Finale": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Finale" - } - } - } - }, - "Season Folders": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Folders" - } - } - } - }, - "Season Pack": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Pack" + "Season Files Deleted" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Files Deleted" } } } }, - "Season Premiere": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Premiere" + "Season Finale" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Finale" } } } }, - "Season Search Queued": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Season Search Queued" + "Season Folders" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Folders" } } } }, - "Seasons": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Seasons" + "Season Pack" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Pack" } } } }, - "Seeders": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Seeders" + "Season Premiere" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Premiere" } } } }, - "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." + "Season Search Queued" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Season Search Queued" } } } }, - "Series": { - "comment": "Plural. Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series" + "Seasons" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seasons" } } } }, - "Series Added": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Added" + "Seeders" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seeders" } } } }, - "Series Deleted": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Deleted" + "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sending push notifications to devices requires reliable server infrastructure, which incurs monthly operating expenses for this free, open-source project." } } } }, - "Series Finale": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Finale" + "Series" : { + "comment" : "Plural. Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series" } } } }, - "Series imported from folder.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series imported from folder." + "Series Added" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Added" } } } }, - "Series Not Monitored": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Not Monitored" + "Series Deleted" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Deleted" } } } }, - "Series Premiere": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Premiere" + "Series Finale" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Finale" } } } }, - "Series Type": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Series Type" + "Series imported from folder." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series imported from folder." } } } }, - "Server Error Response": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Server Error Response" + "Series Not Monitored" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Not Monitored" } } } }, - "Server returned %lld status code.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Server returned %lld status code." + "Series Premiere" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Premiere" } } } }, - "Settings": { - "comment": "Tab/sidebar menu item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Settings" + "Series Type" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Series Type" } } } }, - "Share App": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Share App" + "Server Error Response" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server Error Response" } } } }, - "Show Advanced Settings": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show Advanced Settings" + "Server returned %lld status code." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Server returned %lld status code." } } } }, - "Show All Tasks": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show All Tasks" + "Settings" : { + "comment" : "Tab/sidebar menu item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings" } } } }, - "Single Episode": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Single Episode" + "Share App" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Share App" } } } }, - "Slow Instance": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Slow Instance" + "Show Advanced Settings" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show Advanced Settings" } } } }, - "Some releases are hidden by the selected filters.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Some releases are hidden by the selected filters." + "Single Episode" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Single Episode" } } } }, - "Something Went Wrong": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Something Went Wrong" + "Slow Instance" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slow Instance" } } } }, - "Sort By": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Sort By" + "Some releases are hidden by the selected filters." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Some releases are hidden by the selected filters." } } } }, - "Source": { - "comment": "Release source", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Source" + "Something Went Wrong" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Something Went Wrong" } } } }, - "Special": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Special" + "Sort By" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sort By" } } } }, - "Specials": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Specials" + "Source" : { + "comment" : "Release source", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Source" } } } }, - "Standard": { - "comment": "Series type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Standard" + "Special" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Special" } } } }, - "Started": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Started" + "Specials" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Specials" } } } }, - "Status": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Status" + "Standard" : { + "comment" : "Series type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standard" } } } }, - "Still searching for releases.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Still searching for releases." + "Status" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Status" } } } }, - "Streams": { - "comment": "Audio stream count", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Streams" + "Still searching for releases." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Still searching for releases." } } } }, - "Studio": { - "comment": "The studio that produces the movie", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Studio" + "Streams" : { + "comment" : "Audio stream count", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Streams" } } } }, - "Submit": { - "comment": "Send bug report", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Submit" + "Studio" : { + "comment" : "The studio that produces the movie", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Studio" } } } }, - "Subscription": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Subscription" + "Submit" : { + "comment" : "Send bug report", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Submit" } } } }, - "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." + "Subscription" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subscription" } } } }, - "Subtitles": { - "comment": "Type of the extra movie file", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Subtitles" + "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subscription unlocks instance notifications, alternate app icons and supports the continued indie development of %@." } } } }, - "System": { - "comment": "Preferences section header", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "System" + "Subtitles" : { + "comment" : "Type of the extra movie file", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Subtitles" } } } }, - "System Settings": { - "comment": "Settings app name", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "System Settings" + "System" : { + "comment" : "Preferences section header", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System" } } } }, - "System Settings > Notifications > %@": { - "comment": "macOS notifications path", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "System Settings > Notifications > %@" + "System Settings" : { + "comment" : "Settings app name", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System Settings" } } } }, - "System Settings > Privacy & Security > Local Network": { - "comment": "macOS local network path", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "System Settings > Privacy & Security > Local Network" + "System Settings > Notifications > %@" : { + "comment" : "macOS notifications path", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System Settings > Notifications > %@" } } } }, - "Tab": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tab" + "System Settings > Privacy & Security > Local Network" : { + "comment" : "macOS local network path", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System Settings > Privacy & Security > Local Network" } } } }, - "Tags": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tags" + "Tab" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tab" } } } }, - "TBA": { - "comment": "(Short, 3-6 characters) Conveying unannounced", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TBA" + "Tags" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tags" } } } }, - "TestFlight for macOS": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TestFlight for macOS" + "TBA" : { + "comment" : "(Short, 3-6 characters) Conveying unannounced", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TBA" } } } }, - "The API Key can be found in the web interface under \"Settings > General > Security\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The API Key can be found in the web interface under \"Settings > General > Security\"." + "TestFlight for macOS" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TestFlight for macOS" } } } }, - "The credentials will be encoded and added as an \"Authorization\" header.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The credentials will be encoded and added as an \"Authorization\" header." + "The API Key can be found in the web interface under \"Settings > General > Security\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The API Key can be found in the web interface under \"Settings > General > Security\"." } } } }, - "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" + "The credentials will be encoded and added as an \"Authorization\" header." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The credentials will be encoded and added as an \"Authorization\" header." } } } }, - "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" + "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The release for this movie could not be determined and it may not import automatically. Do you want to grab \"%@\"?" } } } }, - "The URL used to access the %@ web interface.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The URL used to access the %@ web interface." + "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The release for this series/episode could not be determined and it may not import automatically. Do you want to grab \"%@\"?" } } } }, - "This will permanently erase all episode files of this season.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This will permanently erase all episode files of this season." + "The URL used to access the %@ web interface." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The URL used to access the %@ web interface." } } } }, - "This will permanently erase the episode file.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This will permanently erase the episode file." + "This will permanently erase all episode files of this season." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This will permanently erase all episode files of this season." } } } }, - "This will permanently erase the movie file.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This will permanently erase the movie file." + "This will permanently erase the episode file." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This will permanently erase the episode file." } } } }, - "Time flies when you're having fun.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Time flies when you're having fun." + "This will permanently erase the movie file." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This will permanently erase the movie file." } } } }, - "Title": { - "comment": "Match type of the release\nMedia grid sorting", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Title" + "Time flies when you're having fun." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Time flies when you're having fun." } } } }, - "To monitor a season or episode, the series itself must be monitored.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "To monitor a season or episode, the series itself must be monitored." + "Title" : { + "comment" : "Match type of the release\nMedia grid sorting", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Title" } } } }, - "Today": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Today" + "To monitor a season or episode, the series itself must be monitored." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "To monitor a season or episode, the series itself must be monitored." } } } }, - "Tomorrow": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tomorrow" + "Today" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Today" } } } }, - "Torrent": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Torrent" + "Tomorrow" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tomorrow" } } } }, - "Trailer": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Trailer" + "Torrent" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Torrent" } } } }, - "Translate the App": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Translate the App" + "Trailer" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Trailer" } } } }, - "Try again later.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Try again later." + "Translate the App" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Translate the App" } } } }, - "Try holding your breath.": { - "comment": "Release search taunt", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Try holding your breath." + "Try again later." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Try again later." } } } }, - "Type": { - "comment": "Short version of Series Type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Type" + "Try holding your breath." : { + "comment" : "Release search taunt", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Try holding your breath." } } } }, - "Unable to Import Automatically": { - "comment": "State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unable to Import Automatically" + "Type" : { + "comment" : "Short version of Series Type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Type" } } } }, - "Unaired": { - "comment": "(Single word) Episode status label", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unaired" + "Unable to Import Automatically" : { + "comment" : "State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unable to Import Automatically" } } } }, - "Unannounced": { - "comment": "Media status label\nMissing media title", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unannounced" + "Unaired" : { + "comment" : "(Single word) Episode status label", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unaired" } } } }, - "Uncoded": { - "comment": "Label for uncoded languages", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Uncoded" + "Unannounced" : { + "comment" : "Media status label\nMissing media title", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unannounced" } } } }, - "Undetermined": { - "comment": "Label for unknown/undetermined language", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Undetermined" + "Uncoded" : { + "comment" : "Label for uncoded languages", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uncoded" } } } }, - "Unknown": { - "comment": "(Short) State of task in queue\n(Short) Title of history event\nCommand status\nStatus of task in queue\nStatus of the app subscription", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unknown" + "Undetermined" : { + "comment" : "Label for unknown/undetermined language", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Undetermined" } } } }, - "Unknown Event": { - "comment": "Title of history event type", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unknown Event" + "Unknown" : { + "comment" : "(Short) State of task in queue\n(Short) Title of history event\nStatus of task in queue\nStatus of the app subscription", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unknown" } } } }, - "Unknown event.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unknown event." + "Unknown Event" : { + "comment" : "Title of history event type", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unknown Event" } } } }, - "Unmonitor Specials": { - "comment": "Series monitoring option", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unmonitor Specials" + "Unknown event." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unknown event." } } } }, - "Unmonitored": { - "comment": "Media grid filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unmonitored" + "Unmonitor Specials" : { + "comment" : "Series monitoring option", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unmonitor Specials" } } } }, - "Unrated": { - "comment": "No age/audience rating available", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unrated" + "Unmonitored" : { + "comment" : "Media grid filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unmonitored" } } } }, - "Unreleased": { - "comment": "State of media item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unreleased" + "Unrated" : { + "comment" : "No age/audience rating available", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unrated" } } } }, - "Unsupported URL: %@": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unsupported URL: %@" + "Unreleased" : { + "comment" : "State of media item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unreleased" } } } }, - "Unwanted": { - "comment": "State of media item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Unwanted" + "Unsupported URL: %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unsupported URL: %@" } } } }, - "Upcoming": { - "comment": "(Single word) Series status", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Upcoming" + "Unwanted" : { + "comment" : "State of media item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unwanted" } } } }, - "Upgrade to Sonarr v4.0.5 or newer.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Upgrade to Sonarr v4.0.5 or newer." + "Upcoming" : { + "comment" : "(Single word) Series status", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upcoming" } } } }, - "URL": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "URL" + "Upgrade to Sonarr v4.0.5 or newer." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Upgrade to Sonarr v4.0.5 or newer." } } } }, - "URL identified itself as a %@ instance, not a %@ instance.": { - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "URL identified itself as a %1$@ instance, not a %2$@ instance." + "URL" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL" } } } }, - "URL must start with \"http://\" or \"https://\".": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "URL must start with \"http://\" or \"https://\"." + "URL identified itself as a %@ instance, not a %@ instance." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "URL identified itself as a %1$@ instance, not a %2$@ instance." } } } }, - "URL Not Reachable": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "URL Not Reachable" + "URL must start with \"http://\" or \"https://\"." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL must start with \"http://\" or \"https://\"." } } } }, - "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." + "URL Not Reachable" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL Not Reachable" } } } }, - "Usenet": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Usenet" + "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "URLs must be non-local, \"localhost\" and \"127.0.0.1\" will not work." } } } }, - "User Invoked Search": { - "comment": "Source of the release", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "User Invoked Search" + "Usenet" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usenet" } } } }, - "Username": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Username" + "User Invoked Search" : { + "comment" : "Source of the release", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "User Invoked Search" } } } }, - "Version %@ (%@)": { - "comment": "$1 = version, $2 = build", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Version %1$@ (%2$@)" + "Username" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Username" } } } }, - "Video": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Video" + "Version %@ (%@)" : { + "comment" : "$1 = version, $2 = build", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Version %1$@ (%2$@)" } } } }, - "Waiting": { - "comment": "(Short) State of task in queue\nState of media item", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Waiting" + "Video" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Video" } } } }, - "Waiting to Import": { - "comment": "State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Waiting to Import" + "Waiting" : { + "comment" : "(Short) State of task in queue\nState of media item", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Waiting" } } } }, - "Waiting to Process": { - "comment": "State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Waiting to Process" + "Waiting to Import" : { + "comment" : "State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Waiting to Import" } } } }, - "Wanted": { - "comment": "Media grid filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Wanted" + "Waiting to Process" : { + "comment" : "State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Waiting to Process" } } } }, - "Warning": { - "comment": "(Short) State of task in queue", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Warning" + "Wanted" : { + "comment" : "Media grid filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wanted" } } } }, - "Watch": { - "comment": "Localized name of Apple's Watch app", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Watch" + "Warning" : { + "comment" : "(Short) State of task in queue", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Warning" } } } }, - "Watch Trailer": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Watch Trailer" + "Watch" : { + "comment" : "Localized name of Apple's Watch app", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Watch" } } } }, - "Website": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Website" + "Watch Trailer" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Watch Trailer" } } } }, - "Weight": { - "comment": "Release filter", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Weight" + "Website" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Website" } } } }, - "What happened?": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "What happened?" + "Weight" : { + "comment" : "Release filter", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Weight" } } } }, - "What's New in %@": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "What's New in %@" + "What happened?" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "What happened?" } } } }, - "Whether to ignore the download, or remove it and its file(s) from the download client.": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Whether to ignore the download, or remove it and its file(s) from the download client." + "What's New in %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "What's New in %@" } } } }, - "Wrong Instance Type": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Wrong Instance Type" + "Whether to ignore the download, or remove it and its file(s) from the download client." : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Whether to ignore the download, or remove it and its file(s) from the download client." } } } }, - "Year": { - "comment": "Media grid sorting", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Year" + "Wrong Instance Type" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wrong Instance Type" } } } }, - "Yes": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Yes" + "Year" : { + "comment" : "Media grid sorting", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Year" } } } }, - "Yesterday": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Yesterday" + "Yes" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Yes" } } } }, - "Searches": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Searches" + "Yesterday" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Yesterday" } } } } }, - "version": "1.0" -} + "version" : "1.0" +} \ No newline at end of file From 4c3a4d05e4d7c05046ced32a85b5868dd99edc36 Mon Sep 17 00:00:00 2001 From: joptimus Date: Wed, 8 Apr 2026 12:29:26 -0500 Subject: [PATCH 19/20] apply instance filter to commands section --- Ruddarr/Models/Commands/Commands.swift | 1 - Ruddarr/Views/ActivityView.swift | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index 41fdc803..039e3363 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -64,7 +64,6 @@ struct InstanceCommandStatus: Identifiable, Codable, Equatable, Hashable { "RefreshCollections", "RssSync", "ManualImport", - "ImportListSync", "RenameFiles", "RenameMovie", "RenameSeries", diff --git a/Ruddarr/Views/ActivityView.swift b/Ruddarr/Views/ActivityView.swift index c9de0130..5d4c8e98 100644 --- a/Ruddarr/Views/ActivityView.swift +++ b/Ruddarr/Views/ActivityView.swift @@ -120,7 +120,13 @@ struct ActivityView: View { } var commandItems: [InstanceCommandStatus] { - commands.filteredItems(showAll: true) + var cmds = commands.filteredItems(showAll: true) + if sort.instance != .all { + cmds = cmds.filter { + $0.instanceId?.isEqual(to: sort.instance) == true + } + } + return cmds } var commandsSectionHeader: some View { From 5a2a7f753aff102caa27a568c64c48a7da26cd07 Mon Sep 17 00:00:00 2001 From: joptimus Date: Wed, 8 Apr 2026 12:44:13 -0500 Subject: [PATCH 20/20] set 5 minute time to live after completed --- Ruddarr/Models/Commands/Commands.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Ruddarr/Models/Commands/Commands.swift b/Ruddarr/Models/Commands/Commands.swift index 039e3363..2c963898 100644 --- a/Ruddarr/Models/Commands/Commands.swift +++ b/Ruddarr/Models/Commands/Commands.swift @@ -141,7 +141,6 @@ class Commands { var items: [Instance.ID: [InstanceCommandStatus]] = [:] private let perInstanceLimit = 50 - private let sessionStart = Date() private init() { let interval: TimeInterval = isRunningIn(.preview) ? 30 : 5 @@ -164,10 +163,11 @@ class Commands { } func merge(_ incoming: [InstanceCommandStatus], for instanceId: Instance.ID) { + let visible = incoming.filter { InstanceCommandStatus.visibleCommandNames.contains($0.name) } var existing = items[instanceId] ?? [] let existingById = Dictionary(existing.map { ($0.id, $0) }, uniquingKeysWith: { first, _ in first }) - for var fresh in incoming { + for var fresh in visible { if let prior = existingById[fresh.id], fresh.subject == nil { fresh.subject = prior.subject } @@ -209,7 +209,7 @@ class Commands { func filteredItems(showAll: Bool) -> [InstanceCommandStatus] { let all = items.values.flatMap { $0 } .filter { InstanceCommandStatus.visibleCommandNames.contains($0.name) } - .filter { !$0.isTerminal || $0.queued >= sessionStart } + .filter { !$0.isTerminal || ($0.ended ?? $0.started ?? $0.queued) >= Date().addingTimeInterval(-300) } let filtered = showAll ? all : all.filter { $0.isSearchCommand } return filtered.sorted { $0.sortDate > $1.sortDate } }