From 18b06ff2972ad61d3da34cb112d0eceaf301d91c Mon Sep 17 00:00:00 2001 From: Daniel Chick Date: Wed, 18 Oct 2023 20:14:43 -0500 Subject: [PATCH] Localization strings (#878) --- Shared/Strings/Strings.swift | 80 +++++++++++++++++++ Swiftfin/Views/BasicAppSettingsView.swift | 8 +- Swiftfin/Views/DownloadListView.swift | 2 +- .../DownloadTaskContentView.swift | 6 +- Swiftfin/Views/LiveTVChannelsView.swift | 4 +- Swiftfin/Views/LiveTVHomeView.swift | 2 +- Swiftfin/Views/LiveTVProgramsView.swift | 12 +-- .../FilterDrawerButtonSelectorView.swift | 8 +- .../Views/SettingsView/SettingsView.swift | 12 +-- .../VideoPlayerSettingsView.swift | 44 +++++----- .../VideoPlayer/Components/LoadingView.swift | 4 +- .../Components/PlaybackSettingsView.swift | 12 +-- .../VideoPlayer/Overlays/ChapterOverlay.swift | 2 +- .../Overlays/Components/OverlayMenu.swift | 8 +- Translations/en.lproj/Localizable.strings | 43 ++++++++++ 15 files changed, 185 insertions(+), 62 deletions(-) diff --git a/Shared/Strings/Strings.swift b/Shared/Strings/Strings.swift index 394ddd7a..03a4183d 100644 --- a/Shared/Strings/Strings.swift +++ b/Shared/Strings/Strings.swift @@ -20,6 +20,8 @@ internal enum L10n { internal static let accessibility = L10n.tr("Localizable", "accessibility", fallback: "Accessibility") /// Add URL internal static let addURL = L10n.tr("Localizable", "addURL", fallback: "Add URL") + /// Advanced + internal static let advanced = L10n.tr("Localizable", "advanced", fallback: "Advanced") /// Airs %s internal static func airWithDate(_ p1: UnsafePointer) -> String { return L10n.tr("Localizable", "airWithDate", p1, fallback: "Airs %s") @@ -34,10 +36,14 @@ internal enum L10n { internal static let appIcon = L10n.tr("Localizable", "appIcon", fallback: "App Icon") /// Apply internal static let apply = L10n.tr("Localizable", "apply", fallback: "Apply") + /// Aspect Fill + internal static let aspectFill = L10n.tr("Localizable", "aspectFill", fallback: "Aspect Fill") /// Audio internal static let audio = L10n.tr("Localizable", "audio", fallback: "Audio") /// Audio & Captions internal static let audioAndCaptions = L10n.tr("Localizable", "audioAndCaptions", fallback: "Audio & Captions") + /// Audio Offset + internal static let audioOffset = L10n.tr("Localizable", "audioOffset", fallback: "Audio Offset") /// Audio Track internal static let audioTrack = L10n.tr("Localizable", "audioTrack", fallback: "Audio Track") /// Authorize @@ -46,10 +52,14 @@ internal enum L10n { internal static let autoPlay = L10n.tr("Localizable", "autoPlay", fallback: "Auto Play") /// Back internal static let back = L10n.tr("Localizable", "back", fallback: "Back") + /// Bar Buttons + internal static let barButtons = L10n.tr("Localizable", "barButtons", fallback: "Bar Buttons") /// Blue internal static let blue = L10n.tr("Localizable", "blue", fallback: "Blue") /// Bugs and Features internal static let bugsAndFeatures = L10n.tr("Localizable", "bugsAndFeatures", fallback: "Bugs and Features") + /// Buttons + internal static let buttons = L10n.tr("Localizable", "buttons", fallback: "Buttons") /// Cancel internal static let cancel = L10n.tr("Localizable", "cancel", fallback: "Cancel") /// Cannot connect to host @@ -64,6 +74,8 @@ internal enum L10n { internal static let channels = L10n.tr("Localizable", "channels", fallback: "Channels") /// Chapters internal static let chapters = L10n.tr("Localizable", "chapters", fallback: "Chapters") + /// Chapter Slider + internal static let chapterSlider = L10n.tr("Localizable", "chapterSlider", fallback: "Chapter Slider") /// Cinematic internal static let cinematic = L10n.tr("Localizable", "cinematic", fallback: "Cinematic") /// Cinematic Views @@ -76,6 +88,8 @@ internal enum L10n { internal static let collections = L10n.tr("Localizable", "collections", fallback: "Collections") /// Color internal static let color = L10n.tr("Localizable", "color", fallback: "Color") + /// Coming soon + internal static let comingSoon = L10n.tr("Localizable", "comingSoon", fallback: "Coming soon") /// Compact internal static let compact = L10n.tr("Localizable", "compact", fallback: "Compact") /// Compact Logo @@ -102,6 +116,8 @@ internal enum L10n { internal static let `continue` = L10n.tr("Localizable", "continue", fallback: "Continue") /// Continue Watching internal static let continueWatching = L10n.tr("Localizable", "continueWatching", fallback: "Continue Watching") + /// Current + internal static let current = L10n.tr("Localizable", "current", fallback: "Current") /// Current Position internal static let currentPosition = L10n.tr("Localizable", "currentPosition", fallback: "Current Position") /// Customize @@ -114,6 +130,8 @@ internal enum L10n { internal static let delivery = L10n.tr("Localizable", "delivery", fallback: "Delivery") /// DIRECTOR internal static let director = L10n.tr("Localizable", "director", fallback: "DIRECTOR") + /// Disabled + internal static let disabled = L10n.tr("Localizable", "disabled", fallback: "Disabled") /// Discovered Servers internal static let discoveredServers = L10n.tr("Localizable", "discoveredServers", fallback: "Discovered Servers") /// Dismiss @@ -126,6 +144,8 @@ internal enum L10n { internal static let editJumpLengths = L10n.tr("Localizable", "editJumpLengths", fallback: "Edit Jump Lengths") /// Empty Next Up internal static let emptyNextUp = L10n.tr("Localizable", "emptyNextUp", fallback: "Empty Next Up") + /// Enabled + internal static let enabled = L10n.tr("Localizable", "enabled", fallback: "Enabled") /// Episode Landscape Poster internal static let episodeLandscapePoster = L10n.tr("Localizable", "episodeLandscapePoster", fallback: "Episode Landscape Poster") /// Episode %1$@ @@ -154,6 +174,8 @@ internal enum L10n { internal static let filters = L10n.tr("Localizable", "filters", fallback: "Filters") /// Genres internal static let genres = L10n.tr("Localizable", "genres", fallback: "Genres") + /// Gestures + internal static let gestures = L10n.tr("Localizable", "gestures", fallback: "Gestures") /// Green internal static let green = L10n.tr("Localizable", "green", fallback: "Green") /// Grid @@ -172,6 +194,8 @@ internal enum L10n { internal static let invertedLight = L10n.tr("Localizable", "invertedLight", fallback: "Inverted Light") /// Items internal static let items = L10n.tr("Localizable", "items", fallback: "Items") + /// Jump + internal static let jump = L10n.tr("Localizable", "jump", fallback: "Jump") /// Jump Backward internal static let jumpBackward = L10n.tr("Localizable", "jumpBackward", fallback: "Jump Backward") /// Jump Backward Length @@ -186,6 +210,8 @@ internal enum L10n { internal static func jumpLengthSeconds(_ p1: UnsafePointer) -> String { return L10n.tr("Localizable", "jumpLengthSeconds", p1, fallback: "%s seconds") } + /// Kids + internal static let kids = L10n.tr("Localizable", "kids", fallback: "Kids") /// Larger internal static let larger = L10n.tr("Localizable", "larger", fallback: "Larger") /// Largest @@ -212,8 +238,12 @@ internal enum L10n { internal static func loginToWithString(_ p1: Any) -> String { return L10n.tr("Localizable", "loginToWithString", String(describing: p1), fallback: "Login to %@") } + /// Logs + internal static let logs = L10n.tr("Localizable", "logs", fallback: "Logs") /// Media internal static let media = L10n.tr("Localizable", "media", fallback: "Media") + /// Menu Buttons + internal static let menuButtons = L10n.tr("Localizable", "menuButtons", fallback: "Menu Buttons") /// Missing internal static let missing = L10n.tr("Localizable", "missing", fallback: "Missing") /// Missing Items @@ -228,10 +258,14 @@ internal enum L10n { } /// Name internal static let name = L10n.tr("Localizable", "name", fallback: "Name") + /// Native Player + internal static let nativePlayer = L10n.tr("Localizable", "nativePlayer", fallback: "Native Player") /// Networking internal static let networking = L10n.tr("Localizable", "networking", fallback: "Networking") /// Network timed out internal static let networkTimedOut = L10n.tr("Localizable", "networkTimedOut", fallback: "Network timed out") + /// News + internal static let news = L10n.tr("Localizable", "news", fallback: "News") /// Next internal static let next = L10n.tr("Localizable", "next", fallback: "Next") /// Next Item @@ -268,6 +302,8 @@ internal enum L10n { internal static let ok = L10n.tr("Localizable", "ok", fallback: "Ok") /// 1 user internal static let oneUser = L10n.tr("Localizable", "oneUser", fallback: "1 user") + /// On Now + internal static let onNow = L10n.tr("Localizable", "onNow", fallback: "On Now") /// Operating System internal static let operatingSystem = L10n.tr("Localizable", "operatingSystem", fallback: "Operating System") /// Orange @@ -290,12 +326,18 @@ internal enum L10n { } /// Password internal static let password = L10n.tr("Localizable", "password", fallback: "Password") + /// Pause on background + internal static let pauseOnBackground = L10n.tr("Localizable", "pauseOnBackground", fallback: "Pause on background") /// People internal static let people = L10n.tr("Localizable", "people", fallback: "People") /// Play internal static let play = L10n.tr("Localizable", "play", fallback: "Play") /// Play / Pause internal static let playAndPause = L10n.tr("Localizable", "playAndPause", fallback: "Play / Pause") + /// Playback + internal static let playback = L10n.tr("Localizable", "playback", fallback: "Playback") + /// Playback Buttons + internal static let playbackButtons = L10n.tr("Localizable", "playbackButtons", fallback: "Playback Buttons") /// Playback settings internal static let playbackSettings = L10n.tr("Localizable", "playbackSettings", fallback: "Playback settings") /// Playback Speed @@ -310,6 +352,8 @@ internal enum L10n { internal static let playNext = L10n.tr("Localizable", "playNext", fallback: "Play Next") /// Play Next Item internal static let playNextItem = L10n.tr("Localizable", "playNextItem", fallback: "Play Next Item") + /// Play on active + internal static let playOnActive = L10n.tr("Localizable", "playOnActive", fallback: "Play on active") /// Play Previous Item internal static let playPreviousItem = L10n.tr("Localizable", "playPreviousItem", fallback: "Play Previous Item") /// Posters @@ -364,10 +408,14 @@ internal enum L10n { internal static let regular = L10n.tr("Localizable", "regular", fallback: "Regular") /// Released internal static let released = L10n.tr("Localizable", "released", fallback: "Released") + /// Reload + internal static let reload = L10n.tr("Localizable", "reload", fallback: "Reload") /// Remaining Time internal static let remainingTime = L10n.tr("Localizable", "remainingTime", fallback: "Remaining Time") /// Remove internal static let remove = L10n.tr("Localizable", "remove", fallback: "Remove") + /// Remove All Servers + internal static let removeAllServers = L10n.tr("Localizable", "removeAllServers", fallback: "Remove All Servers") /// Remove All Users internal static let removeAllUsers = L10n.tr("Localizable", "removeAllUsers", fallback: "Remove All Users") /// Remove From Resume @@ -378,16 +426,26 @@ internal enum L10n { internal static let requestFeature = L10n.tr("Localizable", "requestFeature", fallback: "Request a Feature") /// Reset internal static let reset = L10n.tr("Localizable", "reset", fallback: "Reset") + /// Reset all settings back to defaults. + internal static let resetAllSettings = L10n.tr("Localizable", "resetAllSettings", fallback: "Reset all settings back to defaults.") /// Reset App Settings internal static let resetAppSettings = L10n.tr("Localizable", "resetAppSettings", fallback: "Reset App Settings") /// Reset User Settings internal static let resetUserSettings = L10n.tr("Localizable", "resetUserSettings", fallback: "Reset User Settings") /// Resume 5 Second Offset internal static let resume5SecondOffset = L10n.tr("Localizable", "resume5SecondOffset", fallback: "Resume 5 Second Offset") + /// Resume Offset + internal static let resumeOffset = L10n.tr("Localizable", "resumeOffset", fallback: "Resume Offset") + /// Resume content seconds before the recorded resume time + internal static let resumeOffsetDescription = L10n.tr("Localizable", "resumeOffsetDescription", fallback: "Resume content seconds before the recorded resume time") + /// Retrieving media information + internal static let retrievingMediaInformation = L10n.tr("Localizable", "retrievingMediaInformation", fallback: "Retrieving media information") /// Retry internal static let retry = L10n.tr("Localizable", "retry", fallback: "Retry") /// Runtime internal static let runtime = L10n.tr("Localizable", "runtime", fallback: "Runtime") + /// Scrub Current Time + internal static let scrubCurrentTime = L10n.tr("Localizable", "scrubCurrentTime", fallback: "Scrub Current Time") /// Search internal static let search = L10n.tr("Localizable", "search", fallback: "Search") /// Search… @@ -458,6 +516,12 @@ internal enum L10n { internal static func signInToServer(_ p1: UnsafePointer) -> String { return L10n.tr("Localizable", "signInToServer", p1, fallback: "Sign In to %s") } + /// Slider + internal static let slider = L10n.tr("Localizable", "slider", fallback: "Slider") + /// Slider Color + internal static let sliderColor = L10n.tr("Localizable", "sliderColor", fallback: "Slider Color") + /// Slider Type + internal static let sliderType = L10n.tr("Localizable", "sliderType", fallback: "Slider Type") /// Smaller internal static let smaller = L10n.tr("Localizable", "smaller", fallback: "Smaller") /// Smallest @@ -470,14 +534,20 @@ internal enum L10n { internal static let sourceCode = L10n.tr("Localizable", "sourceCode", fallback: "Source Code") /// Special Features internal static let specialFeatures = L10n.tr("Localizable", "specialFeatures", fallback: "Special Features") + /// Sports + internal static let sports = L10n.tr("Localizable", "sports", fallback: "Sports") /// STUDIO internal static let studio = L10n.tr("Localizable", "studio", fallback: "STUDIO") /// Studios internal static let studios = L10n.tr("Localizable", "studios", fallback: "Studios") /// Subtitle internal static let subtitle = L10n.tr("Localizable", "subtitle", fallback: "Subtitle") + /// Subtitle Color + internal static let subtitleColor = L10n.tr("Localizable", "subtitleColor", fallback: "Subtitle Color") /// Subtitle Font internal static let subtitleFont = L10n.tr("Localizable", "subtitleFont", fallback: "Subtitle Font") + /// Subtitle Offset + internal static let subtitleOffset = L10n.tr("Localizable", "subtitleOffset", fallback: "Subtitle Offset") /// Subtitles internal static let subtitles = L10n.tr("Localizable", "subtitles", fallback: "Subtitles") /// Subtitle Size @@ -492,8 +562,16 @@ internal enum L10n { internal static let systemControlGesturesEnabled = L10n.tr("Localizable", "systemControlGesturesEnabled", fallback: "System Control Gestures Enabled") /// Tags internal static let tags = L10n.tr("Localizable", "tags", fallback: "Tags") + /// Timestamp + internal static let timestamp = L10n.tr("Localizable", "timestamp", fallback: "Timestamp") + /// Timestamp Type + internal static let timestampType = L10n.tr("Localizable", "timestampType", fallback: "Timestamp Type") /// Too Many Redirects internal static let tooManyRedirects = L10n.tr("Localizable", "tooManyRedirects", fallback: "Too Many Redirects") + /// Trailing Value + internal static let trailingValue = L10n.tr("Localizable", "trailingValue", fallback: "Trailing Value") + /// Transition + internal static let transition = L10n.tr("Localizable", "transition", fallback: "Transition") /// Try again internal static let tryAgain = L10n.tr("Localizable", "tryAgain", fallback: "Try again") /// TV Shows @@ -534,6 +612,8 @@ internal enum L10n { internal static let video = L10n.tr("Localizable", "video", fallback: "Video") /// Video Player internal static let videoPlayer = L10n.tr("Localizable", "videoPlayer", fallback: "Video Player") + /// Video Player Type + internal static let videoPlayerType = L10n.tr("Localizable", "videoPlayerType", fallback: "Video Player Type") /// Who's watching? internal static let whosWatching = L10n.tr("Localizable", "WhosWatching", fallback: "Who's watching?") /// WIP diff --git a/Swiftfin/Views/BasicAppSettingsView.swift b/Swiftfin/Views/BasicAppSettingsView.swift index 1e4916f2..5b3236e6 100644 --- a/Swiftfin/Views/BasicAppSettingsView.swift +++ b/Swiftfin/Views/BasicAppSettingsView.swift @@ -55,7 +55,7 @@ struct BasicAppSettingsView: View { L10n.accentColorDescription.text } - ChevronButton(title: "Logs") + ChevronButton(title: L10n.logs) .onSelect { router.route(to: \.log) } @@ -70,7 +70,7 @@ struct BasicAppSettingsView: View { Button { removeAllServersSelected = true } label: { - Text("Remove All Servers") + Text(L10n.removeAllServers) } } } @@ -79,9 +79,9 @@ struct BasicAppSettingsView: View { viewModel.resetUserSettings() } } message: { - Text("Reset all settings back to defaults.") + Text(L10n.resetAllSettings) } - .alert("Remove All Servers", isPresented: $removeAllServersSelected) { + .alert(L10n.removeAllServers, isPresented: $removeAllServersSelected) { Button(L10n.reset, role: .destructive) { viewModel.removeAllServers() } diff --git a/Swiftfin/Views/DownloadListView.swift b/Swiftfin/Views/DownloadListView.swift index 5ab2ae03..02612787 100644 --- a/Swiftfin/Views/DownloadListView.swift +++ b/Swiftfin/Views/DownloadListView.swift @@ -20,7 +20,7 @@ struct DownloadListView: View { DownloadTaskRow(downloadTask: item) } } - .navigationTitle("Downloads") + .navigationTitle(L10n.downloads) .navigationBarTitleDisplayMode(.inline) } } diff --git a/Swiftfin/Views/DownloadTaskView/DownloadTaskContentView.swift b/Swiftfin/Views/DownloadTaskView/DownloadTaskContentView.swift index 8b02bb82..8f42e746 100644 --- a/Swiftfin/Views/DownloadTaskView/DownloadTaskContentView.swift +++ b/Swiftfin/Views/DownloadTaskView/DownloadTaskContentView.swift @@ -75,7 +75,7 @@ extension DownloadTaskView { .padding(.horizontal) case let .error(error): VStack { - PrimaryButton(title: "Retry") + PrimaryButton(title: L10n.retry) .onSelect { downloadManager.download(task: downloadTask) } @@ -86,7 +86,7 @@ extension DownloadTaskView { .padding(.horizontal) } case .complete: - PrimaryButton(title: "Play") + PrimaryButton(title: L10n.play) .onSelect { if Defaults[.VideoPlayer.videoPlayerType] == .swiftfin { router.dismissCoordinator { @@ -113,7 +113,7 @@ extension DownloadTaskView { Button { isPresentingVideoPlayerTypeError = false } label: { - Text("Dismiss") + Text(L10n.dismiss) } } message: { Text("Downloaded items are only playable through the Swiftfin video player.") diff --git a/Swiftfin/Views/LiveTVChannelsView.swift b/Swiftfin/Views/LiveTVChannelsView.swift index 44994369..26692257 100644 --- a/Swiftfin/Views/LiveTVChannelsView.swift +++ b/Swiftfin/Views/LiveTVChannelsView.swift @@ -80,11 +80,11 @@ struct LiveTVChannelsView: View { } } else { VStack { - Text("No results.") + Text(L10n.noResults) Button { viewModel.getChannels() } label: { - Text("Reload") + Text(L10n.reload) } } } diff --git a/Swiftfin/Views/LiveTVHomeView.swift b/Swiftfin/Views/LiveTVHomeView.swift index d7a1c8cb..42a23e6d 100644 --- a/Swiftfin/Views/LiveTVHomeView.swift +++ b/Swiftfin/Views/LiveTVHomeView.swift @@ -11,6 +11,6 @@ import SwiftUI struct LiveTVHomeView: View { var body: some View { - Text("Coming Soon") + Text(L10n.comingSoon) } } diff --git a/Swiftfin/Views/LiveTVProgramsView.swift b/Swiftfin/Views/LiveTVProgramsView.swift index 3f7756c2..d1c93599 100644 --- a/Swiftfin/Views/LiveTVProgramsView.swift +++ b/Swiftfin/Views/LiveTVProgramsView.swift @@ -21,7 +21,7 @@ struct LiveTVProgramsView: View { LazyVStack(alignment: .leading) { if !viewModel.recommendedItems.isEmpty { let items = viewModel.recommendedItems - PosterHStack(title: "On Now", type: .portrait, items: items) + PosterHStack(title: L10n.onNow, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) @@ -34,7 +34,7 @@ struct LiveTVProgramsView: View { } if !viewModel.seriesItems.isEmpty { let items = viewModel.seriesItems - PosterHStack(title: "Shows", type: .portrait, items: items) + PosterHStack(title: L10n.tvShows, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) @@ -47,7 +47,7 @@ struct LiveTVProgramsView: View { } if !viewModel.movieItems.isEmpty { let items = viewModel.movieItems - PosterHStack(title: "Movies", type: .portrait, items: items) + PosterHStack(title: L10n.movies, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) @@ -60,7 +60,7 @@ struct LiveTVProgramsView: View { } if !viewModel.sportsItems.isEmpty { let items = viewModel.sportsItems - PosterHStack(title: "Sports", type: .portrait, items: items) + PosterHStack(title: L10n.sports, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) @@ -73,7 +73,7 @@ struct LiveTVProgramsView: View { } if !viewModel.kidsItems.isEmpty { let items = viewModel.kidsItems - PosterHStack(title: "Kids", type: .portrait, items: items) + PosterHStack(title: L10n.kids, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) @@ -86,7 +86,7 @@ struct LiveTVProgramsView: View { } if !viewModel.newsItems.isEmpty { let items = viewModel.newsItems - PosterHStack(title: "News", type: .portrait, items: items) + PosterHStack(title: L10n.news, type: .portrait, items: items) // .onSelect { item in // if let chanId = item.channelId, // let chan = viewModel.findChannel(id: chanId) diff --git a/Swiftfin/Views/SettingsView/FilterDrawerSettingsView/Components/FilterDrawerButtonSelectorView.swift b/Swiftfin/Views/SettingsView/FilterDrawerSettingsView/Components/FilterDrawerButtonSelectorView.swift index 62bc33ac..1c4e997e 100644 --- a/Swiftfin/Views/SettingsView/FilterDrawerSettingsView/Components/FilterDrawerButtonSelectorView.swift +++ b/Swiftfin/Views/SettingsView/FilterDrawerSettingsView/Components/FilterDrawerButtonSelectorView.swift @@ -51,11 +51,11 @@ struct FilterDrawerButtonSelectorView: View { .onMove(perform: move) if _selectedButtons.isEmpty { - Text("None") + Text(L10n.none) .foregroundColor(.secondary) } } header: { - Text("Enabled") + Text(L10n.enabled) } Section { @@ -80,11 +80,11 @@ struct FilterDrawerButtonSelectorView: View { } if disabledButtons.isEmpty { - Text("None") + Text(L10n.none) .foregroundColor(.secondary) } } header: { - Text("Disabled") + Text(L10n.disabled) } } .animation(.linear(duration: 0.2), value: _selectedButtons) diff --git a/Swiftfin/Views/SettingsView/SettingsView.swift b/Swiftfin/Views/SettingsView/SettingsView.swift index 863afa27..caf8ba32 100644 --- a/Swiftfin/Views/SettingsView/SettingsView.swift +++ b/Swiftfin/Views/SettingsView/SettingsView.swift @@ -63,11 +63,11 @@ struct SettingsView: View { Section { EnumPicker( - title: "Video Player Type", + title: L10n.videoPlayerType, selection: $videoPlayerType ) - ChevronButton(title: "Native Player") + ChevronButton(title: L10n.nativePlayer) .onSelect { router.route(to: \.nativePlayerSettings) } @@ -83,7 +83,7 @@ struct SettingsView: View { Section { EnumPicker(title: L10n.appearance, selection: $appAppearance) - ChevronButton(title: "App Icon") + ChevronButton(title: L10n.appIcon) .onSelect { router.route(to: \.appIconSelector) } @@ -102,9 +102,9 @@ struct SettingsView: View { } Section { - ColorPicker("Accent Color", selection: $accentColor, supportsOpacity: false) + ColorPicker(L10n.accentColor, selection: $accentColor, supportsOpacity: false) } footer: { - Text("Some views may need an app restart to update.") + Text(L10n.accentColorDescription) } ChevronButton(title: L10n.about) @@ -112,7 +112,7 @@ struct SettingsView: View { router.route(to: \.about) } - ChevronButton(title: "Logs") + ChevronButton(title: L10n.logs) .onSelect { router.route(to: \.log) } diff --git a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift index 1e6323c0..4dc4ee34 100644 --- a/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift +++ b/Swiftfin/Views/SettingsView/VideoPlayerSettingsView/VideoPlayerSettingsView.swift @@ -65,7 +65,7 @@ struct VideoPlayerSettingsView: View { var body: some View { Form { - ChevronButton(title: "Gestures") + ChevronButton(title: L10n.gestures) .onSelect { router.route(to: \.gestureSettings) } @@ -77,7 +77,7 @@ struct VideoPlayerSettingsView: View { Section { BasicStepper( - title: "Resume Offset", + title: L10n.resumeOffset, value: $resumeOffset, range: 0 ... 30, step: 1 @@ -86,40 +86,40 @@ struct VideoPlayerSettingsView: View { $0.secondFormat } } footer: { - Text("Resume content seconds before the recorded resume time") + Text(L10n.resumeOffsetDescription) } - Section("Buttons") { + Section(L10n.buttons) { - EnumPicker(title: "Playback Buttons", selection: $playbackButtonType) + EnumPicker(title: L10n.playbackButtons, selection: $playbackButtonType) Toggle(isOn: $showJumpButtons) { HStack { Image(systemName: "goforward") - Text("Jump") + Text(L10n.jump) } } - ChevronButton(title: "Bar Buttons") + ChevronButton(title: L10n.barButtons) .onSelect { router.route(to: \.actionButtonSelector, $barActionButtons) } - ChevronButton(title: "Menu Buttons") + ChevronButton(title: L10n.menuButtons) .onSelect { router.route(to: \.actionButtonSelector, $menuActionButtons) } } - Section("Slider") { + Section(L10n.slider) { - Toggle("Chapter Slider", isOn: $chapterSlider) + Toggle(L10n.chapterSlider, isOn: $chapterSlider) ColorPicker(selection: $sliderColor, supportsOpacity: false) { - Text("Slider Color") + Text(L10n.sliderColor) } - EnumPicker(title: "Slider Type", selection: $sliderType) + EnumPicker(title: L10n.sliderType, selection: $sliderType) } Section { @@ -137,31 +137,31 @@ struct VideoPlayerSettingsView: View { ) ColorPicker(selection: $subtitleColor, supportsOpacity: false) { - Text("Subtitle Color") + Text(L10n.subtitleColor) } } header: { - Text("Subtitle") + Text(L10n.subtitle) } footer: { // TODO: better wording Text("Settings only affect some subtitle types") } - Section("Timestamp") { + Section(L10n.timestamp) { - Toggle("Scrub Current Time", isOn: $showCurrentTimeWhileScrubbing) + Toggle(L10n.scrubCurrentTime, isOn: $showCurrentTimeWhileScrubbing) - EnumPicker(title: "Timestamp Type", selection: $timestampType) + EnumPicker(title: L10n.timestampType, selection: $timestampType) - EnumPicker(title: "Trailing Value", selection: $trailingTimestampType) + EnumPicker(title: L10n.trailingValue, selection: $trailingTimestampType) } - Section("Transition") { + Section(L10n.transition) { - Toggle("Pause on background", isOn: $pauseOnBackground) - Toggle("Play on active", isOn: $playOnActive) + Toggle(L10n.pauseOnBackground, isOn: $pauseOnBackground) + Toggle(L10n.playOnActive, isOn: $playOnActive) } } - .navigationTitle("Video Player") + .navigationTitle(L10n.videoPlayer) .onChange(of: barActionButtons) { newValue in autoPlayEnabled = newValue.contains(.autoPlay) || menuActionButtons.contains(.autoPlay) } diff --git a/Swiftfin/Views/VideoPlayer/Components/LoadingView.swift b/Swiftfin/Views/VideoPlayer/Components/LoadingView.swift index 26761193..eee393fb 100644 --- a/Swiftfin/Views/VideoPlayer/Components/LoadingView.swift +++ b/Swiftfin/Views/VideoPlayer/Components/LoadingView.swift @@ -22,7 +22,7 @@ extension VideoPlayer { VStack(spacing: 10) { - Text("Retrieving media information") + Text(L10n.retrievingMediaInformation) .foregroundColor(.white) ProgressView() @@ -30,7 +30,7 @@ extension VideoPlayer { Button { router.dismissCoordinator() } label: { - Text("Cancel") + Text(L10n.cancel) .foregroundColor(.red) .padding() .overlay { diff --git a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift index dd8e909b..6d6bcfff 100644 --- a/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift +++ b/Swiftfin/Views/VideoPlayer/Components/PlaybackSettingsView.swift @@ -45,7 +45,7 @@ struct PlaybackSettingsView: View { } BasicStepper( - title: "Audio Offset", + title: L10n.audioOffset, value: _audioOffset.wrappedValue, range: -30000 ... 30000, step: 100 @@ -55,7 +55,7 @@ struct PlaybackSettingsView: View { } BasicStepper( - title: "Subtitle Offset", + title: L10n.subtitleOffset, value: _subtitleOffset.wrappedValue, range: -30000 ... 30000, step: 100 @@ -65,7 +65,7 @@ struct PlaybackSettingsView: View { } if !viewModel.videoStreams.isEmpty { - Section("Video") { + Section(L10n.video) { ForEach(viewModel.videoStreams, id: \.displayTitle) { mediaStream in ChevronButton(title: mediaStream.displayTitle ?? .emptyDash) .onSelect { @@ -76,7 +76,7 @@ struct PlaybackSettingsView: View { } if !viewModel.audioStreams.isEmpty { - Section("Audio") { + Section(L10n.audio) { ForEach(viewModel.audioStreams, id: \.displayTitle) { mediaStream in ChevronButton(title: mediaStream.displayTitle ?? .emptyDash) .onSelect { @@ -87,7 +87,7 @@ struct PlaybackSettingsView: View { } if !viewModel.subtitleStreams.isEmpty { - Section("Subtitle") { + Section(L10n.subtitle) { ForEach(viewModel.subtitleStreams, id: \.displayTitle) { mediaStream in ChevronButton(title: mediaStream.displayTitle ?? .emptyDash) .onSelect { @@ -97,7 +97,7 @@ struct PlaybackSettingsView: View { } } } - .navigationTitle("Playback") + .navigationTitle(L10n.playback) .navigationBarTitleDisplayMode(.inline) .navigationCloseButton { splitContentViewProxy.hide() diff --git a/Swiftfin/Views/VideoPlayer/Overlays/ChapterOverlay.swift b/Swiftfin/Views/VideoPlayer/Overlays/ChapterOverlay.swift index ce7d3cf2..6863ccf6 100644 --- a/Swiftfin/Views/VideoPlayer/Overlays/ChapterOverlay.swift +++ b/Swiftfin/Views/VideoPlayer/Overlays/ChapterOverlay.swift @@ -60,7 +60,7 @@ extension VideoPlayer.Overlay { } } } label: { - Text("Current") + Text(L10n.current) .font(.title2) .foregroundColor(accentColor) } diff --git a/Swiftfin/Views/VideoPlayer/Overlays/Components/OverlayMenu.swift b/Swiftfin/Views/VideoPlayer/Overlays/Components/OverlayMenu.swift index 816673c4..7b44e93d 100644 --- a/Swiftfin/Views/VideoPlayer/Overlays/Components/OverlayMenu.swift +++ b/Swiftfin/Views/VideoPlayer/Overlays/Components/OverlayMenu.swift @@ -30,7 +30,7 @@ extension VideoPlayer.Overlay { HStack { Image(systemName: "gearshape.fill") - Text("Advanced") + Text(L10n.advanced) } } } @@ -45,7 +45,7 @@ extension VideoPlayer.Overlay { Image(systemName: "arrow.up.left.and.arrow.down.right") } - Text("Aspect Fill") + Text(L10n.aspectFill) } } } @@ -113,7 +113,7 @@ extension VideoPlayer.Overlay { HStack { Image(systemName: "chevron.right.circle") - Text("Play Next Item") + Text(L10n.playNextItem) } } } @@ -126,7 +126,7 @@ extension VideoPlayer.Overlay { HStack { Image(systemName: "chevron.left.circle") - Text("Play Previous Item") + Text(L10n.playPreviousItem) } } } diff --git a/Translations/en.lproj/Localizable.strings b/Translations/en.lproj/Localizable.strings index ac6a47f3..60e07501 100644 --- a/Translations/en.lproj/Localizable.strings +++ b/Translations/en.lproj/Localizable.strings @@ -8,6 +8,7 @@ "cast" = "CAST"; "changeServer" = "Change Server"; "closedCaptions" = "Closed Captions"; +"comingSoon" = "Coming soon"; "connect" = "Connect"; "connectManually" = "Connect Manually"; "connectToJellyfin" = "Connect to Jellyfin"; @@ -39,8 +40,10 @@ "password" = "Password"; "playNext" = "Play Next"; "play" = "Play"; +"playback" = "Playback"; "playbackSettings" = "Playback settings"; "playbackSpeed" = "Playback Speed"; +"reload" = "Reload"; "reset" = "Reset"; "seasonAndEpisode" = "S%1$@:E%2$@"; "search" = "Search"; @@ -77,6 +80,10 @@ /* Represents the light theme setting */ "light" = "Light"; +"advanced" = "Advanced"; +"aspectFill" = "Aspect Fill"; +"enabled" = "Enabled"; +"disabled" = "Disabled"; "existingServer" = "Existing Server"; "existingUser" = "Existing User"; "serverAlreadyConnected" = "Server %s is already connected"; @@ -90,8 +97,10 @@ "defaultScheme" = "Default Scheme"; "networking" = "Networking"; "resetUserSettings" = "Reset User Settings"; +"resetAllSettings" = "Reset all settings back to defaults."; "resetAppSettings" = "Reset App Settings"; "removeAllUsers" = "Remove All Users"; +"removeAllServers" = "Remove All Servers"; "settings" = "Settings"; "cancel" = "Cancel"; "connectToJellyfinServer" = "Connect to a Jellyfin server"; @@ -128,16 +137,24 @@ "overlayType" = "Overlay Type"; "user" = "User"; "server" = "Server"; +"nativePlayer" = "Native Player"; "videoPlayer" = "Video Player"; +"videoPlayerType" = "Video Player Type"; +"gestures" = "Gestures"; "jumpForwardLength" = "Jump Forward Length"; "jumpBackwardLength" = "Jump Backward Length"; "jumpGesturesEnabled" = "Jump Gestures Enabled"; "systemControlGesturesEnabled" = "System Control Gestures Enabled"; "playerGesturesLockGestureEnabled" = "Player Gestures Lock Gesture Enabled"; "seekSlideGestureEnabled" = "Seek Slide Gesture Enabled"; +"audioOffset" = "Audio Offset"; +"subtitleOffset" = "Subtitle Offset"; +"resumeOffset" = "Resume Offset"; +"resumeOffsetDescription" = "Resume content seconds before the recorded resume time"; "resume5SecondOffset" = "Resume 5 Second Offset"; "showPosterLabels" = "Show Poster Labels"; "showCastAndCrew" = "Show Cast & Crew"; +"subtitleColor" = "Subtitle Color"; "subtitleSize" = "Subtitle Size"; "subtitleFont" = "Subtitle Font"; "signInGetStarted" = "Sign in to get started"; @@ -193,6 +210,7 @@ "customize" = "Customize"; "tooManyRedirects" = "Too Many Redirects"; "chapters" = "Chapters"; +"current" = "Current"; "currentPosition" = "Current Position"; "remainingTime" = "Remaining Time"; "sourceCode" = "Source Code"; @@ -262,3 +280,28 @@ "random" = "Random"; "grid" = "Grid"; "list" = "List"; +"logs" = "Logs"; + +"onNow" = "On Now"; +"sports" = "Sports"; +"kids" = "Kids"; +"news" = "News"; + +"buttons" = "Buttons"; +"playbackButtons" = "Playback Buttons"; +"barButtons" = "Bar Buttons"; +"menuButtons" = "Menu Buttons"; +"jump" = "Jump"; +"slider" = "Slider"; +"chapterSlider" = "Chapter Slider"; +"sliderColor" = "Slider Color"; +"sliderType" = "Slider Type"; +"timestamp" = "Timestamp"; +"scrubCurrentTime" = "Scrub Current Time"; +"timestampType" = "Timestamp Type"; +"trailingValue" = "Trailing Value"; +"transition" = "Transition"; +"pauseOnBackground" = "Pause on background"; +"playOnActive" = "Play on active"; + +"retrievingMediaInformation" = "Retrieving media information";