From 638117f923725e8b45adcf3bd5cf5b2052e09202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pantale=C3=A3o=20Gon=C3=A7alves?= <5808343+bgoncal@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:46:50 +0100 Subject: [PATCH] Fix SwiftUI Text verbatim usage and missing localization (#3450) ## Summary ## Screenshots ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes --- HomeAssistant.xcodeproj/project.pbxproj | 4 --- Sources/App/Assist/AssistView.swift | 4 +-- .../Assist/Views/AssistMicAnimationView.swift | 2 +- Sources/App/Improv/ImprovDiscoverView.swift | 4 +-- .../App/Improv/Views/ImprovFailureView.swift | 2 +- .../App/Improv/Views/ImprovSuccessView.swift | 4 +-- .../Screens/OnboardingErrorView.swift | 2 +- .../Screens/OnboardingWelcomeView.swift | 6 ++-- .../Screens/PermissionRequestView.swift | 6 ++-- .../Resources/en.lproj/Localizable.strings | 4 +++ .../AppIcon/AppIconSelectorView.swift | 2 +- .../WatchConfigurationView.swift | 10 +++---- .../CarPlay/CarPlayConfigurationView.swift | 12 ++++---- .../ClientEventsLogView.swift | 4 +-- Sources/App/Settings/DebugView.swift | 20 ++++++------- .../MagicItem/Add/MagicItemAddView.swift | 10 +++---- .../MagicItem/AssistPipelinePicker.swift | 2 +- .../Edit/MagicItemCustomizationView.swift | 16 +++++----- .../App/Settings/MagicItem/EntityPicker.swift | 2 +- .../Widgets/Builder/WidgetAddItemView.swift | 11 ------- .../Widgets/Builder/WidgetBuilderView.swift | 8 ++--- .../Widgets/Builder/WidgetCreationView.swift | 8 ++--- .../ThreadCredentialsSharingView.swift | 4 +-- .../WebView/ConnectionErrorDetailsView.swift | 10 +++---- .../DownloadManager/DownloadManagerView.swift | 4 +-- Sources/App/WebView/NoActiveURLView.swift | 2 +- Sources/App/WebView/WebViewController.swift | 2 +- .../Watch/Assist/WatchAssistView.swift | 6 ++-- .../Home/MagicItemRow/WatchMagicViewRow.swift | 4 +-- .../Extensions/Watch/Home/WatchHomeView.swift | 2 +- .../Widgets/Assist/WidgetAssistView.swift | 2 +- .../Widgets/Common/WidgetBasicView.swift | 4 +-- .../Widgets/Custom/WidgetCustom.swift | 2 +- .../Shared/Resources/Swiftgen/Strings.swift | 30 +++++++++++++++++++ 34 files changed, 117 insertions(+), 98 deletions(-) delete mode 100644 Sources/App/Settings/Widgets/Builder/WidgetAddItemView.swift diff --git a/HomeAssistant.xcodeproj/project.pbxproj b/HomeAssistant.xcodeproj/project.pbxproj index 0c74f5456..06d4e357a 100644 --- a/HomeAssistant.xcodeproj/project.pbxproj +++ b/HomeAssistant.xcodeproj/project.pbxproj @@ -713,7 +713,6 @@ 428338452BA1BB4F004798C2 /* Spaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = 428338422BA1BAFB004798C2 /* Spaces.swift */; }; 4285C5512D355F9900DADE45 /* WidgetCreationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4285C5502D355F9900DADE45 /* WidgetCreationView.swift */; }; 4285C5532D35658000DADE45 /* TileCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4285C5522D35658000DADE45 /* TileCard.swift */; }; - 4285C5552D3568A100DADE45 /* WidgetAddItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4285C5542D3568A100DADE45 /* WidgetAddItemView.swift */; }; 428830EB2C6E3A8D0012373D /* WatchHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 428830EA2C6E3A8D0012373D /* WatchHomeView.swift */; }; 428830ED2C6E3A9A0012373D /* WatchHomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 428830EC2C6E3A9A0012373D /* WatchHomeViewModel.swift */; }; 4289DDAA2C85AB4C003591C2 /* AssistAppIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425FF0552C8216B3000AA641 /* AssistAppIntent.swift */; }; @@ -2068,7 +2067,6 @@ 428338422BA1BAFB004798C2 /* Spaces.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Spaces.swift; sourceTree = ""; }; 4285C5502D355F9900DADE45 /* WidgetCreationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetCreationView.swift; sourceTree = ""; }; 4285C5522D35658000DADE45 /* TileCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileCard.swift; sourceTree = ""; }; - 4285C5542D3568A100DADE45 /* WidgetAddItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetAddItemView.swift; sourceTree = ""; }; 428830EA2C6E3A8D0012373D /* WatchHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchHomeView.swift; sourceTree = ""; }; 428830EC2C6E3A9A0012373D /* WatchHomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchHomeViewModel.swift; sourceTree = ""; }; 4289DDAE2C85D5C4003591C2 /* ControlScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlScene.swift; sourceTree = ""; }; @@ -4104,7 +4102,6 @@ 421B1C172BD6524E001ED18C /* WidgetBuilderViewModel.swift */, 4285C5502D355F9900DADE45 /* WidgetCreationView.swift */, 42B74A652D37C2C000C37304 /* WidgetCreationViewModel.swift */, - 4285C5542D3568A100DADE45 /* WidgetAddItemView.swift */, ); path = Builder; sourceTree = ""; @@ -7128,7 +7125,6 @@ 1185DF94271FBA6100ED7D9A /* OnboardingAuthDetails.swift in Sources */, 42BE698D2C4691EA00745ECA /* WebViewAccessoryViews.swift in Sources */, 4273C48B2C8858470065A5B4 /* ControlOpenPageValueProvider.swift in Sources */, - 4285C5552D3568A100DADE45 /* WidgetAddItemView.swift in Sources */, 420FE84B2B556BB100878E06 /* CarPlayActionsTemplate+Build.swift in Sources */, 42DF6B2F2CCF918D00D7EC14 /* BluetoothPermissionView.swift in Sources */, 425573C72B5572AD00145217 /* CarPlayServerListTemplate+Build.swift in Sources */, diff --git a/Sources/App/Assist/AssistView.swift b/Sources/App/Assist/AssistView.swift index 8591fdb99..605b15c9f 100644 --- a/Sources/App/Assist/AssistView.swift +++ b/Sources/App/Assist/AssistView.swift @@ -58,9 +58,9 @@ struct AssistView: View { } .alert(isPresented: $viewModel.showError) { .init( - title: Text(L10n.errorLabel), + title: Text(verbatim: L10n.errorLabel), message: Text(viewModel.errorMessage), - dismissButton: .default(Text(L10n.okLabel)) + dismissButton: .default(Text(verbatim: L10n.okLabel)) ) } } diff --git a/Sources/App/Assist/Views/AssistMicAnimationView.swift b/Sources/App/Assist/Views/AssistMicAnimationView.swift index 7131656d8..aa0a4c286 100644 --- a/Sources/App/Assist/Views/AssistMicAnimationView.swift +++ b/Sources/App/Assist/Views/AssistMicAnimationView.swift @@ -30,7 +30,7 @@ struct AssistMicAnimationView: View { VStack(spacing: Spaces.one) { icon .foregroundStyle(Color.asset(Asset.Colors.haPrimary)) - Text(L10n.Assist.Button.Listening.title) + Text(verbatim: L10n.Assist.Button.Listening.title) .opacity(0.5) } } diff --git a/Sources/App/Improv/ImprovDiscoverView.swift b/Sources/App/Improv/ImprovDiscoverView.swift index 03976d074..b9634bae9 100644 --- a/Sources/App/Improv/ImprovDiscoverView.swift +++ b/Sources/App/Improv/ImprovDiscoverView.swift @@ -128,7 +128,7 @@ struct ImprovDiscoverView: View where Manager: ImprovManagerProtocol { cancelWifiInput() } } message: { - Text(L10n.Improv.Wifi.Alert.description) + Text(verbatim: L10n.Improv.Wifi.Alert.description) } } @@ -196,7 +196,7 @@ struct ImprovDiscoverView: View where Manager: ImprovManagerProtocol { } }, header: { HStack(spacing: Spaces.two) { - Text(L10n.Improv.List.title) + Text(verbatim: L10n.Improv.List.title) .textCase(.uppercase) .font(.footnote) .foregroundStyle(Color(uiColor: .secondaryLabel)) diff --git a/Sources/App/Improv/Views/ImprovFailureView.swift b/Sources/App/Improv/Views/ImprovFailureView.swift index f1b868b62..945cdf6d7 100644 --- a/Sources/App/Improv/Views/ImprovFailureView.swift +++ b/Sources/App/Improv/Views/ImprovFailureView.swift @@ -19,7 +19,7 @@ struct ImprovFailureView: View { Button { action() } label: { - Text(L10n.Improv.Button.continue) + Text(verbatim: L10n.Improv.Button.continue) .padding() .foregroundColor(Color(uiColor: .secondaryLabel)) } diff --git a/Sources/App/Improv/Views/ImprovSuccessView.swift b/Sources/App/Improv/Views/ImprovSuccessView.swift index b8ed23a29..863ad9bdb 100644 --- a/Sources/App/Improv/Views/ImprovSuccessView.swift +++ b/Sources/App/Improv/Views/ImprovSuccessView.swift @@ -18,7 +18,7 @@ struct ImprovSuccessView: View { .stroke(.regularMaterial, lineWidth: 5) ) } - Text(L10n.Improv.State.success) + Text(verbatim: L10n.Improv.State.success) .font(.title3.bold()) .foregroundStyle(Color(uiColor: .secondaryLabel)) } @@ -31,7 +31,7 @@ struct ImprovSuccessView: View { Button { action() } label: { - Text(L10n.Improv.Button.continue) + Text(verbatim: L10n.Improv.Button.continue) .foregroundStyle(Color(uiColor: .label)) .padding() } diff --git a/Sources/App/Onboarding/Screens/OnboardingErrorView.swift b/Sources/App/Onboarding/Screens/OnboardingErrorView.swift index 29d9f4569..4528673fe 100644 --- a/Sources/App/Onboarding/Screens/OnboardingErrorView.swift +++ b/Sources/App/Onboarding/Screens/OnboardingErrorView.swift @@ -12,7 +12,7 @@ struct OnboardingErrorView: View { var body: some View { VStack(spacing: Spaces.two) { - Text(L10n.Onboarding.ConnectionError.title) + Text(verbatim: L10n.Onboarding.ConnectionError.title) .font(.title.bold()) Image(systemSymbol: .xmarkCircleFill) .font(.system(size: 60)) diff --git a/Sources/App/Onboarding/Screens/OnboardingWelcomeView.swift b/Sources/App/Onboarding/Screens/OnboardingWelcomeView.swift index 03e88731a..fd0e41ca9 100644 --- a/Sources/App/Onboarding/Screens/OnboardingWelcomeView.swift +++ b/Sources/App/Onboarding/Screens/OnboardingWelcomeView.swift @@ -27,11 +27,11 @@ struct OnboardingWelcomeView: View { private var textBlock: some View { ScrollView { VStack(spacing: Spaces.two) { - Text(L10n.Onboarding.Welcome.title(Current.device.systemName())) + Text(verbatim: L10n.Onboarding.Welcome.title(Current.device.systemName())) .font(.title.bold()) .frame(maxWidth: .infinity, alignment: .center) .multilineTextAlignment(.center) - Text(L10n.Onboarding.Welcome.description) + Text(verbatim: L10n.Onboarding.Welcome.description) .foregroundStyle(Color(uiColor: .secondaryLabel)) Button(L10n.Onboarding.Welcome.learnMore) { showLearnMore = true @@ -44,7 +44,7 @@ struct OnboardingWelcomeView: View { private var continueButton: some View { NavigationLink(destination: OnboardingScanningView()) { - Text(L10n.continueLabel) + Text(verbatim: L10n.continueLabel) .font(.callout.bold()) .foregroundColor(.white) .frame(maxWidth: .infinity) diff --git a/Sources/App/Onboarding/Screens/PermissionRequestView.swift b/Sources/App/Onboarding/Screens/PermissionRequestView.swift index ada7abe4e..95ad85222 100644 --- a/Sources/App/Onboarding/Screens/PermissionRequestView.swift +++ b/Sources/App/Onboarding/Screens/PermissionRequestView.swift @@ -44,7 +44,7 @@ struct PermissionRequestView: View { Button { continueAction() } label: { - Text(L10n.continueLabel) + Text(verbatim: L10n.continueLabel) } .buttonStyle(.primaryButton) if showSkipButton { @@ -52,14 +52,14 @@ struct PermissionRequestView: View { dismissAction?() dismiss() } label: { - Text(L10n.Permission.Screen.Bluetooth.secondaryButton) + Text(verbatim: L10n.Permission.Screen.Bluetooth.secondaryButton) } .buttonStyle(.secondaryButton) } else { Button { /* no-op */ } label: { - Text(L10n.Onboarding.Permissions.changeLaterNote) + Text(verbatim: L10n.Onboarding.Permissions.changeLaterNote) } .buttonStyle(.linkButton) } diff --git a/Sources/App/Resources/en.lproj/Localizable.strings b/Sources/App/Resources/en.lproj/Localizable.strings index ee1a4adf5..670da2677 100644 --- a/Sources/App/Resources/en.lproj/Localizable.strings +++ b/Sources/App/Resources/en.lproj/Localizable.strings @@ -150,6 +150,9 @@ "carplay.navigation.button.next" = "Next"; "carplay.navigation.button.previous" = "Previous"; "carplay.unlock.confirmation.title" = "Are you sure you want to perform unlock action on %@?"; +"carPlay.tabs.active.title" = "Active"; +"carPlay.tabs.inactive.title" = "Inactive"; +"carPlay.tabs.active.delete_action.title" = "Swipe left to remove tab"; "cl_error.description.deferred_accuracy_too_low" = "Deferred mode is not supported for the requested accuracy."; "cl_error.description.deferred_canceled" = "The request for deferred updates was canceled by your app or by the location manager."; "cl_error.description.deferred_distance_filtered" = "Deferred mode does not support distance filters."; @@ -1170,6 +1173,7 @@ Home Assistant is free and open source home automation software with a focus on "widgets.sensors.description" = "Display state of sensors"; "widgets.sensors.not_configured" = "No Sensors Configured"; "widgets.sensors.title" = "Sensors"; +"connection_error.advanced_section.title" = "Advanced"; "widgets.custom.show_last_update_time.param.title" = "Show last update time"; "widgets.custom.show_states.param.title" = "Show states (BETA)"; "connection_error.open_settings.title" = "Open settings"; diff --git a/Sources/App/Settings/AppIcon/AppIconSelectorView.swift b/Sources/App/Settings/AppIcon/AppIconSelectorView.swift index 3bb02972f..591d31650 100644 --- a/Sources/App/Settings/AppIcon/AppIconSelectorView.swift +++ b/Sources/App/Settings/AppIcon/AppIconSelectorView.swift @@ -15,7 +15,7 @@ struct AppIconSelectorView: View { var body: some View { List { - Text(L10n.SettingsDetails.General.AppIcon.Explanation.title) + Text(verbatim: L10n.SettingsDetails.General.AppIcon.Explanation.title) .font(.footnote) ForEach(AppIcon.allCases, id: \.self) { icon in makeRow(name: sectionNameForIcon(icon), icons: [ diff --git a/Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationView.swift b/Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationView.swift index 765b223dd..634053bb3 100644 --- a/Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationView.swift +++ b/Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationView.swift @@ -20,7 +20,7 @@ struct WatchConfigurationView: View { Button(action: { dismiss() }, label: { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) }) } ToolbarItem(placement: .topBarTrailing) { @@ -34,7 +34,7 @@ struct WatchConfigurationView: View { } } }, label: { - Text(L10n.Watch.Configuration.Save.title) + Text(verbatim: L10n.Watch.Configuration.Save.title) }) } }) @@ -53,7 +53,7 @@ struct WatchConfigurationView: View { }) .alert(viewModel.errorMessage ?? L10n.errorLabel, isPresented: $viewModel.showError) { Button(action: {}, label: { - Text(L10n.okLabel) + Text(verbatim: L10n.okLabel) }) } } @@ -116,7 +116,7 @@ struct WatchConfigurationView: View { private var assistSection: some View { Section("Assist") { Toggle(isOn: $viewModel.watchConfig.assist.showAssist, label: { - Text(L10n.Watch.Configuration.ShowAssist.title) + Text(verbatim: L10n.Watch.Configuration.ShowAssist.title) }) if viewModel.watchConfig.assist.showAssist { Picker(L10n.Watch.Config.Assist.selectServer, selection: $viewModel.watchConfig.assist.serverId) { @@ -287,7 +287,7 @@ struct WatchConfigurationView: View { } private var noItemsWatchView: some View { - Text(L10n.Watch.Settings.NoItems.Phone.title) + Text(verbatim: L10n.Watch.Settings.NoItems.Phone.title) .frame(maxWidth: .infinity, alignment: .center) .font(.footnote) .padding(Spaces.one) diff --git a/Sources/App/Settings/CarPlay/CarPlayConfigurationView.swift b/Sources/App/Settings/CarPlay/CarPlayConfigurationView.swift index 8d08ebf6d..f8223b695 100644 --- a/Sources/App/Settings/CarPlay/CarPlayConfigurationView.swift +++ b/Sources/App/Settings/CarPlay/CarPlayConfigurationView.swift @@ -21,7 +21,7 @@ struct CarPlayConfigurationView: View { Button(action: { dismiss() }, label: { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) }) } ToolbarItem(placement: .topBarTrailing) { @@ -35,7 +35,7 @@ struct CarPlayConfigurationView: View { } } }, label: { - Text(L10n.Watch.Configuration.Save.title) + Text(verbatim: L10n.Watch.Configuration.Save.title) }) } }) @@ -53,7 +53,7 @@ struct CarPlayConfigurationView: View { }) .alert(viewModel.errorMessage ?? L10n.errorLabel, isPresented: $viewModel.showError) { Button(action: {}, label: { - Text(L10n.okLabel) + Text(verbatim: L10n.okLabel) }) } } @@ -182,12 +182,12 @@ struct CarPlayConfigurationView: View { viewModel.deleteTab(at: indexSet) } } header: { - Text("Active") + Text(L10n.CarPlay.Tabs.Active.title) } footer: { - Text("Swipe left to remove tab") + Text(L10n.CarPlay.Tabs.Active.DeleteAction.title) } if viewModel.config.tabs.count != CarPlayTab.allCases.count { - Section("Inactive") { + Section(L10n.CarPlay.Tabs.Inactive.title) { ForEach(CarPlayTab.allCases.filter({ tab in !viewModel.config.tabs.contains(tab) }), id: \.rawValue) { tab in diff --git a/Sources/App/Settings/ClientEventsLogView/ClientEventsLogView.swift b/Sources/App/Settings/ClientEventsLogView/ClientEventsLogView.swift index 4ffd25e39..1055c866b 100644 --- a/Sources/App/Settings/ClientEventsLogView/ClientEventsLogView.swift +++ b/Sources/App/Settings/ClientEventsLogView/ClientEventsLogView.swift @@ -23,7 +23,7 @@ struct ClientEventsLogView: View { Button { showClearConfirmation = true } label: { - Text(L10n.ClientEvents.View.clear) + Text(verbatim: L10n.ClientEvents.View.clear) } .confirmationDialog( L10n.ClientEvents.View.ClearConfirm.title, @@ -51,7 +51,7 @@ struct ClientEventsLogView: View { listItem(event) } if filteredEvents.isEmpty { - Text(L10n.ClientEvents.noEvents) + Text(verbatim: L10n.ClientEvents.noEvents) .frame(maxWidth: .infinity, alignment: .center) .listRowBackground(Color.clear) .font(.headline) diff --git a/Sources/App/Settings/DebugView.swift b/Sources/App/Settings/DebugView.swift index aa33a895e..063e4466a 100644 --- a/Sources/App/Settings/DebugView.swift +++ b/Sources/App/Settings/DebugView.swift @@ -174,7 +174,7 @@ struct DebugView: View { } .alert(L10n.Alert.Confirmation.Generic.title, isPresented: $showDeleteEntitiesAlert) { Button(role: .cancel, action: { /* no-op */ }) { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) } Button(role: .destructive, action: { do { @@ -186,10 +186,10 @@ struct DebugView: View { Current.Log.error("Failed to reset app entities, error: \(error)") } }) { - Text(L10n.yesLabel) + Text(verbatim: L10n.yesLabel) } } message: { - Text(L10n.Alert.Confirmation.DeleteEntities.message) + Text(verbatim: L10n.Alert.Confirmation.DeleteEntities.message) } Button { loadingCleaningWebCache = true @@ -224,21 +224,21 @@ struct DebugView: View { } .alert(L10n.Alert.Confirmation.Generic.title, isPresented: $showResetAppAlert) { Button(role: .cancel, action: { /* no-op */ }) { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) } Button(role: .destructive, action: { Task { await resetApp() } }) { - Text(L10n.yesLabel) + Text(verbatim: L10n.yesLabel) } } message: { - Text(L10n.Settings.ResetSection.ResetAlert.title) + Text(verbatim: L10n.Settings.ResetSection.ResetAlert.title) } } footer: { - Text(L10n.Settings.Debugging.CriticalSection.footer) + Text(verbatim: L10n.Settings.Debugging.CriticalSection.footer) } } @@ -257,7 +257,7 @@ struct DebugView: View { } .alert(L10n.errorLabel, isPresented: $showWatchSyncError) { Button(role: .cancel, action: { /* no-op */ }) { - Text(L10n.okLabel) + Text(verbatim: L10n.okLabel) } } message: { Text(watchSyncErrorMessage ?? "Unknown") @@ -312,9 +312,9 @@ struct DebugView: View { } } header: { - Text(L10n.Settings.Developer.header) + Text(verbatim: L10n.Settings.Developer.header) } footer: { - Text(L10n.Settings.Developer.footer) + Text(verbatim: L10n.Settings.Developer.footer) } } diff --git a/Sources/App/Settings/MagicItem/Add/MagicItemAddView.swift b/Sources/App/Settings/MagicItem/Add/MagicItemAddView.swift index 79f01b3ce..5bd32c987 100644 --- a/Sources/App/Settings/MagicItem/Add/MagicItemAddView.swift +++ b/Sources/App/Settings/MagicItem/Add/MagicItemAddView.swift @@ -86,16 +86,16 @@ struct MagicItemAddView: View { ForEach(visiblePickerOptions, id: \.self) { option in switch option { case .entities: - Text(L10n.MagicItem.ItemType.Entity.List.title) + Text(verbatim: L10n.MagicItem.ItemType.Entity.List.title) .tag(MagicItemAddType.entities) case .legacyiOSActions: - Text(L10n.MagicItem.ItemType.Action.List.title) + Text(verbatim: L10n.MagicItem.ItemType.Action.List.title) .tag(MagicItemAddType.actions) case .scripts: - Text(L10n.MagicItem.ItemType.Script.List.title) + Text(verbatim: L10n.MagicItem.ItemType.Script.List.title) .tag(MagicItemAddType.scripts) case .scenes: - Text(L10n.MagicItem.ItemType.Scene.List.title) + Text(verbatim: L10n.MagicItem.ItemType.Scene.List.title) .tag(MagicItemAddType.scenes) } } @@ -135,7 +135,7 @@ struct MagicItemAddView: View { Button { viewModel.selectedItemType = .scripts } label: { - Text(L10n.MagicItem.ItemType.Action.List.Warning.title) + Text(verbatim: L10n.MagicItem.ItemType.Action.List.Warning.title) } .buttonStyle(.bordered) .tint(.red) diff --git a/Sources/App/Settings/MagicItem/AssistPipelinePicker.swift b/Sources/App/Settings/MagicItem/AssistPipelinePicker.swift index c4c12f4bf..6ed1ac8ec 100644 --- a/Sources/App/Settings/MagicItem/AssistPipelinePicker.swift +++ b/Sources/App/Settings/MagicItem/AssistPipelinePicker.swift @@ -22,7 +22,7 @@ struct AssistPipelinePicker: View { if selectedServerId != nil, let selectedPipelineId, !assistConfigs.isEmpty { Text(nameForSelectedPipeline() ?? selectedPipelineId) } else { - Text(L10n.AssistPipelinePicker.placeholder) + Text(verbatim: L10n.AssistPipelinePicker.placeholder) } }) .onAppear { diff --git a/Sources/App/Settings/MagicItem/Edit/MagicItemCustomizationView.swift b/Sources/App/Settings/MagicItem/Edit/MagicItemCustomizationView.swift index 636230dbe..514b1a375 100644 --- a/Sources/App/Settings/MagicItem/Edit/MagicItemCustomizationView.swift +++ b/Sources/App/Settings/MagicItem/Edit/MagicItemCustomizationView.swift @@ -141,13 +141,13 @@ struct MagicItemCustomizationView: View { .frame(maxWidth: .infinity, alignment: .leading) } } header: { - Text(L10n.MagicItem.DisplayText.title) + Text(verbatim: L10n.MagicItem.DisplayText.title) } footer: { if viewModel.item.type == .script { - Text(L10n.MagicItem.NameAndIcon.footer) + Text(verbatim: L10n.MagicItem.NameAndIcon.footer) } if viewModel.item.type == .scene { - Text(L10n.MagicItem.NameAndIcon.Footer.scenes) + Text(verbatim: L10n.MagicItem.NameAndIcon.Footer.scenes) } } } @@ -187,7 +187,7 @@ struct MagicItemCustomizationView: View { if context == .widget, actionsLoaded { Section(L10n.MagicItem.action) { HStack { - Text(L10n.MagicItem.Action.onTap) + Text(verbatim: L10n.MagicItem.Action.onTap) Spacer() Menu { ForEach(ItemAction.allCases, id: \.id) { itemAction in @@ -227,7 +227,7 @@ struct MagicItemCustomizationView: View { })) } footer: { if context == .widget { - Text(L10n.Widgets.Custom.RequireConfirmation.footer) + Text(verbatim: L10n.Widgets.Custom.RequireConfirmation.footer) } } } @@ -242,7 +242,7 @@ struct MagicItemCustomizationView: View { private var assistActionDetails: some View { Section(L10n.MagicItem.Action.Assist.title) { HStack { - Text(L10n.MagicItem.Action.Assist.Pipeline.title) + Text(verbatim: L10n.MagicItem.Action.Assist.Pipeline.title) .frame(maxWidth: .infinity, alignment: .leading) AssistPipelinePicker( selectedServerId: $viewModel.selectedServerIdForPipeline, @@ -268,7 +268,7 @@ struct MagicItemCustomizationView: View { } } HStack { - Text(L10n.MagicItem.Action.Assist.StartListening.title) + Text(verbatim: L10n.MagicItem.Action.Assist.StartListening.title) .frame(maxWidth: .infinity, alignment: .leading) Toggle(isOn: $viewModel.startListeningAssistAction, label: {}) .onChange(of: viewModel.startListeningAssistAction) { newValue in @@ -281,7 +281,7 @@ struct MagicItemCustomizationView: View { private var scriptActionDetails: some View { HStack { - Text(L10n.MagicItem.Action.Script.title) + Text(verbatim: L10n.MagicItem.Action.Script.title) EntityPicker(selectedEntity: $viewModel.selectedEntity, domainFilter: .script) .frame(maxWidth: .infinity, alignment: .trailing) .onChange(of: viewModel.selectedEntity) { newValue in diff --git a/Sources/App/Settings/MagicItem/EntityPicker.swift b/Sources/App/Settings/MagicItem/EntityPicker.swift index ddb60911d..a29306d4a 100644 --- a/Sources/App/Settings/MagicItem/EntityPicker.swift +++ b/Sources/App/Settings/MagicItem/EntityPicker.swift @@ -30,7 +30,7 @@ struct EntityPicker: View { if let name = selectedEntity?.name { Text(name) } else { - Text(L10n.EntityPicker.placeholder) + Text(verbatim: L10n.EntityPicker.placeholder) } }) } diff --git a/Sources/App/Settings/Widgets/Builder/WidgetAddItemView.swift b/Sources/App/Settings/Widgets/Builder/WidgetAddItemView.swift deleted file mode 100644 index b43bf634d..000000000 --- a/Sources/App/Settings/Widgets/Builder/WidgetAddItemView.swift +++ /dev/null @@ -1,11 +0,0 @@ -import SwiftUI - -struct WidgetAddItemView: View { - var body: some View { - Text("Hello, World!") - } -} - -#Preview { - WidgetAddItemView() -} diff --git a/Sources/App/Settings/Widgets/Builder/WidgetBuilderView.swift b/Sources/App/Settings/Widgets/Builder/WidgetBuilderView.swift index f6227f56e..dd5e9e21c 100644 --- a/Sources/App/Settings/Widgets/Builder/WidgetBuilderView.swift +++ b/Sources/App/Settings/Widgets/Builder/WidgetBuilderView.swift @@ -13,7 +13,7 @@ struct WidgetBuilderView: View { Section { reloadWidgetsView } footer: { - Text(L10n.SettingsDetails.Widgets.ReloadAll.description) + Text(verbatim: L10n.SettingsDetails.Widgets.ReloadAll.description) } if #available(iOS 17, *) { @@ -21,7 +21,7 @@ struct WidgetBuilderView: View { showDeleteConfirmation = true } label: { - Text(L10n.Settings.Widgets.Custom.DeleteAll.title) + Text(verbatim: L10n.Settings.Widgets.Custom.DeleteAll.title) } .tint(.red) .confirmationDialog( @@ -30,13 +30,13 @@ struct WidgetBuilderView: View { titleVisibility: .visible ) { Button(role: .cancel, action: { /* no-op */ }) { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) } Button(role: .destructive, action: { viewModel.deleteAllWidgets() }) { - Text(L10n.yesLabel) + Text(verbatim: L10n.yesLabel) } } } diff --git a/Sources/App/Settings/Widgets/Builder/WidgetCreationView.swift b/Sources/App/Settings/Widgets/Builder/WidgetCreationView.swift index de06eb16e..382f2d963 100644 --- a/Sources/App/Settings/Widgets/Builder/WidgetCreationView.swift +++ b/Sources/App/Settings/Widgets/Builder/WidgetCreationView.swift @@ -28,7 +28,7 @@ struct WidgetCreationView: View { Button { viewModel.save() } label: { - Text(L10n.saveLabel) + Text(verbatim: L10n.saveLabel) } } } @@ -45,7 +45,7 @@ struct WidgetCreationView: View { Button(action: { /* no-op */ }, label: { - Text(L10n.okLabel) + Text(verbatim: L10n.okLabel) }) }, message: { Text(viewModel.errorMessage) @@ -107,9 +107,9 @@ struct WidgetCreationView: View { Label(L10n.Settings.Widgets.Create.AddItem.title, systemSymbol: .plus) } } header: { - Text(L10n.Watch.Configuration.Items.title) + Text(verbatim: L10n.Watch.Configuration.Items.title) } footer: { - Text(L10n.Settings.Widgets.Create.Footer.title) + Text(verbatim: L10n.Settings.Widgets.Create.Footer.title) } } diff --git a/Sources/App/Thread/CredentialsSharing/ThreadCredentialsSharingView.swift b/Sources/App/Thread/CredentialsSharing/ThreadCredentialsSharingView.swift index abc1bbaad..685611f8b 100644 --- a/Sources/App/Thread/CredentialsSharing/ThreadCredentialsSharingView.swift +++ b/Sources/App/Thread/CredentialsSharing/ThreadCredentialsSharingView.swift @@ -77,7 +77,7 @@ struct ThreadCredentialsSharingView: View where Model: ThreadCredentialsS Button { dismiss() } label: { - Text(L10n.doneLabel) + Text(verbatim: L10n.doneLabel) } } @@ -87,7 +87,7 @@ struct ThreadCredentialsSharingView: View where Model: ThreadCredentialsS await viewModel.mainOperation() } } label: { - Text(L10n.retryLabel) + Text(verbatim: L10n.retryLabel) } } diff --git a/Sources/App/WebView/ConnectionErrorDetailsView.swift b/Sources/App/WebView/ConnectionErrorDetailsView.swift index 8b3623298..dfb045ac1 100644 --- a/Sources/App/WebView/ConnectionErrorDetailsView.swift +++ b/Sources/App/WebView/ConnectionErrorDetailsView.swift @@ -14,14 +14,14 @@ struct ConnectionErrorDetailsView: View { headerView VStack(alignment: .leading) { VStack(alignment: .leading, spacing: Spaces.two) { - Text(L10n.Connection.Error.FailedConnect.title) + Text(verbatim: L10n.Connection.Error.FailedConnect.title) .font(.title.bold()) - Text(L10n.Connection.Error.FailedConnect.subtitle) + Text(verbatim: L10n.Connection.Error.FailedConnect.subtitle) if let urlError = error as? URLError, let url = urlError.failingURL?.absoluteString, let attributedString = try? AttributedString(markdown: "[\(url)](\(url))") { VStack { - Text(L10n.Connection.Error.FailedConnect.url) + Text(verbatim: L10n.Connection.Error.FailedConnect.url) .font(.footnote) Text(attributedString) .font(.body.bold()) @@ -44,13 +44,13 @@ struct ConnectionErrorDetailsView: View { .font(.body.italic()) } else { // Alert user when it has deactivated cloud usage in the App - Text(L10n.Connection.Error.FailedConnect.CloudInactive.title) + Text(verbatim: L10n.Connection.Error.FailedConnect.CloudInactive.title) } } } openSettingsButton CollapsibleView { - Text("Advanced") + Text(L10n.ConnectionError.AdvancedSection.title) .font(.body.bold()) } expandedContent: { advancedContent diff --git a/Sources/App/WebView/DownloadManager/DownloadManagerView.swift b/Sources/App/WebView/DownloadManager/DownloadManagerView.swift index c0a794aa9..39a29fa2d 100644 --- a/Sources/App/WebView/DownloadManager/DownloadManagerView.swift +++ b/Sources/App/WebView/DownloadManager/DownloadManagerView.swift @@ -41,7 +41,7 @@ struct DownloadManagerView: View { .progressViewStyle(.circular) .scaleEffect(2) .padding(Spaces.four) - Text(L10n.DownloadManager.Downloading.title) + Text(verbatim: L10n.DownloadManager.Downloading.title) .font(.title.bold()) fileCard Text(viewModel.progress) @@ -76,7 +76,7 @@ struct DownloadManagerView: View { .bounce, options: .nonRepeating ) - Text(L10n.DownloadManager.Finished.title) + Text(verbatim: L10n.DownloadManager.Finished.title) .font(.title.bold()) if let url = viewModel.lastURLCreated { if Current.isCatalyst { diff --git a/Sources/App/WebView/NoActiveURLView.swift b/Sources/App/WebView/NoActiveURLView.swift index 77ee28066..02fdac50e 100644 --- a/Sources/App/WebView/NoActiveURLView.swift +++ b/Sources/App/WebView/NoActiveURLView.swift @@ -105,7 +105,7 @@ struct NoActiveURLView: View { @ViewBuilder private var textBlock: some View { - Text(L10n.Connection.Permission.InternalUrl.title) + Text(verbatim: L10n.Connection.Permission.InternalUrl.title) .font(.title.bold()) .padding(.vertical) VStack(spacing: Spaces.two) { diff --git a/Sources/App/WebView/WebViewController.swift b/Sources/App/WebView/WebViewController.swift index dffa7bc40..27a371df0 100644 --- a/Sources/App/WebView/WebViewController.swift +++ b/Sources/App/WebView/WebViewController.swift @@ -1043,7 +1043,7 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg NavigationView { VStack { HStack(spacing: Spaces.half) { - Text(L10n.Settings.Debugging.ShakeDisclaimerOptional.title) + Text(verbatim: L10n.Settings.Debugging.ShakeDisclaimerOptional.title) Toggle(isOn: .init(get: { Current.settingsStore.gestures[.shake] == .openDebug }, set: { newValue in diff --git a/Sources/Extensions/Watch/Assist/WatchAssistView.swift b/Sources/Extensions/Watch/Assist/WatchAssistView.swift index a05885cd3..f476f0407 100644 --- a/Sources/Extensions/Watch/Assist/WatchAssistView.swift +++ b/Sources/Extensions/Watch/Assist/WatchAssistView.swift @@ -109,7 +109,7 @@ struct WatchAssistView: View { if ![.loading, .recording].contains(viewModel.state), !viewModel.showChatLoader { HStack(spacing: Spaces.one) { if viewModel.assistService.deviceReachable { - Text(L10n.Assist.Watch.MicButton.title) + Text(verbatim: L10n.Assist.Watch.MicButton.title) Image(systemName: "mic.fill") } else { Image(systemName: "iphone.slash") @@ -170,10 +170,10 @@ struct WatchAssistView: View { Image(systemSymbol: .waveformCircleFill) .font(.system(size: 50)) } - Text(L10n.Watch.Assist.Button.Recording.title) + Text(verbatim: L10n.Watch.Assist.Button.Recording.title) .font(.system(size: 11)) .foregroundStyle(.gray) - Text(L10n.Watch.Assist.Button.SendRequest.title) + Text(verbatim: L10n.Watch.Assist.Button.SendRequest.title) .font(.footnote.bold()) .padding() } diff --git a/Sources/Extensions/Watch/Home/MagicItemRow/WatchMagicViewRow.swift b/Sources/Extensions/Watch/Home/MagicItemRow/WatchMagicViewRow.swift index 2a1e6b9b2..983d8b882 100644 --- a/Sources/Extensions/Watch/Home/MagicItemRow/WatchMagicViewRow.swift +++ b/Sources/Extensions/Watch/Home/MagicItemRow/WatchMagicViewRow.swift @@ -31,10 +31,10 @@ struct WatchMagicViewRow: View { Button(action: { viewModel.confirmationAction() }, label: { - Text(L10n.yesLabel) + Text(verbatim: L10n.yesLabel) }) Button(action: {}, label: { - Text(L10n.cancelLabel) + Text(verbatim: L10n.cancelLabel) }) .tint(.red) } diff --git a/Sources/Extensions/Watch/Home/WatchHomeView.swift b/Sources/Extensions/Watch/Home/WatchHomeView.swift index a048ce4cf..71f023024 100644 --- a/Sources/Extensions/Watch/Home/WatchHomeView.swift +++ b/Sources/Extensions/Watch/Home/WatchHomeView.swift @@ -91,7 +91,7 @@ struct WatchHomeView: View { .listRowBackground(Color.red.opacity(0.5).clipShape(RoundedRectangle(cornerRadius: 12))) } if viewModel.watchConfig.items.isEmpty { - Text(L10n.Watch.Labels.noConfig) + Text(verbatim: L10n.Watch.Labels.noConfig) .font(.footnote) } else { mainContent diff --git a/Sources/Extensions/Widgets/Assist/WidgetAssistView.swift b/Sources/Extensions/Widgets/Assist/WidgetAssistView.swift index 1dc3ff00a..c96696659 100644 --- a/Sources/Extensions/Widgets/Assist/WidgetAssistView.swift +++ b/Sources/Extensions/Widgets/Assist/WidgetAssistView.swift @@ -50,7 +50,7 @@ struct WidgetAssistView: View { .foregroundStyle(.ultraThickMaterial) VStack(spacing: .zero) { Group { - Text(L10n.Widgets.Assist.actionTitle) + Text(verbatim: L10n.Widgets.Assist.actionTitle) .font(.footnote.bold()) .foregroundColor(Color(uiColor: .label)) Text(subtitle) diff --git a/Sources/Extensions/Widgets/Common/WidgetBasicView.swift b/Sources/Extensions/Widgets/Common/WidgetBasicView.swift index 7cbd46111..f835494cc 100644 --- a/Sources/Extensions/Widgets/Common/WidgetBasicView.swift +++ b/Sources/Extensions/Widgets/Common/WidgetBasicView.swift @@ -186,7 +186,7 @@ struct WidgetBasicView: View { confirmationColor: Color ) -> some View { VStack { - Text(L10n.Alert.Confirmation.Generic.title) + Text(verbatim: L10n.Alert.Confirmation.Generic.title) .font(.footnote.bold()) .frame(maxWidth: .infinity, alignment: .leading) Spacer() @@ -219,7 +219,7 @@ struct WidgetBasicView: View { confirmationColor: Color ) -> some View { VStack(spacing: .zero) { - Text(L10n.Alert.Confirmation.Generic.title) + Text(verbatim: L10n.Alert.Confirmation.Generic.title) .font(.footnote.bold()) .frame(maxWidth: .infinity, alignment: .leading) .padding([.horizontal, .top], Spaces.one) diff --git a/Sources/Extensions/Widgets/Custom/WidgetCustom.swift b/Sources/Extensions/Widgets/Custom/WidgetCustom.swift index 111b29a8e..b72005e24 100644 --- a/Sources/Extensions/Widgets/Custom/WidgetCustom.swift +++ b/Sources/Extensions/Widgets/Custom/WidgetCustom.swift @@ -39,7 +39,7 @@ struct WidgetCustom: Widget { Image(systemSymbol: .squareBadgePlusFill) .foregroundStyle(Color.asset(Asset.Colors.haPrimary)) .font(.system(size: 55)) - Text(L10n.Widgets.Preview.Empty.Create.button) + Text(verbatim: L10n.Widgets.Preview.Empty.Create.button) .foregroundStyle(.secondary) .font(.footnote) } diff --git a/Sources/Shared/Resources/Swiftgen/Strings.swift b/Sources/Shared/Resources/Swiftgen/Strings.swift index c0dbbd4e9..41910d568 100644 --- a/Sources/Shared/Resources/Swiftgen/Strings.swift +++ b/Sources/Shared/Resources/Swiftgen/Strings.swift @@ -638,6 +638,20 @@ public enum L10n { public static var title: String { return L10n.tr("Localizable", "carPlay.state.loading.title") } } } + public enum Tabs { + public enum Active { + /// Active + public static var title: String { return L10n.tr("Localizable", "carPlay.tabs.active.title") } + public enum DeleteAction { + /// Swipe left to remove tab + public static var title: String { return L10n.tr("Localizable", "carPlay.tabs.active.delete_action.title") } + } + } + public enum Inactive { + /// Inactive + public static var title: String { return L10n.tr("Localizable", "carPlay.tabs.inactive.title") } + } + } public enum Unlock { public enum Confirmation { /// Are you sure you want to perform unlock action on %@? @@ -848,6 +862,10 @@ public enum L10n { } public enum ConnectionError { + public enum AdvancedSection { + /// Advanced + public static var title: String { return L10n.tr("Localizable", "connection_error.advanced_section.title") } + } public enum OpenSettings { /// Open settings public static var title: String { return L10n.tr("Localizable", "connection_error.open_settings.title") } @@ -3967,6 +3985,18 @@ public enum L10n { /// Widget confirmation and state display are currently in BETA, if you experience issues please disable 'Require confirmation' and save. public static var footer: String { return L10n.tr("Localizable", "widgets.custom.require_confirmation.footer") } } + public enum ShowLastUpdateTime { + public enum Param { + /// Show last update time + public static var title: String { return L10n.tr("Localizable", "widgets.custom.show_last_update_time.param.title") } + } + } + public enum ShowStates { + public enum Param { + /// Show states (BETA) + public static var title: String { return L10n.tr("Localizable", "widgets.custom.show_states.param.title") } + } + } public enum ShowUpdateTime { /// Last update: public static var title: String { return L10n.tr("Localizable", "widgets.custom.show_update_time.title") }