[iOS & tvOS] Localize Existing Strings (#1361)
This commit is contained in:
parent
d001a96d6c
commit
b0583125f7
|
@ -73,7 +73,7 @@ enum DeviceType: String, Displayable, Codable, CaseIterable {
|
||||||
case .xbox:
|
case .xbox:
|
||||||
return "Xbox"
|
return "Xbox"
|
||||||
case .other:
|
case .other:
|
||||||
return "Other"
|
return L10n.other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ extension MediaStream {
|
||||||
var properties: [TextPair] = []
|
var properties: [TextPair] = []
|
||||||
|
|
||||||
if let value = type {
|
if let value = type {
|
||||||
properties.append(.init(title: "Type", subtitle: value.rawValue))
|
properties.append(.init(title: L10n.type, subtitle: value.rawValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = codec {
|
if let value = codec {
|
||||||
|
@ -63,7 +63,7 @@ extension MediaStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = language {
|
if let value = language {
|
||||||
properties.append(.init(title: "Language", subtitle: value))
|
properties.append(.init(title: L10n.language, subtitle: value))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = timeBase {
|
if let value = timeBase {
|
||||||
|
@ -107,7 +107,7 @@ extension MediaStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = channels {
|
if let value = channels {
|
||||||
properties.append(.init(title: "Channels", subtitle: value.description))
|
properties.append(.init(title: L10n.channels, subtitle: value.description))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = sampleRate {
|
if let value = sampleRate {
|
||||||
|
@ -115,7 +115,7 @@ extension MediaStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = isDefault {
|
if let value = isDefault {
|
||||||
properties.append(.init(title: "Default", subtitle: value.description))
|
properties.append(.init(title: L10n.default, subtitle: value.description))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = isForced {
|
if let value = isForced {
|
||||||
|
@ -195,7 +195,7 @@ extension MediaStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = deliveryURL {
|
if let value = deliveryURL {
|
||||||
properties.append(.init(title: "URL", subtitle: value))
|
properties.append(.init(title: L10n.url, subtitle: value))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = deliveryURL {
|
if let value = deliveryURL {
|
||||||
|
|
|
@ -17,7 +17,7 @@ enum CustomDeviceProfileAction: String, CaseIterable, Displayable, Storable {
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .add:
|
case .add:
|
||||||
return "Add"
|
return L10n.add
|
||||||
case .replace:
|
case .replace:
|
||||||
return "Replace"
|
return "Replace"
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ enum MultiTapAction: String, GestureAction {
|
||||||
case .none:
|
case .none:
|
||||||
return L10n.none
|
return L10n.none
|
||||||
case .jump:
|
case .jump:
|
||||||
return "Jump"
|
return L10n.jump
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ enum DoubleTouchAction: String, GestureAction {
|
||||||
case .none:
|
case .none:
|
||||||
return L10n.none
|
return L10n.none
|
||||||
case .aspectFill:
|
case .aspectFill:
|
||||||
return "Aspect Fill"
|
return L10n.aspectFill
|
||||||
case .gestureLock:
|
case .gestureLock:
|
||||||
return "Gesture Lock"
|
return "Gesture Lock"
|
||||||
case .pausePlay:
|
case .pausePlay:
|
||||||
return "Pause/Play"
|
return L10n.playAndPause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,17 +83,17 @@ enum PanAction: String, GestureAction {
|
||||||
case .none:
|
case .none:
|
||||||
return L10n.none
|
return L10n.none
|
||||||
case .audioffset:
|
case .audioffset:
|
||||||
return "Audio Offset"
|
return L10n.audioOffset
|
||||||
case .brightness:
|
case .brightness:
|
||||||
return "Brightness"
|
return "Brightness"
|
||||||
case .playbackSpeed:
|
case .playbackSpeed:
|
||||||
return "Playback Speed"
|
return L10n.playbackSpeed
|
||||||
case .scrub:
|
case .scrub:
|
||||||
return "Scrub"
|
return "Scrub"
|
||||||
case .slowScrub:
|
case .slowScrub:
|
||||||
return "Slow Scrub"
|
return "Slow Scrub"
|
||||||
case .subtitleOffset:
|
case .subtitleOffset:
|
||||||
return "Subtitle Offset"
|
return L10n.subtitleOffset
|
||||||
case .volume:
|
case .volume:
|
||||||
return "Volume"
|
return "Volume"
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ enum PinchAction: String, GestureAction {
|
||||||
case .none:
|
case .none:
|
||||||
return L10n.none
|
return L10n.none
|
||||||
case .aspectFill:
|
case .aspectFill:
|
||||||
return "Aspect Fill"
|
return L10n.aspectFill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ enum SwipeAction: String, GestureAction {
|
||||||
case .none:
|
case .none:
|
||||||
return L10n.none
|
return L10n.none
|
||||||
case .jump:
|
case .jump:
|
||||||
return "Jump"
|
return L10n.jump
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ extension ItemFilterType: Displayable {
|
||||||
case .genres:
|
case .genres:
|
||||||
L10n.genres
|
L10n.genres
|
||||||
case .letter:
|
case .letter:
|
||||||
"Letter"
|
L10n.letter
|
||||||
case .sortBy:
|
case .sortBy:
|
||||||
L10n.sort
|
L10n.sort
|
||||||
case .sortOrder:
|
case .sortOrder:
|
||||||
|
@ -65,7 +65,7 @@ extension ItemFilterType: Displayable {
|
||||||
case .traits:
|
case .traits:
|
||||||
L10n.filters
|
L10n.filters
|
||||||
case .years:
|
case .years:
|
||||||
"Years"
|
L10n.years
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ enum ItemSortBy: String, CaseIterable, Displayable, Codable {
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .premiereDate:
|
case .premiereDate:
|
||||||
return "Premiere date"
|
return L10n.premiereDate
|
||||||
case .name:
|
case .name:
|
||||||
return "Name"
|
return L10n.name
|
||||||
case .dateAdded:
|
case .dateAdded:
|
||||||
return "Date added"
|
return L10n.dateAdded
|
||||||
case .random:
|
case .random:
|
||||||
return "Random"
|
return L10n.random
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ enum PlaybackButtonType: String, CaseIterable, Displayable, Defaults.Serializabl
|
||||||
case .large:
|
case .large:
|
||||||
return "Large"
|
return "Large"
|
||||||
case .compact:
|
case .compact:
|
||||||
return "Compact"
|
return L10n.compact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ enum StreamType: String, Displayable {
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .direct:
|
case .direct:
|
||||||
return "Direct"
|
return L10n.direct
|
||||||
case .transcode:
|
case .transcode:
|
||||||
return "Transcode"
|
return L10n.transcode
|
||||||
case .hls:
|
case .hls:
|
||||||
return "HLS"
|
return "HLS"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ enum TimestampType: String, CaseIterable, Defaults.Serializable, Displayable {
|
||||||
case .split:
|
case .split:
|
||||||
return "Split"
|
return "Split"
|
||||||
case .compact:
|
case .compact:
|
||||||
return "Compact"
|
return L10n.compact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@ enum UserAccessPolicy: String, CaseIterable, Codable, Displayable {
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .none:
|
case .none:
|
||||||
"None"
|
L10n.none
|
||||||
case .requireDeviceAuthentication:
|
case .requireDeviceAuthentication:
|
||||||
"Device Authentication"
|
"Device Authentication"
|
||||||
case .requirePin:
|
case .requirePin:
|
||||||
"Pin"
|
L10n.pin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,23 +25,23 @@ enum VideoPlayerActionButton: String, CaseIterable, Defaults.Serializable, Displ
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
// case .advanced:
|
// case .advanced:
|
||||||
// return "Advanced"
|
// return L10n.advanced
|
||||||
case .aspectFill:
|
case .aspectFill:
|
||||||
return "Aspect Fill"
|
return L10n.aspectFill
|
||||||
case .audio:
|
case .audio:
|
||||||
return "Audio"
|
return L10n.audio
|
||||||
case .autoPlay:
|
case .autoPlay:
|
||||||
return "Auto Play"
|
return L10n.autoPlay
|
||||||
case .chapters:
|
case .chapters:
|
||||||
return "Chapters"
|
return L10n.chapters
|
||||||
case .playbackSpeed:
|
case .playbackSpeed:
|
||||||
return "Playback Speed"
|
return L10n.playbackSpeed
|
||||||
case .playNextItem:
|
case .playNextItem:
|
||||||
return "Play Next Item"
|
return L10n.playNextItem
|
||||||
case .playPreviousItem:
|
case .playPreviousItem:
|
||||||
return "Play Previous Item"
|
return L10n.playPreviousItem
|
||||||
case .subtitles:
|
case .subtitles:
|
||||||
return "Subtitles"
|
return L10n.subtitles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,13 +64,13 @@ struct OrderedSectionSelectorView<Element: Displayable & Hashable>: View {
|
||||||
Text(L10n.enabled)
|
Text(L10n.enabled)
|
||||||
Spacer()
|
Spacer()
|
||||||
if editMode?.wrappedValue.isEditing ?? false {
|
if editMode?.wrappedValue.isEditing ?? false {
|
||||||
Button("Done") {
|
Button(L10n.done) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
editMode?.wrappedValue = .inactive
|
editMode?.wrappedValue = .inactive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Button("Edit") {
|
Button(L10n.edit) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
editMode?.wrappedValue = .active
|
editMode?.wrappedValue = .active
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct AppSettingsView: View {
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// ChevronButton("Logs")
|
// ChevronButton(L10n.logs)
|
||||||
// .onSelect {
|
// .onSelect {
|
||||||
// router.route(to: \.log)
|
// router.route(to: \.log)
|
||||||
// }
|
// }
|
||||||
|
@ -68,7 +68,7 @@ struct AppSettingsView: View {
|
||||||
// Button {
|
// Button {
|
||||||
// removeAllServersSelected = true
|
// removeAllServersSelected = true
|
||||||
// } label: {
|
// } label: {
|
||||||
// Text("Remove All Servers")
|
// Text(L10n.removeAllServers)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -79,9 +79,9 @@ struct AppSettingsView: View {
|
||||||
//// viewModel.resetUserSettings()
|
//// viewModel.resetUserSettings()
|
||||||
// }
|
// }
|
||||||
// } message: {
|
// } 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) {
|
// Button(L10n.reset, role: .destructive) {
|
||||||
//// viewModel.removeAllServers()
|
//// viewModel.removeAllServers()
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -20,7 +20,7 @@ extension ItemView {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
PosterHStack(
|
PosterHStack(
|
||||||
title: "Special Features",
|
title: L10n.specialFeatures,
|
||||||
type: .landscape,
|
type: .landscape,
|
||||||
items: items
|
items: items
|
||||||
)
|
)
|
||||||
|
|
|
@ -62,13 +62,13 @@ extension SelectUserView {
|
||||||
.buttonBorderShape(.circleBackport)
|
.buttonBorderShape(.circleBackport)
|
||||||
.disabled(!isEnabled)
|
.disabled(!isEnabled)
|
||||||
|
|
||||||
Text("Add User")
|
Text(L10n.addUser)
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundStyle(isEnabled ? .primary : .secondary)
|
.foregroundStyle(isEnabled ? .primary : .secondary)
|
||||||
|
|
||||||
if serverSelection == .all {
|
if serverSelection == .all {
|
||||||
Text("Hidden")
|
Text(L10n.hidden)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.hidden()
|
.hidden()
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ extension SelectUserView {
|
||||||
Group {
|
Group {
|
||||||
switch serverSelection {
|
switch serverSelection {
|
||||||
case .all:
|
case .all:
|
||||||
Label("All Servers", systemImage: "person.2.fill")
|
Label(L10n.allServers, systemImage: "person.2.fill")
|
||||||
case let .server(id):
|
case let .server(id):
|
||||||
if let server = viewModel.servers.keys.first(where: { $0.id == id }) {
|
if let server = viewModel.servers.keys.first(where: { $0.id == id }) {
|
||||||
Label(server.name, systemImage: "server.rack")
|
Label(server.name, systemImage: "server.rack")
|
||||||
|
|
|
@ -87,7 +87,7 @@ extension SelectUserView {
|
||||||
.buttonStyle(.card)
|
.buttonStyle(.card)
|
||||||
.buttonBorderShape(.circleBackport)
|
.buttonBorderShape(.circleBackport)
|
||||||
// .contextMenu {
|
// .contextMenu {
|
||||||
// Button("Delete", role: .destructive) {
|
// Button(L10n.delete, role: .destructive) {
|
||||||
// onDelete()
|
// onDelete()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -48,7 +48,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
|
|
||||||
profileDetailsView(
|
profileDetailsView(
|
||||||
title: L10n.useAsTranscodingProfile,
|
title: L10n.useAsTranscodingProfile,
|
||||||
detail: profile.useAsTranscodingProfile ? "Yes" : "No"
|
detail: profile.useAsTranscodingProfile ? L10n.yes : L10n.no
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
HStack {
|
HStack {
|
||||||
Text(L10n.customProfile)
|
Text(L10n.customProfile)
|
||||||
Spacer()
|
Spacer()
|
||||||
Button("Save") {
|
Button(L10n.save) {
|
||||||
if createProfile {
|
if createProfile {
|
||||||
customDeviceProfiles.append(profile.value)
|
customDeviceProfiles.append(profile.value)
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
}
|
}
|
||||||
.navigationTitle(L10n.customProfile)
|
.navigationTitle(L10n.customProfile)
|
||||||
.alert("Profile not saved", isPresented: $isPresentingNotSaved) {
|
.alert("Profile not saved", isPresented: $isPresentingNotSaved) {
|
||||||
Button("Close", role: .destructive) {
|
Button(L10n.close, role: .destructive) {
|
||||||
router.dismissCoordinator()
|
router.dismissCoordinator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ struct CustomDeviceProfileSettingsView: View {
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
deleteProfile(profile)
|
deleteProfile(profile)
|
||||||
} label: {
|
} label: {
|
||||||
Label("Delete", systemImage: "trash")
|
Label(L10n.delete, systemImage: "trash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ struct CustomDeviceProfileSettingsView: View {
|
||||||
Text(L10n.profiles)
|
Text(L10n.profiles)
|
||||||
Spacer()
|
Spacer()
|
||||||
if customProfiles.isNotEmpty {
|
if customProfiles.isNotEmpty {
|
||||||
Button("Add") {
|
Button(L10n.add) {
|
||||||
router.route(to: \.createCustomDeviceProfile)
|
router.route(to: \.createCustomDeviceProfile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct ListColumnsPickerView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
StepperView(
|
StepperView(
|
||||||
title: "Columns",
|
title: L10n.columns,
|
||||||
value: $selection,
|
value: $selection,
|
||||||
range: 1 ... 3,
|
range: 1 ... 3,
|
||||||
step: 1
|
step: 1
|
||||||
|
|
|
@ -22,7 +22,7 @@ extension VideoPlayer {
|
||||||
|
|
||||||
VStack(spacing: 10) {
|
VStack(spacing: 10) {
|
||||||
|
|
||||||
Text("Retrieving media information")
|
Text(L10n.retrievingMediaInformation)
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
|
|
||||||
ProgressView()
|
ProgressView()
|
||||||
|
@ -30,7 +30,7 @@ extension VideoPlayer {
|
||||||
Button {
|
Button {
|
||||||
router.dismissCoordinator()
|
router.dismissCoordinator()
|
||||||
} label: {
|
} label: {
|
||||||
Text("Cancel")
|
Text(L10n.cancel)
|
||||||
.foregroundColor(.red)
|
.foregroundColor(.red)
|
||||||
.padding()
|
.padding()
|
||||||
.overlay {
|
.overlay {
|
||||||
|
|
|
@ -20,11 +20,11 @@ extension VideoPlayer {
|
||||||
var displayTitle: String {
|
var displayTitle: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .audio:
|
case .audio:
|
||||||
return "Audio"
|
return L10n.audio
|
||||||
case .playbackSpeed:
|
case .playbackSpeed:
|
||||||
return "Playback Speed"
|
return L10n.playbackSpeed
|
||||||
case .subtitles:
|
case .subtitles:
|
||||||
return "Subtitles"
|
return L10n.subtitles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ struct VideoPlayer: View {
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var loadingView: some View {
|
private var loadingView: some View {
|
||||||
Text("Retrieving media information")
|
Text(L10n.retrievingMediaInformation)
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct AppLoadingView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.topBarTrailing {
|
.topBarTrailing {
|
||||||
Button("Advanced", systemImage: "gearshape.fill") {}
|
Button(L10n.advanced, systemImage: "gearshape.fill") {}
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
.opacity(didFailMigration ? 0 : 1)
|
.opacity(didFailMigration ? 0 : 1)
|
||||||
|
|
|
@ -62,10 +62,10 @@ struct AppSettingsView: View {
|
||||||
Toggle("Use splashscreen", isOn: $selectUserUseSplashscreen)
|
Toggle("Use splashscreen", isOn: $selectUserUseSplashscreen)
|
||||||
|
|
||||||
if selectUserUseSplashscreen {
|
if selectUserUseSplashscreen {
|
||||||
Picker("Servers", selection: $selectUserAllServersSplashscreen) {
|
Picker(L10n.servers, selection: $selectUserAllServersSplashscreen) {
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Label("Random", systemImage: "dice.fill")
|
Label(L10n.random, systemImage: "dice.fill")
|
||||||
.tag(SelectUserServerSelection.all)
|
.tag(SelectUserServerSelection.all)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ struct ChannelLibraryView: View {
|
||||||
// We repurposed `LibraryDisplayType` but want different labels
|
// We repurposed `LibraryDisplayType` but want different labels
|
||||||
Picker("Channel Display", selection: $channelDisplayType) {
|
Picker("Channel Display", selection: $channelDisplayType) {
|
||||||
|
|
||||||
Label("Compact", systemImage: LibraryDisplayType.grid.systemImage)
|
Label(L10n.compact, systemImage: LibraryDisplayType.grid.systemImage)
|
||||||
.tag(LibraryDisplayType.grid)
|
.tag(LibraryDisplayType.grid)
|
||||||
|
|
||||||
Label("Detailed", systemImage: LibraryDisplayType.list.systemImage)
|
Label("Detailed", systemImage: LibraryDisplayType.list.systemImage)
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct EditServerView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
if isEditing {
|
if isEditing {
|
||||||
ListRowButton("Delete") {
|
ListRowButton(L10n.delete) {
|
||||||
isPresentingConfirmDeletion = true
|
isPresentingConfirmDeletion = true
|
||||||
}
|
}
|
||||||
.foregroundStyle(.red, .red.opacity(0.2))
|
.foregroundStyle(.red, .red.opacity(0.2))
|
||||||
|
@ -66,8 +66,8 @@ struct EditServerView: View {
|
||||||
.onChange(of: currentServerURL) { newValue in
|
.onChange(of: currentServerURL) { newValue in
|
||||||
viewModel.setCurrentURL(to: newValue)
|
viewModel.setCurrentURL(to: newValue)
|
||||||
}
|
}
|
||||||
.alert("Delete Server", isPresented: $isPresentingConfirmDeletion) {
|
.alert(L10n.deleteServer, isPresented: $isPresentingConfirmDeletion) {
|
||||||
Button("Delete", role: .destructive) {
|
Button(L10n.delete, role: .destructive) {
|
||||||
viewModel.delete()
|
viewModel.delete()
|
||||||
router.popLast()
|
router.popLast()
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ extension PagingLibraryView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section("Layout") {
|
Section(L10n.layout) {
|
||||||
Button {
|
Button {
|
||||||
viewType = .grid
|
viewType = .grid
|
||||||
} label: {
|
} label: {
|
||||||
|
@ -87,9 +87,9 @@ extension PagingLibraryView {
|
||||||
} label: {
|
} label: {
|
||||||
switch viewType {
|
switch viewType {
|
||||||
case .grid:
|
case .grid:
|
||||||
Label("Layout", systemImage: "square.grid.2x2.fill")
|
Label(L10n.layout, systemImage: "square.grid.2x2.fill")
|
||||||
case .list:
|
case .list:
|
||||||
Label("Layout", systemImage: "square.fill.text.grid.1x2")
|
Label(L10n.layout, systemImage: "square.fill.text.grid.1x2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,13 +63,13 @@ extension SelectUserView {
|
||||||
.clipShape(.circle)
|
.clipShape(.circle)
|
||||||
.aspectRatio(1, contentMode: .fill)
|
.aspectRatio(1, contentMode: .fill)
|
||||||
|
|
||||||
Text("Add User")
|
Text(L10n.addUser)
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundStyle(isEnabled ? .primary : .secondary)
|
.foregroundStyle(isEnabled ? .primary : .secondary)
|
||||||
|
|
||||||
if serverSelection == .all {
|
if serverSelection == .all {
|
||||||
Text("Hidden")
|
Text(L10n.hidden)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.hidden()
|
.hidden()
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ extension SelectUserView {
|
||||||
private var rowContent: some View {
|
private var rowContent: some View {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
||||||
Text("Add User")
|
Text(L10n.addUser)
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundStyle(isEnabled ? .primary : .secondary)
|
.foregroundStyle(isEnabled ? .primary : .secondary)
|
||||||
|
|
|
@ -45,21 +45,21 @@ extension SelectUserView {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Menu {
|
Menu {
|
||||||
Section {
|
Section {
|
||||||
Button("Add Server", systemImage: "plus") {
|
Button(L10n.addServer, systemImage: "plus") {
|
||||||
router.route(to: \.connectToServer)
|
router.route(to: \.connectToServer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let selectedServer {
|
if let selectedServer {
|
||||||
Button("Edit Server", systemImage: "server.rack") {
|
Button(L10n.editServer, systemImage: "server.rack") {
|
||||||
router.route(to: \.editServer, selectedServer)
|
router.route(to: \.editServer, selectedServer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Picker("Servers", selection: _serverSelection) {
|
Picker(L10n.servers, selection: _serverSelection) {
|
||||||
|
|
||||||
if viewModel.servers.keys.count > 1 {
|
if viewModel.servers.keys.count > 1 {
|
||||||
Label("All Servers", systemImage: "person.2.fill")
|
Label(L10n.allServers, systemImage: "person.2.fill")
|
||||||
.tag(SelectUserServerSelection.all)
|
.tag(SelectUserServerSelection.all)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ extension SelectUserView {
|
||||||
HStack {
|
HStack {
|
||||||
switch serverSelection {
|
switch serverSelection {
|
||||||
case .all:
|
case .all:
|
||||||
Label("All Servers", systemImage: "person.2.fill")
|
Label(L10n.allServers, systemImage: "person.2.fill")
|
||||||
case let .server(id):
|
case let .server(id):
|
||||||
if let server = viewModel.servers.keys.first(where: { $0.id == id }) {
|
if let server = viewModel.servers.keys.first(where: { $0.id == id }) {
|
||||||
Label(server.name, systemImage: "server.rack")
|
Label(server.name, systemImage: "server.rack")
|
||||||
|
|
|
@ -126,7 +126,7 @@ extension SelectUserView {
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button("Delete", role: .destructive) {
|
Button(L10n.delete, role: .destructive) {
|
||||||
onDelete()
|
onDelete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ extension SelectUserView {
|
||||||
}
|
}
|
||||||
.onSelect(perform: action)
|
.onSelect(perform: action)
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button("Delete", role: .destructive) {
|
Button(L10n.delete, role: .destructive) {
|
||||||
onDelete()
|
onDelete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
|
|
||||||
profileDetailsView(
|
profileDetailsView(
|
||||||
title: L10n.useAsTranscodingProfile,
|
title: L10n.useAsTranscodingProfile,
|
||||||
detail: profile.useAsTranscodingProfile ? "Yes" : "No"
|
detail: profile.useAsTranscodingProfile ? L10n.yes : L10n.no
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
}
|
}
|
||||||
.navigationTitle(L10n.customProfile)
|
.navigationTitle(L10n.customProfile)
|
||||||
.topBarTrailing {
|
.topBarTrailing {
|
||||||
Button("Save") {
|
Button(L10n.save) {
|
||||||
if createProfile {
|
if createProfile {
|
||||||
customDeviceProfiles.append(profile)
|
customDeviceProfiles.append(profile)
|
||||||
} else {
|
} else {
|
||||||
|
@ -137,7 +137,7 @@ extension CustomDeviceProfileSettingsView {
|
||||||
.disabled(!isValid)
|
.disabled(!isValid)
|
||||||
}
|
}
|
||||||
.alert("Profile not saved", isPresented: $isPresentingNotSaved) {
|
.alert("Profile not saved", isPresented: $isPresentingNotSaved) {
|
||||||
Button("Close", role: .destructive) {
|
Button(L10n.close, role: .destructive) {
|
||||||
router.dismissCoordinator()
|
router.dismissCoordinator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,6 @@ struct GestureSettingsView: View {
|
||||||
CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight)
|
CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Gestures")
|
.navigationTitle(L10n.gestures)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct NativeVideoPlayerSettingsView: View {
|
||||||
Section {
|
Section {
|
||||||
|
|
||||||
BasicStepper(
|
BasicStepper(
|
||||||
title: "Resume Offset",
|
title: L10n.resumeOffset,
|
||||||
value: $resumeOffset,
|
value: $resumeOffset,
|
||||||
range: 0 ... 30,
|
range: 0 ... 30,
|
||||||
step: 1
|
step: 1
|
||||||
|
@ -29,9 +29,9 @@ struct NativeVideoPlayerSettingsView: View {
|
||||||
$0.secondLabel
|
$0.secondLabel
|
||||||
}
|
}
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("Resume content seconds before the recorded resume time")
|
Text(L10n.resumeOffsetDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Native Player")
|
.navigationTitle(L10n.nativePlayer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,14 +89,14 @@ struct UserProfileSettingsView: View {
|
||||||
router.route(to: \.quickConnect)
|
router.route(to: \.quickConnect)
|
||||||
}
|
}
|
||||||
|
|
||||||
ChevronButton("Password")
|
ChevronButton(L10n.password)
|
||||||
.onSelect {
|
.onSelect {
|
||||||
router.route(to: \.resetUserPassword, viewModel.userSession.user.id)
|
router.route(to: \.resetUserPassword, viewModel.userSession.user.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
ChevronButton("Security")
|
ChevronButton(L10n.security)
|
||||||
.onSelect {
|
.onSelect {
|
||||||
router.route(to: \.localSecurity)
|
router.route(to: \.localSecurity)
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ struct UserProfileSettingsView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert("Reset Settings", isPresented: $isPresentingConfirmReset) {
|
.alert("Reset Settings", isPresented: $isPresentingConfirmReset) {
|
||||||
Button("Reset", role: .destructive) {
|
Button(L10n.reset, role: .destructive) {
|
||||||
do {
|
do {
|
||||||
try viewModel.userSession.user.deleteSettings()
|
try viewModel.userSession.user.deleteSettings()
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -134,7 +134,7 @@ struct UserProfileSettingsView: View {
|
||||||
router.route(to: \.photoPicker, viewModel)
|
router.route(to: \.photoPicker, viewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button("Delete", role: .destructive) {
|
Button(L10n.delete, role: .destructive) {
|
||||||
viewModel.deleteCurrentUserProfileImage()
|
viewModel.deleteCurrentUserProfileImage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ extension VideoPlayerSettingsView {
|
||||||
Text(L10n.subtitle)
|
Text(L10n.subtitle)
|
||||||
} footer: {
|
} footer: {
|
||||||
// TODO: better wording
|
// TODO: better wording
|
||||||
Text("Settings only affect some subtitle types")
|
Text(L10n.subtitlesDisclaimer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ extension UserSignInView {
|
||||||
List {
|
List {
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
CaseIterablePicker("Security", selection: $updateSignInPolicy)
|
CaseIterablePicker(L10n.security, selection: $updateSignInPolicy)
|
||||||
} footer: {
|
} footer: {
|
||||||
// TODO: descriptions of each section
|
// TODO: descriptions of each section
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ extension UserSignInView {
|
||||||
Text(UserAccessPolicy.requireDeviceAuthentication.displayTitle)
|
Text(UserAccessPolicy.requireDeviceAuthentication.displayTitle)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
|
|
||||||
Text("Require device authentication when signing in to the user.")
|
Text(L10n.requireDeviceAuthDescription)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 15)
|
.padding(.bottom, 15)
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ extension UserSignInView {
|
||||||
Text(UserAccessPolicy.requirePin.displayTitle)
|
Text(UserAccessPolicy.requirePin.displayTitle)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
|
|
||||||
Text("Require a local pin when signing in to the user. This pin is unrecoverable.")
|
Text(L10n.requirePinDescription)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 15)
|
.padding(.bottom, 15)
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ extension UserSignInView {
|
||||||
Text(UserAccessPolicy.none.displayTitle)
|
Text(UserAccessPolicy.none.displayTitle)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
|
|
||||||
Text("Save the user to this device without any local authentication.")
|
Text(L10n.saveUserWithoutAuthDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: max(10, listSize.width - 50))
|
.frame(width: max(10, listSize.width - 50))
|
||||||
|
@ -84,16 +84,16 @@ extension UserSignInView {
|
||||||
|
|
||||||
if accessPolicy == .requirePin {
|
if accessPolicy == .requirePin {
|
||||||
Section {
|
Section {
|
||||||
TextField("Hint", text: $updatePinHint)
|
TextField(L10n.hint, text: $updatePinHint)
|
||||||
} header: {
|
} header: {
|
||||||
Text("Hint")
|
Text(L10n.hint)
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("Set a hint when prompting for the pin.")
|
Text(L10n.setPinHintDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.animation(.linear, value: accessPolicy)
|
.animation(.linear, value: accessPolicy)
|
||||||
.navigationTitle("Security")
|
.navigationTitle(L10n.security)
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.navigationBarCloseButton {
|
.navigationBarCloseButton {
|
||||||
router.popLast()
|
router.popLast()
|
||||||
|
|
Loading…
Reference in New Issue