Switch to string symbols

This commit is contained in:
Max Goedjen 2025-08-17 12:57:18 -05:00
parent 0e6b218f1f
commit dd3ede37e7
No known key found for this signature in database
14 changed files with 146 additions and 158 deletions

View File

@ -10,8 +10,8 @@ final class Notifier: Sendable {
private let notificationDelegate = NotificationDelegate()
init() {
let updateAction = UNNotificationAction(identifier: Constants.updateActionIdentitifier, title: String(localized: "update_notification_update_button"), options: [])
let ignoreAction = UNNotificationAction(identifier: Constants.ignoreActionIdentitifier, title: String(localized: "update_notification_ignore_button"), options: [])
let updateAction = UNNotificationAction(identifier: Constants.updateActionIdentitifier, title: String(localized: .updateNotificationUpdateButton), options: [])
let ignoreAction = UNNotificationAction(identifier: Constants.ignoreActionIdentitifier, title: String(localized: .updateNotificationIgnoreButton), options: [])
let updateCategory = UNNotificationCategory(identifier: Constants.updateCategoryIdentitifier, actions: [updateAction, ignoreAction], intentIdentifiers: [], options: [])
let criticalUpdateCategory = UNNotificationCategory(identifier: Constants.criticalUpdateCategoryIdentitifier, actions: [updateAction], intentIdentifiers: [], options: [])
@ -22,7 +22,7 @@ final class Notifier: Sendable {
Measurement(value: 24, unit: UnitDuration.hours)
]
let doNotPersistAction = UNNotificationAction(identifier: Constants.doNotPersistActionIdentitifier, title: String(localized: "persist_authentication_decline_button"), options: [])
let doNotPersistAction = UNNotificationAction(identifier: Constants.doNotPersistActionIdentitifier, title: String(localized: .persistAuthenticationDeclineButton), options: [])
var allPersistenceActions = [doNotPersistAction]
let formatter = DateComponentsFormatter()
@ -41,7 +41,7 @@ final class Notifier: Sendable {
let persistAuthenticationCategory = UNNotificationCategory(identifier: Constants.persistAuthenticationCategoryIdentitifier, actions: allPersistenceActions, intentIdentifiers: [], options: [])
if persistAuthenticationCategory.responds(to: Selector(("actionsMenuTitle"))) {
persistAuthenticationCategory.setValue(String(localized: "persist_authentication_accept_button"), forKey: "_actionsMenuTitle")
persistAuthenticationCategory.setValue(String(localized: .persistAuthenticationAcceptButton), forKey: "_actionsMenuTitle")
}
UNUserNotificationCenter.current().setNotificationCategories([updateCategory, criticalUpdateCategory, persistAuthenticationCategory])
UNUserNotificationCenter.current().delegate = notificationDelegate
@ -64,8 +64,8 @@ final class Notifier: Sendable {
await notificationDelegate.state.setPending(secret: secret, store: store)
let notificationCenter = UNUserNotificationCenter.current()
let notificationContent = UNMutableNotificationContent()
notificationContent.title = String(localized: "signed_notification_title_\(provenance.origin.displayName)")
notificationContent.subtitle = String(localized: "signed_notification_description_\(secret.name)")
notificationContent.title = String(localized: .signedNotificationTitle(provenance.origin.displayName))
notificationContent.subtitle = String(localized: .signedNotificationDescription(secret.name))
notificationContent.userInfo[Constants.persistSecretIDKey] = secret.id.description
notificationContent.userInfo[Constants.persistStoreIDKey] = store.id.description
notificationContent.interruptionLevel = .timeSensitive
@ -85,11 +85,11 @@ final class Notifier: Sendable {
let notificationContent = UNMutableNotificationContent()
if update.critical {
notificationContent.interruptionLevel = .critical
notificationContent.title = String(localized: "update_notification_update_critical_title_\(update.name)")
notificationContent.title = String(localized: .updateNotificationUpdateCriticalTitle(update.name))
} else {
notificationContent.title = String(localized: "update_notification_update_normal_title_\(update.name)")
notificationContent.title = String(localized: .updateNotificationUpdateNormalTitle(update.name))
}
notificationContent.subtitle = String(localized: "update_notification_update_description")
notificationContent.subtitle = String(localized: .updateNotificationUpdateDescription)
notificationContent.body = update.body
notificationContent.categoryIdentifier = update.critical ? Constants.criticalUpdateCategoryIdentitifier : Constants.updateCategoryIdentitifier
let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil)

View File

@ -59,18 +59,18 @@ struct Secretive: App {
}
.commands {
CommandGroup(after: CommandGroupPlacement.newItem) {
Button("app_menu_new_secret_button") {
Button(.appMenuNewSecretButton) {
showingCreation = true
}
.keyboardShortcut(KeyboardShortcut(KeyEquivalent("N"), modifiers: [.command, .shift]))
}
CommandGroup(replacing: .help) {
Button("app_menu_help_button") {
Button(.appMenuHelpButton) {
NSWorkspace.shared.open(Constants.helpURL)
}
}
CommandGroup(after: .help) {
Button("app_menu_setup_button") {
Button(.appMenuSetupButton) {
showingSetup = true
}
}

View File

@ -2,6 +2,7 @@
"sourceLanguage" : "en",
"strings" : {
"agent_not_running_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -78,6 +79,7 @@
}
},
"agent_running_notice_detail_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -154,6 +156,7 @@
}
},
"agent_running_notice_detail_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -230,6 +233,7 @@
}
},
"agent_running_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -306,6 +310,7 @@
}
},
"agent_setup_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -382,6 +387,7 @@
}
},
"app_menu_help_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -458,6 +464,7 @@
}
},
"app_menu_new_secret_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -534,6 +541,7 @@
}
},
"app_menu_setup_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -610,6 +618,7 @@
}
},
"app_not_in_applications_notice_detail_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -686,6 +695,7 @@
}
},
"app_not_in_applications_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1308,6 +1318,7 @@
}
},
"copyable_click_to_copy_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1384,6 +1395,7 @@
}
},
"copyable_copied" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1460,6 +1472,7 @@
}
},
"create_secret_cancel_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1536,6 +1549,7 @@
}
},
"create_secret_create_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1612,6 +1626,7 @@
}
},
"create_secret_name_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1688,6 +1703,7 @@
}
},
"create_secret_name_placeholder" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1764,6 +1780,7 @@
}
},
"create_secret_notify_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1840,6 +1857,7 @@
}
},
"create_secret_notify_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1916,6 +1934,7 @@
}
},
"create_secret_require_authentication_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -1992,6 +2011,7 @@
}
},
"create_secret_require_authentication_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2068,6 +2088,7 @@
}
},
"create_secret_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2144,6 +2165,7 @@
}
},
"delete_confirmation_cancel_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2220,6 +2242,7 @@
}
},
"delete_confirmation_confirm_name_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2296,6 +2319,7 @@
}
},
"delete_confirmation_delete_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2372,6 +2396,7 @@
}
},
"delete_confirmation_description_%@_%@" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2448,6 +2473,7 @@
}
},
"delete_confirmation_title_%@" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2524,6 +2550,7 @@
}
},
"empty_store_modifiable_click_here_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2600,83 +2627,7 @@
}
},
"empty_store_modifiable_click_here_title" : {
"localizations" : {
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Sense secrets"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Keine Secrets"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "No Secrets"
}
},
"fi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ei salaisuuksia"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Aucun secret"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nessun Segreto"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "シークレットがありません"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "비밀이 없음"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Brak sekretów"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Sem Segredos"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Нет секретов"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "没有密钥串"
}
}
}
},
"empty_store_modifiable_title" : {
"extractionState" : "stale",
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2753,6 +2704,7 @@
}
},
"empty_store_nonmodifiable_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2829,6 +2781,7 @@
}
},
"empty_store_nonmodifiable_supported_key_types" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2905,6 +2858,7 @@
}
},
"empty_store_nonmodifiable_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -2981,6 +2935,7 @@
}
},
"no_secure_storage_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3057,6 +3012,7 @@
}
},
"no_secure_storage_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3133,6 +3089,7 @@
}
},
"no_secure_storage_yubico_link" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3365,6 +3322,7 @@
}
},
"rename_cancel_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3435,6 +3393,7 @@
}
},
"rename_rename_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3505,6 +3464,7 @@
}
},
"rename_title_%@" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3575,6 +3535,7 @@
}
},
"secret_detail_md5_fingerprint_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3645,6 +3606,7 @@
}
},
"secret_detail_public_key_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3715,6 +3677,7 @@
}
},
"secret_detail_public_key_path_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3785,6 +3748,7 @@
}
},
"secret_detail_sha256_fingerprint_label" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3855,6 +3819,7 @@
}
},
"secret_list_delete_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -3925,6 +3890,7 @@
}
},
"secret_list_rename_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4066,6 +4032,7 @@
}
},
"setup_agent_activity_monitor_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4136,6 +4103,7 @@
}
},
"setup_agent_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4206,6 +4174,7 @@
}
},
"setup_agent_install_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4276,6 +4245,7 @@
}
},
"setup_agent_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4346,6 +4316,7 @@
}
},
"setup_ssh_add_for_me_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4416,6 +4387,7 @@
}
},
"setup_ssh_add_to_config_button_%@" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4486,6 +4458,7 @@
}
},
"setup_ssh_added_manually_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4556,6 +4529,7 @@
}
},
"setup_ssh_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4626,6 +4600,7 @@
}
},
"setup_ssh_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4696,6 +4671,7 @@
}
},
"setup_step_complete_symbol" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4766,6 +4742,7 @@
}
},
"setup_third_party_faq_link" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4836,6 +4813,7 @@
}
},
"setup_updates_description" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4906,6 +4884,7 @@
}
},
"setup_updates_ok" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -4976,6 +4955,7 @@
}
},
"setup_updates_readmore" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -5046,6 +5026,7 @@
}
},
"setup_updates_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -5402,6 +5383,7 @@
}
},
"update_critical_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -5472,6 +5454,7 @@
}
},
"update_ignore_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -5542,6 +5525,7 @@
}
},
"update_normal_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -5972,6 +5956,7 @@
}
},
"update_release_notes_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -6042,6 +6027,7 @@
}
},
"update_test_notice_title" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -6112,6 +6098,7 @@
}
},
"update_update_button" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {
@ -6182,6 +6169,7 @@
}
},
"update_version_name_%@" : {
"extractionState" : "manual",
"localizations" : {
"ca" : {
"stringUnit" : {

View File

@ -64,7 +64,7 @@ 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)
@ -121,13 +121,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))
}
@ -138,7 +138,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()
@ -149,10 +149,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()
@ -166,7 +166,7 @@ extension ContentView {
showingAppPathNotice = true
}, label: {
Group {
Text("app_not_in_applications_notice_title")
Text(.appNotInApplicationsNoticeTitle)
}
.font(.headline)
.foregroundColor(.white)
@ -178,7 +178,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
@ -66,12 +66,12 @@ struct CopyableView: View {
)
}
var hoverText: LocalizedStringKey {
var hoverText: LocalizedStringResource {
switch interactionState {
case .hovering:
return "copyable_click_to_copy_button"
return .copyableClickToCopyButton
case .clicking:
return "copyable_copied"
return .copyableCopied
case .normal:
fatalError()
}

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(secret.name)).bold()
Spacer()
}
HStack {
Text("delete_confirmation_description_\(secret.name)_\(secret.name)")
Text(.deleteConfirmationDescription(secret.name, 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(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(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(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)