Switch to generated localized string symbols (#607)

* Switch to string symbols

* Names

* Cleanup packages

* Cleanup packages

* Remove namespace

* More cleanup

* Fix extra param.

* Use swiftbuild
This commit is contained in:
Max Goedjen
2025-08-17 22:26:13 -05:00
committed by GitHub
parent 83ecc15332
commit 9749cd6f3e
22 changed files with 528 additions and 535 deletions

View File

@@ -70,15 +70,15 @@ extension ContentView {
}
}
var updateNoticeContent: (LocalizedStringKey, Color)? {
var updateNoticeContent: (LocalizedStringResource, Color)? {
guard let update = updater.update else { return nil }
if update.critical {
return ("update_critical_notice_title", .red)
return (.updateCriticalNoticeTitle, .red)
} else {
if updater.testBuild {
return ("update_test_notice_title", .blue)
return (.updateTestNoticeTitle, .blue)
} else {
return ("update_normal_notice_title", .orange)
return (.updateNormalNoticeTitle, .orange)
}
}
}
@@ -127,13 +127,13 @@ extension ContentView {
}, label: {
Group {
if hasRunSetup && !agentStatusChecker.running {
Text("agent_not_running_notice_title")
Text(.agentNotRunningNoticeTitle)
} else {
Text("agent_setup_notice_title")
Text(.agentSetupNoticeTitle)
}
}
.font(.headline)
.foregroundColor(.white)
})
.buttonStyle(ToolbarButtonStyle(color: .orange))
}
@@ -144,7 +144,7 @@ extension ContentView {
showingAgentInfo = true
}, label: {
HStack {
Text("agent_running_notice_title")
Text(.agentRunningNoticeTitle)
.font(.headline)
.foregroundColor(colorScheme == .light ? Color(white: 0.3) : .white)
Circle()
@@ -155,10 +155,10 @@ extension ContentView {
.buttonStyle(ToolbarButtonStyle(lightColor: .black.opacity(0.05), darkColor: .white.opacity(0.05)))
.popover(isPresented: $showingAgentInfo, attachmentAnchor: attachmentAnchor, arrowEdge: .bottom) {
VStack {
Text("agent_running_notice_detail_title")
Text(.agentRunningNoticeDetailTitle)
.font(.title)
.padding(5)
Text("agent_running_notice_detail_description")
Text(.agentRunningNoticeDetailDescription)
.frame(width: 300)
}
.padding()
@@ -172,7 +172,7 @@ extension ContentView {
showingAppPathNotice = true
}, label: {
Group {
Text("app_not_in_applications_notice_title")
Text(.appNotInApplicationsNoticeTitle)
}
.font(.headline)
.foregroundColor(.white)
@@ -184,7 +184,7 @@ extension ContentView {
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 64)
Text("app_not_in_applications_notice_detail_description")
Text(.appNotInApplicationsNoticeDetailDescription)
.frame(maxWidth: 300)
}
.padding()

View File

@@ -3,7 +3,7 @@ import UniformTypeIdentifiers
struct CopyableView: View {
var title: LocalizedStringKey
var title: LocalizedStringResource
var image: Image
var text: String

View File

@@ -14,30 +14,30 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
HStack {
VStack {
HStack {
Text("create_secret_title")
Text(.createSecretTitle)
.font(.largeTitle)
Spacer()
}
HStack {
Text("create_secret_name_label")
TextField("create_secret_name_placeholder", text: $name)
Text(.createSecretNameLabel)
TextField(String(localized: .createSecretNamePlaceholder), text: $name)
.focusable()
}
ThumbnailPickerView(items: [
ThumbnailPickerView.Item(value: true, name: "create_secret_require_authentication_title", description: "create_secret_require_authentication_description", thumbnail: AuthenticationView()),
ThumbnailPickerView.Item(value: false, name: "create_secret_notify_title",
description: "create_secret_notify_description",
ThumbnailPickerView.Item(value: true, name: .createSecretRequireAuthenticationTitle, description: .createSecretRequireAuthenticationDescription, thumbnail: AuthenticationView()),
ThumbnailPickerView.Item(value: false, name: .createSecretNotifyTitle,
description: .createSecretNotifyDescription,
thumbnail: NotificationView())
], selection: $requiresAuthentication)
}
}
HStack {
Spacer()
Button("create_secret_cancel_button") {
Button(.createSecretCancelButton) {
showing = false
}
.keyboardShortcut(.cancelAction)
Button("create_secret_create_button", action: save)
Button(.createSecretCreateButton, action: save)
.disabled(name.isEmpty)
.keyboardShortcut(.defaultAction)
}
@@ -98,11 +98,11 @@ extension ThumbnailPickerView {
struct Item<InnerValueType: Hashable>: Identifiable {
let id = UUID()
let value: InnerValueType
let name: LocalizedStringKey
let description: LocalizedStringKey
let name: LocalizedStringResource
let description: LocalizedStringResource
let thumbnail: AnyView
init<ViewType: View>(value: InnerValueType, name: LocalizedStringKey, description: LocalizedStringKey, thumbnail: ViewType) {
init<ViewType: View>(value: InnerValueType, name: LocalizedStringResource, description: LocalizedStringResource, thumbnail: ViewType) {
self.value = value
self.name = name
self.description = description

View File

@@ -18,24 +18,24 @@ struct DeleteSecretView<StoreType: SecretStoreModifiable>: View {
.padding()
VStack {
HStack {
Text("delete_confirmation_title_\(secret.name)").bold()
Text(.deleteConfirmationTitle(secretName: secret.name)).bold()
Spacer()
}
HStack {
Text("delete_confirmation_description_\(secret.name)_\(secret.name)")
Text(.deleteConfirmationDescription(secretName: secret.name, confirmSecretName: secret.name))
Spacer()
}
HStack {
Text("delete_confirmation_confirm_name_label")
Text(.deleteConfirmationConfirmNameLabel)
TextField(secret.name, text: $confirm)
}
}
}
HStack {
Spacer()
Button("delete_confirmation_delete_button", action: delete)
Button(.deleteConfirmationDeleteButton, action: delete)
.disabled(confirm != secret.name)
Button("delete_confirmation_cancel_button") {
Button(.deleteConfirmationCancelButton) {
dismissalBlock(false)
}
.keyboardShortcut(.cancelAction)

View File

@@ -18,9 +18,9 @@ struct EmptyStoreImmutableView: View {
var body: some View {
VStack {
Text("empty_store_nonmodifiable_title").bold()
Text("empty_store_nonmodifiable_description")
Text("empty_store_nonmodifiable_supported_key_types")
Text(.emptyStoreNonmodifiableTitle).bold()
Text(.emptyStoreNonmodifiableDescription)
Text(.emptyStoreNonmodifiableSupportedKeyTypes)
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
@@ -49,8 +49,8 @@ struct EmptyStoreModifiableView: View {
path.addLine(to: CGPoint(x: g.size.width - 3, y: 0))
}.fill()
}.frame(height: (windowGeometry.size.height/2) - 20).padding()
Text("empty_store_modifiable_click_here_title").bold()
Text("empty_store_modifiable_click_here_description")
Text(.emptyStoreModifiableClickHereTitle).bold()
Text(.emptyStoreModifiableClickHereDescription)
Spacer()
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}

View File

@@ -4,10 +4,10 @@ struct NoStoresView: View {
var body: some View {
VStack {
Text("no_secure_storage_title")
Text(.noSecureStorageTitle)
.bold()
Text("no_secure_storage_description")
Link("no_secure_storage_yubico_link", destination: URL(string: "https://www.yubico.com/products/compare-yubikey-5-series/")!)
Text(.noSecureStorageDescription)
Link(.noSecureStorageYubicoLink, destination: URL(string: "https://www.yubico.com/products/compare-yubikey-5-series/")!)
}.padding()
}

View File

@@ -18,7 +18,7 @@ struct RenameSecretView<StoreType: SecretStoreModifiable>: View {
.padding()
VStack {
HStack {
Text("rename_title_\(secret.name)")
Text(.renameTitle(secretName: secret.name))
Spacer()
}
HStack {
@@ -28,10 +28,10 @@ struct RenameSecretView<StoreType: SecretStoreModifiable>: View {
}
HStack {
Spacer()
Button("rename_rename_button", action: rename)
Button(.renameRenameButton, action: rename)
.disabled(newName.count == 0)
.keyboardShortcut(.return)
Button("rename_cancel_button") {
Button(.renameCancelButton) {
dismissalBlock(false)
}.keyboardShortcut(.cancelAction)
}

View File

@@ -12,16 +12,16 @@ struct SecretDetailView<SecretType: Secret>: View {
ScrollView {
Form {
Section {
CopyableView(title: "secret_detail_sha256_fingerprint_label", image: Image(systemName: "touchid"), text: keyWriter.openSSHSHA256Fingerprint(secret: secret))
CopyableView(title: .secretDetailSha256FingerprintLabel, image: Image(systemName: "touchid"), text: keyWriter.openSSHSHA256Fingerprint(secret: secret))
Spacer()
.frame(height: 20)
CopyableView(title: "secret_detail_md5_fingerprint_label", image: Image(systemName: "touchid"), text: keyWriter.openSSHMD5Fingerprint(secret: secret))
CopyableView(title: .secretDetailMd5FingerprintLabel, image: Image(systemName: "touchid"), text: keyWriter.openSSHMD5Fingerprint(secret: secret))
Spacer()
.frame(height: 20)
CopyableView(title: "secret_detail_public_key_label", image: Image(systemName: "key"), text: keyString)
CopyableView(title: .secretDetailPublicKeyLabel, image: Image(systemName: "key"), text: keyString)
Spacer()
.frame(height: 20)
CopyableView(title: "secret_detail_public_key_path_label", image: Image(systemName: "lock.doc"), text: publicKeyFileStoreController.publicKeyPath(for: secret))
CopyableView(title: .secretDetailPublicKeyPathLabel, image: Image(systemName: "lock.doc"), text: publicKeyFileStoreController.publicKeyPath(for: secret))
Spacer()
}
}

View File

@@ -39,10 +39,10 @@ struct SecretListItemView: View {
.contextMenu {
if store is AnySecretStoreModifiable {
Button(action: { isRenaming = true }) {
Text("secret_list_rename_button")
Text(.secretListRenameButton)
}
Button(action: { isDeleting = true }) {
Text("secret_list_delete_button")
Text(.secretListDeleteButton)
}
}
}

View File

@@ -61,7 +61,7 @@ struct StepView: View {
Circle()
.foregroundColor(.green)
.frame(width: Constants.circleWidth, height: Constants.circleWidth)
Text("setup_step_complete_symbol")
Text(.setupStepCompleteSymbol)
.foregroundColor(.white)
.bold()
} else {
@@ -101,14 +101,14 @@ extension StepView {
struct SetupStepView<Content> : View where Content : View {
let title: LocalizedStringKey
let title: LocalizedStringResource
let image: Image
let bodyText: LocalizedStringKey
let buttonTitle: LocalizedStringKey
let bodyText: LocalizedStringResource
let buttonTitle: LocalizedStringResource
let buttonAction: () -> Void
let content: Content
init(title: LocalizedStringKey, image: Image, bodyText: LocalizedStringKey, buttonTitle: LocalizedStringKey, buttonAction: @escaping () -> Void = {}, @ViewBuilder content: () -> Content) {
init(title: LocalizedStringResource, image: Image, bodyText: LocalizedStringResource, buttonTitle: LocalizedStringResource, buttonAction: @escaping () -> Void = {}, @ViewBuilder content: () -> Content) {
self.title = title
self.image = image
self.bodyText = bodyText
@@ -145,12 +145,12 @@ struct SecretAgentSetupView: View {
let buttonAction: () -> Void
var body: some View {
SetupStepView(title: "setup_agent_title",
SetupStepView(title: .setupAgentTitle,
image: Image(nsImage: NSApplication.shared.applicationIconImage),
bodyText: "setup_agent_description",
buttonTitle: "setup_agent_install_button",
bodyText: .setupAgentDescription,
buttonTitle: .setupAgentInstallButton,
buttonAction: install) {
Text("setup_agent_activity_monitor_description")
Text(.setupAgentActivityMonitorDescription)
.multilineTextAlignment(.center)
}
}
@@ -172,12 +172,12 @@ struct SSHAgentSetupView: View {
@State private var selectedShellInstruction: ShellConfigInstruction = controller.shellInstructions.first!
var body: some View {
SetupStepView(title: "setup_ssh_title",
SetupStepView(title: .setupSshTitle,
image: Image(systemName: "terminal"),
bodyText: "setup_ssh_description",
buttonTitle: "setup_ssh_added_manually_button",
bodyText: .setupSshDescription,
buttonTitle: .setupSshAddedManuallyButton,
buttonAction: buttonAction) {
Link("setup_third_party_faq_link", destination: URL(string: "https://github.com/maxgoedjen/secretive/blob/main/APP_CONFIG.md")!)
Link(.setupThirdPartyFaqLink, destination: URL(string: "https://github.com/maxgoedjen/secretive/blob/main/APP_CONFIG.md")!)
Picker(selection: $selectedShellInstruction, label: EmptyView()) {
ForEach(SSHAgentSetupView.controller.shellInstructions) { instruction in
Text(instruction.shell)
@@ -185,8 +185,8 @@ struct SSHAgentSetupView: View {
.padding()
}
}.pickerStyle(SegmentedPickerStyle())
CopyableView(title: "setup_ssh_add_to_config_button_\(selectedShellInstruction.shellConfigPath)", image: Image(systemName: "greaterthan.square"), text: selectedShellInstruction.text)
Button("setup_ssh_add_for_me_button") {
CopyableView(title: .setupSshAddToConfigButton(configPath: selectedShellInstruction.shellConfigPath), image: Image(systemName: "greaterthan.square"), text: selectedShellInstruction.text)
Button(.setupSshAddForMeButton) {
let controller = ShellConfigurationController()
if controller.addToShell(shellInstructions: selectedShellInstruction) {
buttonAction()
@@ -216,12 +216,12 @@ struct UpdaterExplainerView: View {
let buttonAction: () -> Void
var body: some View {
SetupStepView(title: "setup_updates_title",
SetupStepView(title: .setupUpdatesTitle,
image: Image(systemName: "dot.radiowaves.left.and.right"),
bodyText: "setup_updates_description",
buttonTitle: "setup_updates_ok",
bodyText: .setupUpdatesDescription,
buttonTitle: .setupUpdatesOk,
buttonAction: buttonAction) {
Link("setup_updates_readmore", destination: SetupView.Constants.updaterFAQURL)
Link(.setupUpdatesReadmore, destination: SetupView.Constants.updaterFAQURL)
}
}

View File

@@ -9,22 +9,22 @@ struct UpdateDetailView: View {
var body: some View {
VStack {
Text("update_version_name_\(update.name)").font(.title)
GroupBox(label: Text("update_release_notes_title")) {
Text(.updateVersionName(updateName: update.name)).font(.title)
GroupBox(label: Text(.updateReleaseNotesTitle)) {
ScrollView {
attributedBody
}
}
HStack {
if !update.critical {
Button("update_ignore_button") {
Button(.updateIgnoreButton) {
Task {
await updater.ignore(release: update)
}
}
Spacer()
}
Button("update_update_button") {
Button(.updateUpdateButton) {
NSWorkspace.shared.open(update.html_url)
}
.keyboardShortcut(.defaultAction)