[iOS & tvOS] Localize Existing Strings (#1361)

This commit is contained in:
Joe Kribs 2024-12-13 12:40:37 -07:00 committed by GitHub
parent d001a96d6c
commit b0583125f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 99 additions and 99 deletions

View File

@ -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
} }
} }

View File

@ -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 {

View File

@ -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"
} }

View File

@ -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
} }
} }
} }

View File

@ -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
} }
} }
} }

View File

@ -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
} }
} }
} }

View File

@ -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
} }
} }
} }

View File

@ -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"
} }

View File

@ -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
} }
} }
} }

View File

@ -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
} }
} }
} }

View File

@ -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
} }
} }

View File

@ -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
} }

View File

@ -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()
// } // }

View File

@ -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
) )

View File

@ -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()
} }

View File

@ -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")

View File

@ -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()
// } // }
// } // }

View File

@ -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
) )
} }

View File

@ -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()
} }
} }

View File

@ -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)
} }
} }

View File

@ -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

View File

@ -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 {

View File

@ -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
} }
} }
} }

View File

@ -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 {

View File

@ -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)

View File

@ -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)
} }

View File

@ -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)

View File

@ -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()
} }

View File

@ -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")
} }
} }
} }

View File

@ -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()
} }

View File

@ -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)

View File

@ -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")

View File

@ -126,7 +126,7 @@ extension SelectUserView {
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.contextMenu { .contextMenu {
Button("Delete", role: .destructive) { Button(L10n.delete, role: .destructive) {
onDelete() onDelete()
} }
} }

View File

@ -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()
} }
} }

View File

@ -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
) )
} }

View File

@ -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()
} }
} }

View File

@ -57,6 +57,6 @@ struct GestureSettingsView: View {
CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight) CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight)
} }
} }
.navigationTitle("Gestures") .navigationTitle(L10n.gestures)
} }
} }

View File

@ -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)
} }
} }

View File

@ -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()
} }
} }

View File

@ -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)
} }
} }
} }

View File

@ -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()