Implement localization for hardcoded strings (#1510)

* first string

* add a bunch of localization

* more hardcode to localization

* small changes for two strings

* fix space formatting

* Update Localizable.strings

Put the localizations back in. Don't know why this changes anything but 🤷‍♂️

* Fix encoding

Why???

Also, missing ;

* implement requested changes

---------

Co-authored-by: Joe Kribs <jpkribs@outlook.com>
This commit is contained in:
Rasko 2025-05-02 19:04:34 +02:00 committed by GitHub
parent 78e9d86a34
commit 103982f6e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 124 additions and 58 deletions

View File

@ -31,7 +31,7 @@ struct TruncatedText: View {
private var isTruncatedBinding: Binding<Bool>
private var onSeeMore: () -> Void
private let seeMoreText = "\u{2026} See More"
private let seeMoreText = "\u{2026}" + L10n.seeMore
private var seeMoreType: SeeMoreType
private let text: String

View File

@ -17,9 +17,9 @@ extension ItemSortOrder: Displayable {
var displayTitle: String {
switch self {
case .ascending:
return "Ascending"
return L10n.ascending
case .descending:
return "Descending"
return L10n.descending
}
}
}

View File

@ -19,7 +19,7 @@ enum CustomDeviceProfileAction: String, CaseIterable, Displayable, Storable {
case .add:
return L10n.add
case .replace:
return "Replace"
return L10n.replace
}
}
}

View File

@ -26,7 +26,7 @@ enum LongPressAction: String, GestureAction {
case .none:
return L10n.none
case .gestureLock:
return "Gesture Lock"
return L10n.gestureLock
}
}
}
@ -60,7 +60,7 @@ enum DoubleTouchAction: String, GestureAction {
case .aspectFill:
return L10n.aspectFill
case .gestureLock:
return "Gesture Lock"
return L10n.gestureLock
case .pausePlay:
return L10n.playAndPause
}
@ -85,17 +85,17 @@ enum PanAction: String, GestureAction {
case .audioffset:
return L10n.audioOffset
case .brightness:
return "Brightness"
return L10n.brightness
case .playbackSpeed:
return L10n.playbackSpeed
case .scrub:
return "Scrub"
return L10n.scrub
case .slowScrub:
return "Slow Scrub"
return L10n.slowScrub
case .subtitleOffset:
return L10n.subtitleOffset
case .volume:
return "Volume"
return L10n.volume
}
}
}

View File

@ -32,7 +32,7 @@ enum PlaybackButtonType: String, CaseIterable, Displayable, Defaults.Serializabl
var displayTitle: String {
switch self {
case .large:
return "Large"
return L10n.large
case .compact:
return L10n.compact
}

View File

@ -15,13 +15,12 @@ enum PosterDisplayType: String, CaseIterable, Displayable, Storable, SystemImage
case landscape
case portrait
// TODO: localize
var displayTitle: String {
switch self {
case .landscape:
"Landscape"
L10n.landscape
case .portrait:
"Portrait"
L10n.portrait
}
}

View File

@ -17,9 +17,9 @@ enum SliderType: String, CaseIterable, Displayable, Defaults.Serializable {
var displayTitle: String {
switch self {
case .thumb:
return "Thumb"
return L10n.thumbSlider
case .capsule:
return "Capsule"
return L10n.capsule
}
}
}

View File

@ -17,7 +17,7 @@ enum TimestampType: String, CaseIterable, Defaults.Serializable, Displayable {
var displayTitle: String {
switch self {
case .split:
return "Split"
return L10n.split
case .compact:
return L10n.compact
}

View File

@ -17,9 +17,9 @@ enum TrailingTimestampType: String, CaseIterable, Displayable, Defaults.Serializ
var displayTitle: String {
switch self {
case .timeLeft:
return "Time left"
return L10n.timeLeft
case .totalTime:
return "Total time"
return L10n.totalTime
}
}
}

View File

@ -23,7 +23,7 @@ enum UserAccessPolicy: String, CaseIterable, Codable, Displayable {
case .none:
L10n.none
case .requireDeviceAuthentication:
"Device Authentication"
L10n.deviceAuth
case .requirePin:
L10n.pin
}

View File

@ -19,7 +19,7 @@ enum VideoPlayerType: String, CaseIterable, Defaults.Serializable, Displayable {
var displayTitle: String {
switch self {
case .native:
"Native"
L10n.native
case .swiftfin:
"Swiftfin"
}

View File

@ -128,6 +128,8 @@ internal enum L10n {
internal static let art = L10n.tr("Localizable", "art", fallback: "Art")
/// Artist
internal static let artist = L10n.tr("Localizable", "artist", fallback: "Artist")
/// Ascending
internal static let ascending = L10n.tr("Localizable", "ascending", fallback: "Ascending")
/// Aspect Fill
internal static let aspectFill = L10n.tr("Localizable", "aspectFill", fallback: "Aspect Fill")
/// Audio
@ -238,6 +240,8 @@ internal enum L10n {
internal static let box = L10n.tr("Localizable", "box", fallback: "Box")
/// BoxRear
internal static let boxRear = L10n.tr("Localizable", "boxRear", fallback: "BoxRear")
/// Brightness
internal static let brightness = L10n.tr("Localizable", "brightness", fallback: "Brightness")
/// Bugs and Features
internal static let bugsAndFeatures = L10n.tr("Localizable", "bugsAndFeatures", fallback: "Bugs and Features")
/// Buttons
@ -250,12 +254,16 @@ internal enum L10n {
internal static let cannotConnectToHost = L10n.tr("Localizable", "cannotConnectToHost", fallback: "Cannot connect to host")
/// Capabilities
internal static let capabilities = L10n.tr("Localizable", "capabilities", fallback: "Capabilities")
/// Capsule
internal static let capsule = L10n.tr("Localizable", "capsule", fallback: "Capsule")
/// Cast & Crew
internal static let castAndCrew = L10n.tr("Localizable", "castAndCrew", fallback: "Cast & Crew")
/// Category
internal static let category = L10n.tr("Localizable", "category", fallback: "Category")
/// Change Pin
internal static let changePin = L10n.tr("Localizable", "changePin", fallback: "Change Pin")
/// Channel display
internal static let channelDisplay = L10n.tr("Localizable", "channelDisplay", fallback: "Channel display")
/// Channels
internal static let channels = L10n.tr("Localizable", "channels", fallback: "Channels")
/// Chapter
@ -282,6 +290,10 @@ internal enum L10n {
internal static let colorist = L10n.tr("Localizable", "colorist", fallback: "Colorist")
/// Columns
internal static let columns = L10n.tr("Localizable", "columns", fallback: "Columns")
/// Columns: %@
internal static func columnsWithCount(_ p1: Any) -> String {
return L10n.tr("Localizable", "columnsWithCount", String(describing: p1), fallback: "Columns: %@")
}
/// Community
internal static let community = L10n.tr("Localizable", "community", fallback: "Community")
/// Community rating
@ -304,6 +316,10 @@ internal enum L10n {
internal static let conductor = L10n.tr("Localizable", "conductor", fallback: "Conductor")
/// Confirm
internal static let confirm = L10n.tr("Localizable", "confirm", fallback: "Confirm")
/// Are you sure you want to delete %@ and all of its connected users?
internal static func confirmDeleteServerAndUsers(_ p1: Any) -> String {
return L10n.tr("Localizable", "confirmDeleteServerAndUsers", String(describing: p1), fallback: "Are you sure you want to delete %@ and all of its connected users?")
}
/// Confirm New Password
internal static let confirmNewPassword = L10n.tr("Localizable", "confirmNewPassword", fallback: "Confirm New Password")
/// Confirm Password
@ -408,6 +424,8 @@ internal enum L10n {
internal static let dayOfWeek = L10n.tr("Localizable", "dayOfWeek", fallback: "Day of Week")
/// Days
internal static let days = L10n.tr("Localizable", "days", fallback: "Days")
/// Decrease playback speed
internal static let decreasePlaybackSpeed = L10n.tr("Localizable", "decreasePlaybackSpeed", fallback: "Decrease playback speed")
/// Default
internal static let `default` = L10n.tr("Localizable", "default", fallback: "Default")
/// Admins are locked out after 5 failed attempts. Non-admins are locked out after 3 attempts.
@ -482,12 +500,18 @@ internal enum L10n {
internal static let deletion = L10n.tr("Localizable", "deletion", fallback: "Deletion")
/// Delivery
internal static let delivery = L10n.tr("Localizable", "delivery", fallback: "Delivery")
/// Descending
internal static let descending = L10n.tr("Localizable", "descending", fallback: "Descending")
/// Detailed
internal static let detailed = L10n.tr("Localizable", "detailed", fallback: "Detailed")
/// Details
internal static let details = L10n.tr("Localizable", "details", fallback: "Details")
/// Device
internal static let device = L10n.tr("Localizable", "device", fallback: "Device")
/// Device Access
internal static let deviceAccess = L10n.tr("Localizable", "deviceAccess", fallback: "Device Access")
/// Device authentication
internal static let deviceAuth = L10n.tr("Localizable", "deviceAuth", fallback: "Device authentication")
/// Device authentication failed
internal static let deviceAuthFailed = L10n.tr("Localizable", "deviceAuthFailed", fallback: "Device authentication failed")
/// Device Profile
@ -540,8 +564,8 @@ internal enum L10n {
internal static let dvd = L10n.tr("Localizable", "dvd", fallback: "DVD")
/// Edit
internal static let edit = L10n.tr("Localizable", "edit", fallback: "Edit")
/// Edit collections
internal static let editCollections = L10n.tr("Localizable", "editCollections", fallback: "Edit collections")
/// Edit Collections
internal static let editCollections = L10n.tr("Localizable", "editCollections", fallback: "Edit Collections")
/// Edit media
internal static let editMedia = L10n.tr("Localizable", "editMedia", fallback: "Edit media")
/// Editor
@ -648,8 +672,14 @@ internal enum L10n {
internal static let genres = L10n.tr("Localizable", "genres", fallback: "Genres")
/// Categories that describe the themes or styles of media.
internal static let genresDescription = L10n.tr("Localizable", "genresDescription", fallback: "Categories that describe the themes or styles of media.")
/// Gesture lock
internal static let gestureLock = L10n.tr("Localizable", "gestureLock", fallback: "Gesture lock")
/// Gestures
internal static let gestures = L10n.tr("Localizable", "gestures", fallback: "Gestures")
/// Gestures locked
internal static let gesturesLocked = L10n.tr("Localizable", "gesturesLocked", fallback: "Gestures locked")
/// Gestures unlocked
internal static let gesturesUnlocked = L10n.tr("Localizable", "gesturesUnlocked", fallback: "Gestures unlocked")
/// Gbps
internal static let gigabitsPerSecond = L10n.tr("Localizable", "gigabitsPerSecond", fallback: "Gbps")
/// Green
@ -690,6 +720,12 @@ internal enum L10n {
internal static let images = L10n.tr("Localizable", "images", fallback: "Images")
/// Image source
internal static let imageSource = L10n.tr("Localizable", "imageSource", fallback: "Image source")
/// Incorrect pin for %@
internal static func incorrectPinForUser(_ p1: Any) -> String {
return L10n.tr("Localizable", "incorrectPinForUser", String(describing: p1), fallback: "Incorrect pin for %@")
}
/// Increase playback speed
internal static let increasePlaybackSpeed = L10n.tr("Localizable", "increasePlaybackSpeed", fallback: "Increase playback speed")
/// Index
internal static let index = L10n.tr("Localizable", "index", fallback: "Index")
/// Index number
@ -732,8 +768,12 @@ internal enum L10n {
internal static let kids = L10n.tr("Localizable", "kids", fallback: "Kids")
/// kbps
internal static let kilobitsPerSecond = L10n.tr("Localizable", "kilobitsPerSecond", fallback: "kbps")
/// Landscape
internal static let landscape = L10n.tr("Localizable", "landscape", fallback: "Landscape")
/// Language
internal static let language = L10n.tr("Localizable", "language", fallback: "Language")
/// Large
internal static let large = L10n.tr("Localizable", "large", fallback: "Large")
/// Larger
internal static let larger = L10n.tr("Localizable", "larger", fallback: "Larger")
/// Largest
@ -752,8 +792,8 @@ internal enum L10n {
}
/// Layout
internal static let layout = L10n.tr("Localizable", "layout", fallback: "Layout")
/// Learn more...
internal static let learnMoreEllipsis = L10n.tr("Localizable", "learnMoreEllipsis", fallback: "Learn more...")
/// Learn more
internal static let learnMore = L10n.tr("Localizable", "learnMore", fallback: "Learn more")
/// Left
internal static let `left` = L10n.tr("Localizable", "left", fallback: "Left")
/// Left vertical pan
@ -766,6 +806,8 @@ internal enum L10n {
internal static let letterPicker = L10n.tr("Localizable", "letterPicker", fallback: "Letter Picker")
/// Level
internal static let level = L10n.tr("Localizable", "level", fallback: "Level")
/// Libraries
internal static let libraries = L10n.tr("Localizable", "libraries", fallback: "Libraries")
/// Library
internal static let library = L10n.tr("Localizable", "library", fallback: "Library")
/// Light
@ -874,6 +916,8 @@ internal enum L10n {
internal static let mvc = L10n.tr("Localizable", "mvc", fallback: "MVC")
/// Name
internal static let name = L10n.tr("Localizable", "name", fallback: "Name")
/// Native
internal static let native = L10n.tr("Localizable", "native", fallback: "Native")
/// Native Player
internal static let nativePlayer = L10n.tr("Localizable", "nativePlayer", fallback: "Native Player")
/// Network timed out
@ -970,6 +1014,8 @@ internal enum L10n {
internal static let passwordChangeWarning = L10n.tr("Localizable", "passwordChangeWarning", fallback: "Changes the Jellyfin server user password. This does not change any Swiftfin settings.")
/// New passwords do not match.
internal static let passwordsDoNotMatch = L10n.tr("Localizable", "passwordsDoNotMatch", fallback: "New passwords do not match.")
/// Pause
internal static let pause = L10n.tr("Localizable", "pause", fallback: "Pause")
/// Pause on background
internal static let pauseOnBackground = L10n.tr("Localizable", "pauseOnBackground", fallback: "Pause on background")
/// Penciller
@ -1008,6 +1054,8 @@ internal enum L10n {
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")
/// Portrait
internal static let portrait = L10n.tr("Localizable", "portrait", fallback: "Portrait")
/// Posters
internal static let posters = L10n.tr("Localizable", "posters", fallback: "Posters")
/// Premiere Date
@ -1108,6 +1156,8 @@ internal enum L10n {
internal static let remux = L10n.tr("Localizable", "remux", fallback: "Remux")
/// Reorder
internal static let reorder = L10n.tr("Localizable", "reorder", fallback: "Reorder")
/// Replace
internal static let replace = L10n.tr("Localizable", "replace", fallback: "Replace")
/// Replace All
internal static let replaceAll = L10n.tr("Localizable", "replaceAll", fallback: "Replace All")
/// Replace all unlocked metadata and images with new information.
@ -1140,6 +1190,8 @@ internal enum L10n {
internal static let resetAllSettings = L10n.tr("Localizable", "resetAllSettings", fallback: "Reset all settings back to defaults.")
/// Reset the filter values to none.
internal static let resetFilterFooter = L10n.tr("Localizable", "resetFilterFooter", fallback: "Reset the filter values to none.")
/// Reset playback speed
internal static let resetPlaybackSpeed = L10n.tr("Localizable", "resetPlaybackSpeed", fallback: "Reset playback speed")
/// Reset Settings
internal static let resetSettings = L10n.tr("Localizable", "resetSettings", fallback: "Reset Settings")
/// Reset Swiftfin user settings
@ -1194,6 +1246,8 @@ internal enum L10n {
internal static let score = L10n.tr("Localizable", "score", fallback: "Score")
/// Screenshot
internal static let screenshot = L10n.tr("Localizable", "screenshot", fallback: "Screenshot")
/// Scrub
internal static let scrub = L10n.tr("Localizable", "scrub", fallback: "Scrub")
/// Scrub Current Time
internal static let scrubCurrentTime = L10n.tr("Localizable", "scrubCurrentTime", fallback: "Scrub Current Time")
/// Search
@ -1304,6 +1358,8 @@ internal enum L10n {
internal static let sliderColor = L10n.tr("Localizable", "sliderColor", fallback: "Slider Color")
/// Slider Type
internal static let sliderType = L10n.tr("Localizable", "sliderType", fallback: "Slider Type")
/// Slow scrub
internal static let slowScrub = L10n.tr("Localizable", "slowScrub", fallback: "Slow scrub")
/// Smaller
internal static let smaller = L10n.tr("Localizable", "smaller", fallback: "Smaller")
/// Smallest
@ -1322,6 +1378,8 @@ internal enum L10n {
internal static let splashscreen = L10n.tr("Localizable", "splashscreen", fallback: "Splashscreen")
/// When All Servers is selected, use the splashscreen from a single server or a random server
internal static let splashscreenFooter = L10n.tr("Localizable", "splashscreenFooter", fallback: "When All Servers is selected, use the splashscreen from a single server or a random server")
/// Split
internal static let split = L10n.tr("Localizable", "split", fallback: "Split")
/// Sports
internal static let sports = L10n.tr("Localizable", "sports", fallback: "Sports")
/// Start date
@ -1408,8 +1466,12 @@ internal enum L10n {
internal static let themeVideo = L10n.tr("Localizable", "themeVideo", fallback: "Theme Video")
/// Thumb
internal static let thumb = L10n.tr("Localizable", "thumb", fallback: "Thumb")
/// Thumb
internal static let thumbSlider = L10n.tr("Localizable", "thumbSlider", fallback: "Thumb")
/// Time
internal static let time = L10n.tr("Localizable", "time", fallback: "Time")
/// Time left
internal static let timeLeft = L10n.tr("Localizable", "timeLeft", fallback: "Time left")
/// Time Limit
internal static let timeLimit = L10n.tr("Localizable", "timeLimit", fallback: "Time Limit")
/// Time limit: %1$@
@ -1422,6 +1484,8 @@ internal enum L10n {
internal static let timestampType = L10n.tr("Localizable", "timestampType", fallback: "Timestamp Type")
/// Title
internal static let title = L10n.tr("Localizable", "title", fallback: "Title")
/// Total time
internal static let totalTime = L10n.tr("Localizable", "totalTime", fallback: "Total time")
/// Trailer
internal static let trailer = L10n.tr("Localizable", "trailer", fallback: "Trailer")
/// Trailers
@ -1456,6 +1520,8 @@ internal enum L10n {
internal static let unableToPerformDeviceAuth = L10n.tr("Localizable", "unableToPerformDeviceAuth", fallback: "Unable to perform device authentication")
/// Unable to perform device authentication. You may need to enable Face ID in the Settings app for Swiftfin.
internal static let unableToPerformDeviceAuthFaceID = L10n.tr("Localizable", "unableToPerformDeviceAuthFaceID", fallback: "Unable to perform device authentication. You may need to enable Face ID in the Settings app for Swiftfin.")
/// Unable to update custom name
internal static let unableToUpdateCustomName = L10n.tr("Localizable", "unableToUpdateCustomName", fallback: "Unable to update custom name")
/// Unaired
internal static let unaired = L10n.tr("Localizable", "unaired", fallback: "Unaired")
/// Unauthorized
@ -1546,6 +1612,8 @@ internal enum L10n {
internal static let videoTranscoding = L10n.tr("Localizable", "videoTranscoding", fallback: "Video transcoding")
/// Some views may need an app restart to update.
internal static let viewsMayRequireRestart = L10n.tr("Localizable", "viewsMayRequireRestart", fallback: "Some views may need an app restart to update.")
/// Volume
internal static let volume = L10n.tr("Localizable", "volume", fallback: "Volume")
/// Votes
internal static let votes = L10n.tr("Localizable", "votes", fallback: "Votes")
/// Weekday

View File

@ -68,7 +68,7 @@ final class DeviceDetailViewModel: ViewModel, Stateful, Eventful {
}
} catch {
await MainActor.run {
self.eventSubject.send(.error(.init("Unable to update custom name")))
self.eventSubject.send(.error(.init(L10n.unableToUpdateCustomName)))
}
}

View File

@ -77,8 +77,7 @@ final class SelectUserViewModel: ViewModel, Eventful, Stateful {
if user.accessPolicy == .requirePin, let storedPin = keychain.get("\(user.id)-pin") {
if pin != storedPin {
eventSubject.send(.error(.init("Incorrect pin for \(user.username)")))
eventSubject.send(.error(.init(L10n.incorrectPinForUser(user.username))))
return .content
}
}

View File

@ -61,7 +61,7 @@ final class UserLocalSecurityViewModel: ViewModel, Eventful {
if let storedPin = keychain.get("\(userSession.user.id)-pin") {
if oldPin != storedPin {
eventSubject.send(.error(.init("Incorrect pin for \(userSession.user.username)")))
eventSubject.send(.error(.init(L10n.incorrectPinForUser(userSession.user.username))))
throw JellyfinAPIError("invalid pin")
}
}

View File

@ -85,7 +85,7 @@ struct EditServerView: View {
router.popLast()
}
} message: {
Text("Are you sure you want to delete \(viewModel.server.name) and all of its connected users?")
Text(L10n.confirmDeleteServerAndUsers(viewModel.server.name))
}
}
}

View File

@ -26,7 +26,7 @@ struct LearnMoreButton: View {
// MARK: - Body
var body: some View {
Button(L10n.learnMoreEllipsis) {
Button(L10n.learnMore + "\u{2026}") {
isPresented = true
}
.foregroundStyle(Color.accentColor)

View File

@ -33,7 +33,7 @@ struct ListTitleSection: View {
}
if let onLearnMore {
Button("Learn More\u{2026}", action: onLearnMore)
Button(L10n.learnMore + "\u{2026}", action: onLearnMore)
}
}
.font(.subheadline)
@ -99,7 +99,7 @@ struct InsetGroupedListHeader<Content: View>: View {
}
if onLearnMore != nil {
Text("Learn More\u{2026}")
Text(L10n.learnMore + "\u{2026}")
.foregroundStyle(accentColor)
}
}

View File

@ -163,12 +163,12 @@ struct ChannelLibraryView: View {
Menu {
// We repurposed `LibraryDisplayType` but want different labels
Picker("Channel Display", selection: $channelDisplayType) {
Picker(L10n.channelDisplay, selection: $channelDisplayType) {
Label(L10n.compact, systemImage: LibraryDisplayType.grid.systemImage)
.tag(LibraryDisplayType.grid)
Label("Detailed", systemImage: LibraryDisplayType.list.systemImage)
Label(L10n.detailed, systemImage: LibraryDisplayType.list.systemImage)
.tag(LibraryDisplayType.list)
}
} label: {

View File

@ -72,7 +72,7 @@ struct EditServerView: View {
router.popLast()
}
} message: {
Text("Are you sure you want to delete \(viewModel.server.name) and all of its connected users?")
Text(L10n.confirmDeleteServerAndUsers(viewModel.server.name))
}
}
}

View File

@ -37,14 +37,14 @@ extension PagingLibraryView {
var body: some View {
Menu {
Section("Poster") {
Section(L10n.posters) {
Button {
posterType = .landscape
} label: {
if posterType == .landscape {
Label("Landscape", systemImage: "checkmark")
Label(L10n.landscape, systemImage: "checkmark")
} else {
Label("Landscape", systemImage: "rectangle")
Label(L10n.landscape, systemImage: "rectangle")
}
}
@ -52,9 +52,9 @@ extension PagingLibraryView {
posterType = .portrait
} label: {
if posterType == .portrait {
Label("Portrait", systemImage: "checkmark")
Label(L10n.portrait, systemImage: "checkmark")
} else {
Label("Portrait", systemImage: "rectangle.portrait")
Label(L10n.portrait, systemImage: "rectangle.portrait")
}
}
}
@ -82,7 +82,7 @@ extension PagingLibraryView {
}
if viewType == .list, UIDevice.isPad {
Stepper("Columns: \(listColumnCount)", value: $listColumnCount, in: 1 ... 3)
Stepper(L10n.columnsWithCount(listColumnCount), value: $listColumnCount, in: 1 ... 3)
}
} label: {
switch viewType {

View File

@ -140,7 +140,7 @@ struct CustomizeViewsSettings: View {
CaseIterablePicker(L10n.search, selection: $searchPosterType)
}
Section("Libraries") {
Section(L10n.libraries) {
CaseIterablePicker(L10n.library, selection: $libraryDisplayType)
CaseIterablePicker(L10n.posters, selection: $libraryPosterType)

View File

@ -49,7 +49,7 @@ extension UserSignInView {
VStack(alignment: .leading, spacing: 10) {
Text(
"Additional security for users signed in to this device. This does not change any Jellyfin server user settings."
L10n.additionalSecurityAccessDescription
)
// frame necessary with bug within BulletedList

View File

@ -188,9 +188,9 @@ struct LiveVideoPlayer: View {
}
.onChange(of: isGestureLocked) { newValue in
if newValue {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
} else {
updateViewProxy.present(systemName: "lock.open.fill", title: "Gestures Unlocked")
updateViewProxy.present(systemName: "lock.open.fill", title: L10n.gesturesUnlocked)
}
}
.onChange(of: isScrubbing) { newValue in
@ -305,7 +305,7 @@ extension LiveVideoPlayer {
private func handleTapGesture(unitPoint: UnitPoint, taps: Int) {
guard !isGestureLocked else {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
return
}
@ -330,7 +330,7 @@ extension LiveVideoPlayer {
private func handleDoubleTouchGesture(unitPoint: UnitPoint, taps: Int) {
guard !isGestureLocked else {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
return
}

View File

@ -55,10 +55,10 @@ struct VideoPlayerKeyCommandsModifier: ViewModifier {
) {
if videoPlayerManager.state == .playing {
videoPlayerManager.proxy.pause()
updateViewProxy.present(systemName: "pause.fill", title: "Pause")
updateViewProxy.present(systemName: "pause.fill", title: L10n.pause)
} else {
videoPlayerManager.proxy.play()
updateViewProxy.present(systemName: "play.fill", title: "Play")
updateViewProxy.present(systemName: "play.fill", title: L10n.play)
}
}
@ -139,7 +139,7 @@ struct VideoPlayerKeyCommandsModifier: ViewModifier {
// MARK: aspect fill
KeyCommandAction(
title: "Aspect Fill",
title: L10n.aspectFill,
input: "f",
modifierFlags: .command
) {
@ -151,7 +151,7 @@ struct VideoPlayerKeyCommandsModifier: ViewModifier {
// MARK: decrease playback speed
KeyCommandAction(
title: "Decrease Playback Speed",
title: L10n.decreasePlaybackSpeed,
input: "[",
modifierFlags: .command
) {
@ -171,7 +171,7 @@ struct VideoPlayerKeyCommandsModifier: ViewModifier {
// MARK: increase playback speed
KeyCommandAction(
title: "Increase Playback Speed",
title: L10n.increasePlaybackSpeed,
input: "]",
modifierFlags: .command
) {
@ -191,7 +191,7 @@ struct VideoPlayerKeyCommandsModifier: ViewModifier {
// MARK: reset playback speed
KeyCommandAction(
title: "Reset Playback Speed",
title: L10n.resetPlaybackSpeed,
input: "\\",
modifierFlags: .command
) {

View File

@ -225,9 +225,9 @@ struct VideoPlayer: View {
}
.onChange(of: isGestureLocked) { newValue in
if newValue {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
} else {
updateViewProxy.present(systemName: "lock.open.fill", title: "Gestures Unlocked")
updateViewProxy.present(systemName: "lock.open.fill", title: L10n.gesturesUnlocked)
}
}
.onChange(of: isScrubbing) { newValue in
@ -352,7 +352,7 @@ extension VideoPlayer {
private func handleTapGesture(unitPoint: UnitPoint, taps: Int) {
guard !isGestureLocked else {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
return
}
@ -382,7 +382,7 @@ extension VideoPlayer {
}
guard !isGestureLocked else {
updateViewProxy.present(systemName: "lock.fill", title: "Gestures Locked")
updateViewProxy.present(systemName: "lock.fill", title: L10n.gesturesLocked)
return
}