damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit 887eb902bf60a0169dfbf619125b17f284bfb45e
parent dcf328e7acb5b3d35fdfcacb6d7be17d6269c1b2
Author: Terry Yiu <963907+tyiu@users.noreply.github.com>
Date:   Fri,  6 Jan 2023 22:15:12 -0500

Add comments to localized strings

Diffstat:
Mdamus/Components/ImageCarousel.swift | 10+++++-----
Mdamus/Components/InvoiceView.swift | 4++--
Mdamus/Components/TextFieldAlert.swift | 4++--
Mdamus/ContentView.swift | 12++++++------
Mdamus/Views/AddRelayView.swift | 8++++----
Mdamus/Views/CarouselView.swift | 8++++----
Mdamus/Views/ConfigView.swift | 36++++++++++++++++++------------------
Mdamus/Views/CreateAccountView.swift | 6+++---
Mdamus/Views/DMChatView.swift | 4++--
Mdamus/Views/DirectMessagesView.swift | 2+-
Mdamus/Views/EditMetadataView.swift | 26+++++++++++++-------------
Mdamus/Views/Empty Views/EmptyTimelineView.swift | 2+-
Mdamus/Views/EventActionBar.swift | 8++++----
Mdamus/Views/EventDetailView.swift | 4++--
Mdamus/Views/EventView.swift | 14+++++++-------
Mdamus/Views/FollowButtonView.swift | 8++++----
Mdamus/Views/FollowingView.swift | 4++--
Mdamus/Views/LoginView.swift | 16++++++++--------
Mdamus/Views/MentionView.swift | 2+-
Mdamus/Views/PostView.swift | 4++--
Mdamus/Views/ProfileView.swift | 31+++++++++++--------------------
Mdamus/Views/RecommendedRelayView.swift | 2+-
Mdamus/Views/RelayView.swift | 4++--
Mdamus/Views/ReplyView.swift | 2+-
Mdamus/Views/SaveKeysView.swift | 14+++++++-------
Mdamus/Views/SearchHomeView.swift | 4++--
Mdamus/Views/SearchResultsView.swift | 12++++++------
Mdamus/Views/SelectWalletView.swift | 10+++++-----
Mdamus/Views/SetupView.swift | 2+-
Mdamus/Views/ThreadV2View.swift | 2+-
Mdamus/Views/ThreadView.swift | 4++--
Mdamus/en.lproj/Localizable.stringsdict | 26++++++++++++++++++++++----
32 files changed, 152 insertions(+), 143 deletions(-)

diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift @@ -41,24 +41,24 @@ struct ImageContextMenuModifier: ViewModifier { Button { UIPasteboard.general.url = url } label: { - Label("Copy Image URL", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy Image URL", comment: "Context menu option to copy the URL of an image into clipboard."), systemImage: "doc.on.doc") } if let someImage = image { Button { UIPasteboard.general.image = someImage } label: { - Label("Copy Image", systemImage: "photo.on.rectangle") + Label(NSLocalizedString("Copy Image", comment: "Context menu option to copy an image into clipboard."), systemImage: "photo.on.rectangle") } Button { UIImageWriteToSavedPhotosAlbum(someImage, nil, nil, nil) } label: { - Label("Save Image", systemImage: "square.and.arrow.down") + Label(NSLocalizedString("Save Image", comment: "Context menu option to save an image."), systemImage: "square.and.arrow.down") } } Button { showShareSheet = true } label: { - Label("Share", systemImage: "square.and.arrow.up") + Label(NSLocalizedString("Share", comment: "Button to share an image."), systemImage: "square.and.arrow.up") } } } @@ -143,7 +143,7 @@ struct ImageCarousel: View { } .id(url.absoluteString) .contextMenu { - Button("Copy Image") { + Button(NSLocalizedString("Copy Image", comment: "Context menu option to copy an image to clipboard.")) { UIPasteboard.general.string = url.absoluteString } } diff --git a/damus/Components/InvoiceView.swift b/damus/Components/InvoiceView.swift @@ -47,7 +47,7 @@ struct InvoiceView: View { RoundedRectangle(cornerRadius: 20) .foregroundColor(colorScheme == .light ? .black : .white) .overlay { - Text("Pay") + Text("Pay", comment: "Button to pay a Lightning invoice.") .fontWeight(.medium) .foregroundColor(colorScheme == .light ? .white : .black) } @@ -67,7 +67,7 @@ struct InvoiceView: View { HStack { Label("", systemImage: "bolt.fill") .foregroundColor(.orange) - Text("Lightning Invoice") + Text("Lightning Invoice", comment: "Indicates that the view is for paying a Lightning invoice.") } Divider() Text(invoice.description) diff --git a/damus/Components/TextFieldAlert.swift b/damus/Components/TextFieldAlert.swift @@ -20,7 +20,7 @@ struct TextFieldAlert<Presenting>: View where Presenting: View { .disabled(isShowing) VStack { Text(self.title) - TextField("Relay", text: self.$text) + TextField(NSLocalizedString("Relay", comment: "Text field for relay server. Used for testing purposes."), text: self.$text) Divider() HStack { Button(action: { @@ -28,7 +28,7 @@ struct TextFieldAlert<Presenting>: View where Presenting: View { self.isShowing.toggle() } }) { - Text("Dismiss") + Text("Dismiss", comment: "Button to dismiss a text field alert.") } } } diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -130,9 +130,9 @@ struct ContentView: View { var FiltersView: some View { VStack{ - Picker("Filter State", selection: $filter_state) { - Text("Posts").tag(FilterState.posts) - Text("Posts & Replies").tag(FilterState.posts_and_replies) + Picker(NSLocalizedString("Filter State", comment: "Filter state for seeing either only posts, or posts & replies."), selection: $filter_state) { + Text("Posts", comment: "Label for filter for seeing only posts (instead of posts and replies).").tag(FilterState.posts) + Text("Posts & Replies", comment: "Label for filter for seeing posts and replies (instead of only posts).").tag(FilterState.posts_and_replies) } .pickerStyle(.segmented) } @@ -158,7 +158,7 @@ struct ContentView: View { case .notifications: TimelineView(events: $home.notifications, loading: $home.loading, damus: damus, show_friend_icon: true, filter: { _ in true }) - .navigationTitle("Notifications") + .navigationTitle(NSLocalizedString("Notifications", comment: "Navigation title for notifications.")) case .dms: DirectMessagesView(damus_state: damus_state!) @@ -168,7 +168,7 @@ struct ContentView: View { EmptyView() } } - .navigationBarTitle(selected_timeline == .home ? "Home" : "Global", displayMode: .inline) + .navigationBarTitle(selected_timeline == .home ? NSLocalizedString("Home", comment: "Navigation bar title for Home view where posts and replies appear from those who the user is following.") : NSLocalizedString("Global", comment: "Navigation bar title for Global view where posts from all connected relay servers appear."), displayMode: .inline) } var MaybeSearchView: some View { @@ -229,7 +229,7 @@ struct ContentView: View { ToolbarItem(placement: .navigationBarTrailing) { HStack(alignment: .center) { if home.signal.signal != home.signal.max_signal { - Text("\(home.signal.signal)/\(home.signal.max_signal)") + Text("\(home.signal.signal)/\(home.signal.max_signal)", comment: "Fraction of how many of the user's relay servers that are operational.") .font(.callout) .foregroundColor(.gray) } diff --git a/damus/Views/AddRelayView.swift b/damus/Views/AddRelayView.swift @@ -16,10 +16,10 @@ struct AddRelayView: View { var body: some View { VStack(alignment: .leading) { Form { - Section("Add Relay") { + Section(NSLocalizedString("Add Relay", comment: "Label for section for adding a relay server.")) { ZStack(alignment: .leading) { HStack{ - TextField("wss://some.relay.com", text: $relay) + TextField(NSLocalizedString("wss://some.relay.com", comment: "Placeholder example for relay server address."), text: $relay) .padding(2) .padding(.leading, 25) .autocorrectionDisabled(true) @@ -47,7 +47,7 @@ struct AddRelayView: View { VStack { HStack { - Button("Cancel") { + Button(NSLocalizedString("Cancel", comment: "Button to cancel out of view adding user inputted relay.")) { show_add_relay = false action(nil) } @@ -55,7 +55,7 @@ struct AddRelayView: View { Spacer() - Button("Add") { + Button(NSLocalizedString("Add", comment: "Button to confirm adding user inputted relay.")) { show_add_relay = false action(relay) relay = "" diff --git a/damus/Views/CarouselView.swift b/damus/Views/CarouselView.swift @@ -15,13 +15,13 @@ struct CarouselItem: Identifiable { } let carousel_items = [ - CarouselItem(image: Image("digital-nomad"), text: Text("Welcome to the social network \(Text("you").italic()) control.")), + CarouselItem(image: Image("digital-nomad"), text: Text("Welcome to the social network \(Text("you", comment: "You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself.").italic()) control.", comment: "Welcoming message to the reader. The variable is 'you', the reader.")), CarouselItem(image: Image("encrypted-message"), - text: Text("\(Text("Encrypted").bold()). End-to-End encrypted private messaging. Keep Big Tech out of your DMs")), + text: Text("\(Text("Encrypted", comment: "Heading indicating that this application keeps private messaging end-to-end encrypted.").bold()). End-to-End encrypted private messaging. Keep Big Tech out of your DMs", comment: "Explanation of what is done to keep private data encrypted. There is a heading that precedes this explanation which is a variable to this string.")), CarouselItem(image: Image("undercover"), - text: Text("\(Text("Private").bold()). Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.")), + text: Text("\(Text("Private", comment: "Heading indicating that this application keeps personally identifiable information private. A sentence describing what is done to keep data private comes after this heading.").bold()). Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.", comment: "Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string.")), CarouselItem(image: Image("bitcoin-p2p"), - text: Text("\(Text("Earn Money").bold()). Tip your friend's posts and stack sats with Bitcoin鈿★笍, the native currency of the internet.")) + text: Text("\(Text("Earn Money", comment: "Heading indicating that this application allows users to earn money.").bold()). Tip your friend's posts and stack sats with Bitcoin鈿★笍, the native currency of the internet.", comment: "Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string.")) ] struct CarouselView: View { diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift @@ -61,7 +61,7 @@ struct ConfigView: View { } } header: { HStack { - Text("Relays") + Text("Relays", comment: "Header text for relay server list for configuration.") Spacer() Button(action: { show_add_relay = true }) { Image(systemName: "plus") @@ -70,13 +70,13 @@ struct ConfigView: View { } } - Section("Recommended Relays") { + Section(NSLocalizedString("Recommended Relays", comment: "Section title for recommend relay servers that could be added as part of configuration")) { List(recommended, id: \.url) { r in RecommendedRelayView(damus: state, relay: r.url.absoluteString) } } - Section("Public Account ID") { + Section(NSLocalizedString("Public Account ID", comment: "Section title for the user's public account ID.")) { HStack { Text(state.keypair.pubkey_bech32) @@ -86,10 +86,10 @@ struct ConfigView: View { } if let sec = state.keypair.privkey_bech32 { - Section("Secret Account Login Key") { + Section(NSLocalizedString("Secret Account Login Key", comment: "Section title for user's secret account login key.")) { HStack { if show_privkey == false { - SecureField("PrivateKey", text: $privkey) + SecureField(NSLocalizedString("PrivateKey", comment: "Title of the secure field that holds the user's private key."), text: $privkey) .disabled(true) } else { Text(sec) @@ -99,13 +99,13 @@ struct ConfigView: View { CopyButton(is_pk: false) } - Toggle("Show", isOn: $show_privkey) + Toggle(NSLocalizedString("Show", comment: "Toggle to show or hide user's secret account login key."), isOn: $show_privkey) } } - Section("Wallet Selector") { - Toggle("Show wallet selector", isOn: $user_settings.show_wallet_selector).toggleStyle(.switch) - Picker("Select default wallet", + Section(NSLocalizedString("Wallet Selector", comment: "Section title for selection of wallet.")) { + Toggle(NSLocalizedString("Show wallet selector", comment: "Toggle to show or hide selection of wallet."), isOn: $user_settings.show_wallet_selector).toggleStyle(.switch) + Picker(NSLocalizedString("Select default wallet", comment: "Prompt selection of user's default wallet"), selection: $user_settings.default_wallet) { ForEach(Wallet.allCases, id: \.self) { wallet in Text(wallet.model.displayName) @@ -114,32 +114,32 @@ struct ConfigView: View { } } - Section("Clear Cache") { - Button("Clear") { + Section(NSLocalizedString("Clear Cache", comment: "Section title for clearing cached data.")) { + Button(NSLocalizedString("Clear", comment: "Button for clearing cached data.")) { KingfisherManager.shared.cache.clearMemoryCache() KingfisherManager.shared.cache.clearDiskCache() KingfisherManager.shared.cache.cleanExpiredDiskCache() } } - Section("Reset") { - Button("Logout") { + Section(NSLocalizedString("Reset", comment: "Section title for resetting the user")) { + Button(NSLocalizedString("Logout", comment: "Button to logout the user.")) { confirm_logout = true } } } } - .navigationTitle("Settings") + .navigationTitle(NSLocalizedString("Settings", comment: "Navigation title for Settings view.")) .navigationBarTitleDisplayMode(.large) - .alert("Logout", isPresented: $confirm_logout) { - Button("Cancel") { + .alert(NSLocalizedString("Logout", comment: "Alert for logging out the user."), isPresented: $confirm_logout) { + Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user.")) { confirm_logout = false } - Button("Logout") { + Button(NSLocalizedString("Logout", comment: "Button for logging out the user.")) { notify(.logout, ()) } } message: { - Text("Make sure your nsec account key is saved before you logout or you will lose access to this account") + Text("Make sure your nsec account key is saved before you logout or you will lose access to this account", comment: "Reminder message in alert to get customer to verify that their private security account key is saved saved before logging out.") } .sheet(isPresented: $show_add_relay) { AddRelayView(show_add_relay: $show_add_relay, relay: $new_relay) { m_relay in diff --git a/damus/Views/CreateAccountView.swift b/damus/Views/CreateAccountView.swift @@ -35,14 +35,14 @@ struct CreateAccountView: View { HStack(alignment: .top) { VStack { - Text(" ") + Text(" ", comment: "Blank space to separate profile picture from profile editor form.") .foregroundColor(.white) } VStack { SignupForm { FormLabel(NSLocalizedString("Username", comment: "Label to prompt username entry.")) HStack(spacing: 0.0) { - Text("@") + Text("@", comment: "Prefix character to username.") .foregroundColor(.white) .padding(.leading, -25.0) @@ -151,7 +151,7 @@ func FormLabel(_ title: String, optional: Bool = false) -> some View { .bold() .foregroundColor(.white) if optional { - Text("optional") + Text("optional", comment: "Label indicating that a form input is optional.") .font(.callout) .foregroundColor(.white.opacity(0.5)) } diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift @@ -142,14 +142,14 @@ struct DMChatView: View { Footer } - Text("Send a message to start the conversation...") + Text("Send a message to start the conversation...", comment: "Text prompt for user to send a message to the other user.") .lineLimit(nil) .multilineTextAlignment(.center) .padding(.horizontal, 40) .opacity(((dms.events.count == 0) ? 1.0 : 0.0)) .foregroundColor(.gray) } - .navigationTitle("DM") + .navigationTitle(NSLocalizedString("DM", comment: "Navigation title for DM view, which is the English abbreviation for Direct Message.")) .toolbar { Header } } } diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift @@ -53,7 +53,7 @@ struct DirectMessagesView: View { var body: some View { MainContent - .navigationTitle("Encrypted DMs") + .navigationTitle(NSLocalizedString("Encrypted DMs", comment: "Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message.")) } } diff --git a/damus/Views/EditMetadataView.swift b/damus/Views/EditMetadataView.swift @@ -107,32 +107,32 @@ struct EditMetadataView: View { Spacer() } Form { - Section("Your Name") { + Section(NSLocalizedString("Your Name", comment: "Label for Your Name section of user profile form.")) { TextField("Satoshi Nakamoto", text: $display_name) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) } - Section("Username") { + Section(NSLocalizedString("Username", comment: "Label for Username section of user profile form.")) { TextField("satoshi", text: $name) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) } - Section ("Profile Picture") { - TextField("https://example.com/pic.jpg", text: $picture) + Section (NSLocalizedString("Profile Picture", comment: "Label for Profile Picture section of user profile form.")) { + TextField(NSLocalizedString("https://example.com/pic.jpg", comment: "Placeholder example text for profile picture URL."), text: $picture) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) } - Section("Website") { - TextField("https://jb55.com", text: $website) + Section(NSLocalizedString("Website", comment: "Label for Website section of user profile form.")) { + TextField(NSLocalizedString("https://jb55.com", comment: "Placeholder example text for website URL for user profile."), text: $website) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) } - Section("About Me") { + Section(NSLocalizedString("About Me", comment: "Label for About Me section of user profile form.")) { let placeholder = NSLocalizedString("Absolute Boss", comment: "Placeholder text for About Me description.") ZStack(alignment: .topLeading) { TextEditor(text: $about) @@ -146,18 +146,18 @@ struct EditMetadataView: View { } } - Section("Bitcoin Lightning Tips") { - TextField("Lightning Address or LNURL", text: $ln) + Section(NSLocalizedString("Bitcoin Lightning Tips", comment: "Label for Bitcoin Lightning Tips section of user profile form.")) { + TextField(NSLocalizedString("Lightning Address or LNURL", comment: "Placeholder text for entry of Lightning Address or LNURL."), text: $ln) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) } Section(content: { - TextField("jb55@jb55.com", text: $nip05) + TextField(NSLocalizedString("jb55@jb55.com", comment: "Placeholder example text for identifier used for NIP-05 verification."), text: $nip05) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) }, header: { - Text("NIP-05 Verification") + Text("NIP-05 Verification", comment: "Label for NIP-05 Verification section of user profile form.") }, footer: { if let parts = nip05_parts { Text("'\(parts.username)' at '\(parts.host)' will be used for verification", comment: "Description of how the nip05 identifier would be used for verification.") @@ -166,13 +166,13 @@ struct EditMetadataView: View { } }) - Button("Save") { + Button(NSLocalizedString("Save", comment: "Button for saving profile.")) { save() dismiss() } } } - .navigationTitle("Edit Profile") + .navigationTitle(NSLocalizedString("Edit Profile", comment: "Title of navigation view for Edit Profile.")) } } diff --git a/damus/Views/Empty Views/EmptyTimelineView.swift b/damus/Views/Empty Views/EmptyTimelineView.swift @@ -13,7 +13,7 @@ struct EmptyTimelineView: View { Image(systemName: "tray.fill") .font(.system(size: 35)) .padding() - Text("Nothing to see here. Check back later!") + Text("Nothing to see here. Check back later!", comment: "Indicates that there are no notes in the timeline to view.") .multilineTextAlignment(.center) .font(.callout.weight(.medium)) } diff --git a/damus/Views/EventActionBar.swift b/damus/Views/EventActionBar.swift @@ -102,15 +102,15 @@ struct EventActionBar: View { } } } - .alert("Boost", isPresented: $confirm_boost) { + .alert(NSLocalizedString("Boost", comment: "Title of alert for confirming to boost a post."), isPresented: $confirm_boost) { Button("Cancel") { confirm_boost = false } - Button("Boost") { + Button(NSLocalizedString("Boost", comment: "Button to confirm boosting a post.")) { send_boost() } } message: { - Text("Are you sure you want to boost this post?") + Text("Are you sure you want to boost this post?", comment: "Alert message to ask if user wants to boost a post.") } .onReceive(handle_notify(.liked)) { n in let liked = n.object as! Counted @@ -169,7 +169,7 @@ struct LikeButton: View { var body: some View { Button(action: action) { if liked { - Text("馃") + Text("馃", comment: "Button with emoji to like an event.") } else { Image("shaka") .renderingMode(.template) diff --git a/damus/Views/EventDetailView.swift b/damus/Views/EventDetailView.swift @@ -59,7 +59,7 @@ struct EventDetailView: View { Group { switch cev { case .collapsed(let c): - Text("路路路 \(c.count) other notes 路路路") + Text(String(format: NSLocalizedString("collapsed_event_view_other_notes", comment: "Text to indicate that the thread was collapsed and that there are other notes to view if tapped."), c.count)) .padding([.top,.bottom], 8) .font(.footnote) .foregroundColor(.gray) @@ -114,7 +114,7 @@ struct EventDetailView: View { scroll_after_load(thread: thread, proxy: proxy) } } - .navigationBarTitle("Thread") + .navigationBarTitle(NSLocalizedString("Thread", comment: "Navigation bar title for note thread.")) } diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift @@ -179,7 +179,7 @@ struct EventView: View { ProfileName(pubkey: event.pubkey, profile: prof, damus: damus, show_friend_confirmed: true) .font(.footnote.weight(.bold)) .foregroundColor(Color.gray) - Text("Boosted") + Text("Boosted", comment: "Text indicating that the post was boosted (i.e. re-shared).") .font(.footnote.weight(.bold)) .foregroundColor(Color.gray) } @@ -308,7 +308,7 @@ extension View { Button { UIPasteboard.general.string = bech32_pubkey } label: { - Label("Copy Account ID", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy Account ID", comment: "Context menu option for copying the ID of the account that created the note."), systemImage: "doc.on.doc") } } } @@ -318,31 +318,31 @@ extension View { Button { UIPasteboard.general.string = event.get_content(privkey) } label: { - Label("Copy Text", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy Text", comment: "Context menu option for copying the text from an note."), systemImage: "doc.on.doc") } Button { UIPasteboard.general.string = bech32_pubkey(pubkey) ?? pubkey } label: { - Label("Copy User ID", systemImage: "tag") + Label(NSLocalizedString("Copy User ID", comment: "Context menu option for copying the ID of the user who created the note."), systemImage: "tag") } Button { UIPasteboard.general.string = bech32_note_id(event.id) ?? event.id } label: { - Label("Copy Note ID", systemImage: "tag") + Label(NSLocalizedString("Copy Note ID", comment: "Context menu option for copying the ID of the note."), systemImage: "tag") } Button { UIPasteboard.general.string = event_to_json(ev: event) } label: { - Label("Copy Note JSON", systemImage: "note") + Label(NSLocalizedString("Copy Note JSON", comment: "Context menu option for copying the JSON text from the note."), systemImage: "note") } Button { NotificationCenter.default.post(name: .broadcast_event, object: event) } label: { - Label("Broadcast", systemImage: "globe") + Label(NSLocalizedString("Broadcast", comment: "Context menu option for broadcasting the user's note to all of the user's connected relay servers."), systemImage: "globe") } } diff --git a/damus/Views/FollowButtonView.swift b/damus/Views/FollowButtonView.swift @@ -70,16 +70,16 @@ struct FollowButtonPreviews: View { let target: FollowTarget = .pubkey("") var body: some View { VStack { - Text("Unfollows") + Text("Unfollows", comment: "Text to indicate that the button next to it is in a state that will unfollow a profile when tapped.") FollowButtonView(target: target, follow_state: .unfollows) - Text("Following") + Text("Following", comment: "Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.") FollowButtonView(target: target, follow_state: .following) - Text("Follows") + Text("Follows", comment: "Text to indicate that button next to it is in a state that will follow a profile when tapped.") FollowButtonView(target: target, follow_state: .follows) - Text("Unfollowing") + Text("Unfollowing", comment: "Text to indicate that the button next to it is in a state that indicates that it is in the process of unfollowing a profile.") FollowButtonView(target: target, follow_state: .unfollowing) } } diff --git a/damus/Views/FollowingView.swift b/damus/Views/FollowingView.swift @@ -57,7 +57,7 @@ struct FollowersView: View { } .padding() } - .navigationBarTitle("\(Profile.displayName(profile: profile, pubkey: whos))'s Followers") + .navigationBarTitle(NSLocalizedString("\(Profile.displayName(profile: profile, pubkey: whos))'s Followers", comment: "Navigation bar title for view that shows who is following a user.")) .onAppear { followers.subscribe() } @@ -91,7 +91,7 @@ struct FollowingView: View { .onDisappear { following.unsubscribe() } - .navigationBarTitle("\(who) following") + .navigationBarTitle(NSLocalizedString("\(who) following", comment: "Navigation bar title for view that shows who a user is following.")) } } diff --git a/damus/Views/LoginView.swift b/damus/Views/LoginView.swift @@ -122,21 +122,21 @@ struct LoginView: View { ZStack(alignment: .top) { DamusGradient() VStack { - Text("Login") + Text("Login", comment: "Title of view to log into an account.") .foregroundColor(.white) .font(.title) .padding() - Text("Enter your account key to login:") + Text("Enter your account key to login:", comment: "Prompt for user to enter an account key to login.") .foregroundColor(.white) .padding() - KeyInput("nsec1...", key: $key) + KeyInput(NSLocalizedString("nsec1...", comment: "Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key."), key: $key) let parsed = parse_key(key) if parsed?.is_hex ?? false { - Text("This is an old-style nostr key. We're not sure if it's a pubkey or private key. Please toggle the button below if this a public key.") + Text("This is an old-style nostr key. We're not sure if it's a pubkey or private key. Please toggle the button below if this a public key.", comment: "Warning that the inputted account key for login is an old-style and asking user to verify if it is a public key.") .font(.subheadline.bold()) .foregroundColor(.white) PubkeySwitch(isOn: $is_pubkey) @@ -150,15 +150,15 @@ struct LoginView: View { } if parsed?.is_pub ?? false { - Text("This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.") + Text("This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.", comment: "Warning that the inputted account key is a public key and the result of what happens because of it.") .foregroundColor(.white) .padding() } if let p = parsed { - DamusWhiteButton("Login") { + DamusWhiteButton(NSLocalizedString("Login", comment: "Button to log into account.")) { if !process_login(p, is_pubkey: self.is_pubkey) { - self.error = "Invalid key" + self.error = NSLocalizedString("Invalid key", comment: "Error message indicating that an invalid account key was entered for login.") } } } @@ -175,7 +175,7 @@ struct PubkeySwitch: View { var body: some View { HStack { Toggle(isOn: $isOn) { - Text("Public Key?") + Text("Public Key?", comment: "Prompt to ask user if the key they entered is a public key.") .foregroundColor(.white) } } diff --git a/damus/Views/MentionView.swift b/damus/Views/MentionView.swift @@ -17,7 +17,7 @@ struct MentionView: View { let pk = bech32_pubkey(mention.ref.ref_id) ?? mention.ref.ref_id PubkeyView(pubkey: pk, relay: mention.ref.relay_id) case .event: - Text("< e >") + Text("< e >", comment: "Placeholder for event mention.") //EventBlockView(pubkey: mention.ref.ref_id, relay: mention.ref.relay_id) } } diff --git a/damus/Views/PostView.swift b/damus/Views/PostView.swift @@ -55,7 +55,7 @@ struct PostView: View { var body: some View { VStack { HStack { - Button("Cancel") { + Button(NSLocalizedString("Cancel", comment: "Button to cancel out of posting a note.")) { self.cancel() } .foregroundColor(.primary) @@ -63,7 +63,7 @@ struct PostView: View { Spacer() if !is_post_empty { - Button("Post") { + Button(NSLocalizedString("Post", comment: "Button to post a note.")) { self.send_post() } } diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift @@ -81,7 +81,7 @@ struct EditButton: View { var body: some View { NavigationLink(destination: EditMetadataView(damus_state: damus_state)) { - Text("Edit") + Text("Edit", comment: "Button to edit user's profile.") .frame(height: 30) .padding(.horizontal,25) .font(.caption.weight(.bold)) @@ -153,7 +153,7 @@ struct ProfileView: View { Button { UIPasteboard.general.string = profile.lnurl ?? "" } label: { - Label("Copy LNUrl", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy LNURL", comment: "Context menu option for copying a user's Lightning URL."), systemImage: "doc.on.doc") } } @@ -260,11 +260,7 @@ struct ProfileView: View { let following_model = FollowingModel(damus_state: damus_state, contacts: contacts) NavigationLink(destination: FollowingView(damus_state: damus_state, following: following_model, whos: profile.pubkey)) { HStack { - Text("\(profile.following)") - .font(.subheadline.weight(.medium)) - Text("Following") - .font(.subheadline) - .foregroundColor(.gray) + Text("\(Text("\(profile.following)", comment: "Number of profiles a user is following.").font(.subheadline.weight(.medium))) \(Text("Following", comment: "Part of a larger sentence to describe how many profiles a user is following.").font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.") } } .buttonStyle(PlainButtonStyle()) @@ -287,11 +283,7 @@ struct ProfileView: View { if let relays = profile.relays { NavigationLink(destination: UserRelaysView(state: damus_state, pubkey: profile.pubkey, relays: Array(relays.keys).sorted())) { - Text("\(relays.keys.count)") - .font(.subheadline.weight(.medium)) - Text("Relays") - .font(.subheadline) - .foregroundColor(.gray) + Text("\(Text("\(relays.keys.count)", comment: "Number of relay servers a user is connected.").font(.subheadline.weight(.medium))) \(Text("Relays", comment: "Part of a larger sentence to describe how many relay servers a user is connected.").font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many relay servers a user is connected. In source English, the first variable is the number of relay servers, and the second variable is 'Relays'.") } .buttonStyle(PlainButtonStyle()) } @@ -307,13 +299,12 @@ struct ProfileView: View { HStack { if followers.count_display == "?" { Image(systemName: "square.and.arrow.down") + Text("Followers", comment: "Label describing followers of a user.") + .font(.subheadline) + .foregroundColor(.gray) } else { - Text("\(followers.count_display)") - .font(.subheadline.weight(.medium)) + Text("\(Text("\(followers.count_display)", comment: "Number of people following a user.").font(.subheadline.weight(.medium))) \(Text("Followers", comment: "Part of a larger sentence to describe how many people are following a user.").font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many people are following a user. In source English, the first variable is the number of followers, and the second variable is 'Followers'.") } - Text("Followers") - .font(.subheadline) - .foregroundColor(.gray) } } @@ -405,7 +396,7 @@ struct KeyView: View { isCopied = false } } label: { - Label("Public Key", systemImage: "key.fill") + Label(NSLocalizedString("Public Key", comment: "Label indicating that the text is a user's public account key."), systemImage: "key.fill") .font(.custom("key", size: 12.0)) .labelStyle(IconOnlyLabelStyle()) .foregroundStyle(hex_to_rgb(pubkey)) @@ -428,7 +419,7 @@ struct KeyView: View { } } label: { Label { - Text("Public key") + Text("Public key", comment: "Label indicating that the text is a user's public account key.") } icon: { Image("ic-copy") .contentShape(Rectangle()) @@ -441,7 +432,7 @@ struct KeyView: View { HStack { Image("ic-tick") .frame(width: 20, height: 20) - Text("Copied") + Text(NSLocalizedString("Copied", comment: "Label indicating that a user's key was copied.")) .font(.footnote) .foregroundColor(Color("DamusGreen")) } diff --git a/damus/Views/RecommendedRelayView.swift b/damus/Views/RecommendedRelayView.swift @@ -30,7 +30,7 @@ struct RecommendedRelayView: View { Spacer() if let ev = damus.contacts.event, add_button { if let privkey = damus.keypair.privkey { - Button("Add") { + Button(NSLocalizedString("Add", comment: "Button to add recommended relay server.")) { guard let ev = add_relay(ev: ev, privkey: privkey, current_relays: damus.pool.descriptors, relay: relay, info: .rw) else { return } diff --git a/damus/Views/RelayView.swift b/damus/Views/RelayView.swift @@ -60,7 +60,7 @@ struct RelayView: View { Button { UIPasteboard.general.setValue(relay, forPasteboardType: "public.plain-text") } label: { - Label("Copy", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy", comment: "Button to copy a relay server address."), systemImage: "doc.on.doc") } } @@ -78,7 +78,7 @@ struct RelayView: View { process_contact_event(pool: state.pool, contacts: state.contacts, pubkey: state.pubkey, ev: new_ev) state.pool.send(.event(new_ev)) } label: { - Label("Delete", systemImage: "trash") + Label(NSLocalizedString("Delete", comment: "Button to delete a relay server that the user connects to."), systemImage: "trash") } .tint(.red) } diff --git a/damus/Views/ReplyView.swift b/damus/Views/ReplyView.swift @@ -20,7 +20,7 @@ struct ReplyView: View { var body: some View { VStack { - Text("Replying to:") + Text("Replying to:", comment: "Indicating that the user is replying to the following listed people.") HStack(alignment: .top) { let names = all_referenced_pubkeys(replying_to) .map { pubkey in diff --git a/damus/Views/SaveKeysView.swift b/damus/Views/SaveKeysView.swift @@ -21,21 +21,21 @@ struct SaveKeysView: View { DamusGradient() VStack(alignment: .center) { - Text("Welcome, \(account.rendered_name)!") + Text("Welcome, \(account.rendered_name)!", comment: "Text to welcome user.") .font(.title.bold()) .foregroundColor(.white) .padding(.bottom, 10) - Text("Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus.") + Text("Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus.", comment: "Reminder to user that they should save their account information.") .foregroundColor(.white) .padding(.bottom, 10) - Text("Public Key") + Text("Public Key", comment: "Label to indicate that text below is the user's public key used by others to uniquely refer to the user.") .font(.title2.bold()) .foregroundColor(.white) .padding(.bottom, 10) - Text("This is your account ID, you can give this to your friends so that they can follow you. Click to copy.") + Text("This is your account ID, you can give this to your friends so that they can follow you. Click to copy.", comment: "Label to describe that a public key is the user's account ID and what they can do with it.") .foregroundColor(.white) .padding(.bottom, 10) @@ -43,12 +43,12 @@ struct SaveKeysView: View { .padding(.bottom, 10) if pub_copied { - Text("Private Key") + Text("Private Key", comment: "Label to indicate that the text below is the user's private key used by only the user themself as a secret to login to access their account.") .font(.title2.bold()) .foregroundColor(.white) .padding(.bottom, 10) - Text("This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!") + Text("This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!", comment: "Label to describe that a private key is the user's secret account key and what they should do with it.") .foregroundColor(.white) .padding(.bottom, 10) @@ -61,7 +61,7 @@ struct SaveKeysView: View { ProgressView() .progressViewStyle(.circular) } else if let err = error { - Text("Error: \(err)") + Text("Error: \(err)", comment: "Error message indicating why saving keys failed.") .foregroundColor(.red) DamusWhiteButton("Retry") { complete_account_creation(account) diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift @@ -16,12 +16,12 @@ struct SearchHomeView: View { var SearchInput: some View { ZStack(alignment: .leading) { HStack{ - TextField("Search...", text: $search) + TextField(NSLocalizedString("Search...", comment: "Placeholder text to prompt entry of search query."), text: $search) .padding(8) .padding(.leading, 35) .autocorrectionDisabled(true) .textInputAutocapitalization(.never) - Text("Cancel") + Text("Cancel", comment: "Cancel out of search view.") .foregroundColor(.blue) .padding(EdgeInsets(top: 0.0, leading: 0.0, bottom: 0.0, trailing: 10.0)) .opacity((search == "") ? 0.0 : 1.0) diff --git a/damus/Views/SearchResultsView.swift b/damus/Views/SearchResultsView.swift @@ -38,7 +38,7 @@ struct SearchResultsView: View { let search_model = SearchModel(pool: damus_state.pool, search: .filter_hashtag([ht])) let dst = SearchView(appstate: damus_state, search: search_model) NavigationLink(destination: dst) { - Text("Search hashtag: #\(ht)") + Text("Search hashtag: #\(ht)", comment: "Navigation link to search hashtag.") } case .profile(let prof): let decoded = try? bech32_decode(prof) @@ -47,7 +47,7 @@ struct SearchResultsView: View { let f = FollowersModel(damus_state: damus_state, target: prof) let dst = ProfileView(damus_state: damus_state, profile: prof_model, followers: f) NavigationLink(destination: dst) { - Text("Goto profile \(prof)") + Text("Goto profile \(prof)", comment: "Navigation link to go to profile.") } case .hex(let h): let prof_model = ProfileModel(pubkey: h, damus: damus_state) @@ -60,10 +60,10 @@ struct SearchResultsView: View { VStack(spacing: 50) { NavigationLink(destination: prof_view) { - Text("Goto profile \(h)") + Text("Goto profile \(h)", comment: "Navigation link to go to profile referenced by hex code.") } NavigationLink(destination: ev_view) { - Text("Goto post \(h)") + Text("Goto post \(h)", comment: "Navigation link to go to post referenced by hex code.") } } case .note(let nid): @@ -74,10 +74,10 @@ struct SearchResultsView: View { event_id: hex ) NavigationLink(destination: ev_view) { - Text("Goto post \(nid)") + Text("Goto post \(nid)", comment: "Navigation link to go to post referenced by note ID.") } case .none: - Text("none") + Text("none", comment: "No search results.") } }.padding(.horizontal) } diff --git a/damus/Views/SelectWalletView.swift b/damus/Views/SelectWalletView.swift @@ -20,7 +20,7 @@ struct SelectWalletView: View { var body: some View { NavigationView { Form { - Section("Copy invoice") { + Section(NSLocalizedString("Copy invoice", comment: "Title of section for copying a Lightning invoice identifier.")) { HStack { Text(invoice).font(.body) .lineLimit(2) @@ -35,14 +35,14 @@ struct SelectWalletView: View { generator.impactOccurred() } } - Section("Select a lightning wallet"){ + Section(NSLocalizedString("Select a Lightning wallet", comment: "Title of section for selecting a Lightning wallet to pay a Lightning invoice.")) { List{ Button() { let wallet_model = user_settings.default_wallet.model open_with_wallet(wallet: wallet_model, invoice: invoice) } label: { HStack { - Text("Default Wallet").font(.body).foregroundColor(.blue) + Text("Default Wallet", comment: "Button to pay a Lightning invoice with the user's default Lightning wallet.").font(.body).foregroundColor(.blue) } }.buttonStyle(.plain) List($allWalletModels) { $wallet in @@ -59,10 +59,10 @@ struct SelectWalletView: View { } }.padding(.vertical, 2.5) } - }.navigationBarTitle(Text("Pay the lightning invoice"), displayMode: .inline).navigationBarItems(trailing: Button(action: { + }.navigationBarTitle(Text("Pay the Lightning invoice", comment: "Navigation bar title for view to pay Lightning invoice."), displayMode: .inline).navigationBarItems(trailing: Button(action: { self.showingSelectWallet = false }) { - Text("Done").bold() + Text("Done", comment: "Button to dismiss wallet selection view for paying Lightning invoice.").bold() }) } } diff --git a/damus/Views/SetupView.swift b/damus/Views/SetupView.swift @@ -53,7 +53,7 @@ struct SetupView: View { .resizable() .frame(width: 128.0, height: 128.0, alignment: .center) .padding([.top], 20.0) - Text("Damus") + Text("Damus", comment: "Name of the app, shown on the first screen when user is not logged in.") .font(Font.custom("Nunito", size: 50.0)) .kerning(-2) .foregroundColor(.white) diff --git a/damus/Views/ThreadV2View.swift b/damus/Views/ThreadV2View.swift @@ -310,7 +310,7 @@ struct ThreadV2View: View { } } }.padding() - }.navigationBarTitle("Thread") + }.navigationBarTitle(NSLocalizedString("Thread", comment: "Navigation bar title for note thread.")) } } } diff --git a/damus/Views/ThreadView.swift b/damus/Views/ThreadView.swift @@ -21,11 +21,11 @@ struct ThreadView: View { Group { if is_chatroom { ChatroomView(damus: damus) - .navigationBarTitle(metadata?.name ?? "Chat") + .navigationBarTitle(metadata?.name ?? NSLocalizedString("Chat", comment: "Navigation bar title for Chatroom view.")) .environmentObject(thread) } else { EventDetailView(damus: damus, thread: thread) - .navigationBarTitle(metadata?.name ?? "Thread") + .navigationBarTitle(metadata?.name ?? NSLocalizedString("Thread", comment: "Navigation bar title for threaded event detail view.")) .environmentObject(thread) } diff --git a/damus/en.lproj/Localizable.stringsdict b/damus/en.lproj/Localizable.stringsdict @@ -5,8 +5,8 @@ <key>replying_to_one_and_others</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Replying to %@%#@others@</string> - <key>others</key> + <string>Replying to %@%#@OTHERS@</string> + <key>OTHERS</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> @@ -23,8 +23,8 @@ <key>replying_to_two_and_others</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Replying to %@, %@%#@others@</string> - <key>others</key> + <string>Replying to %@, %@%#@OTHERS@</string> + <key>OTHERS</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> @@ -38,5 +38,23 @@ <string> &amp; %d others</string> </dict> </dict> + <key>collapsed_event_view_other_notes</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>路路路 %#@NOTES@ 路路路</string> + <key>NOTES</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>zero</key> + <string>0 other notes</string> + <key>one</key> + <string>1 other note</string> + <key>other</key> + <string>%d other notes</string> + </dict> + </dict> </dict> </plist>