damus

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

commit 9fd2f519719e9eb6db46a719e936669ad88bac9f
parent 386bae64ca77eaa509ff5afbd962314a316132ca
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 26 Feb 2023 15:48:55 -0800

Merge remote-tracking branch 'tyiu/tyiu/translations'

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 6++++++
Mdamus/Util/LocalizationUtil.swift | 14++++++--------
Mdamus/Views/ActionBar/EventDetailBar.swift | 9+++------
Mdamus/Views/Events/EventMenu.swift | 6+++---
Mdamus/Views/Notifications/EventGroupView.swift | 95++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mdamus/Views/ProfileView.swift | 9+++------
Mdamus/Views/RelayFilterView.swift | 2+-
Mdamus/Views/SaveKeysView.swift | 2+-
Mdamus/Views/Zaps/CustomizeZapView.swift | 26+++++++++++++-------------
Mdamus/ar.lproj/Localizable.strings | 0
Mdamus/cs.lproj/Localizable.strings | 0
Mdamus/de.lproj/Localizable.strings | 0
Mdamus/el-GR.lproj/Localizable.strings | 0
Adamus/en-US.lproj/Localizable.strings | 0
Mdamus/en-US.lproj/Localizable.stringsdict | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdamus/en-US.xcloc/Localized Contents/en-US.xliff | 329++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mdamus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.strings | 0
Mdamus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.stringsdict | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdamus/es-419.lproj/Localizable.strings | 0
Adamus/fa.lproj/InfoPlist.strings | 0
Adamus/fa.lproj/Localizable.strings | 0
Mdamus/ja.lproj/Localizable.strings | 0
Mdamus/nl.lproj/Localizable.strings | 0
Mdamus/pl-PL.lproj/Localizable.strings | 0
Adamus/uk.lproj/InfoPlist.strings | 0
Mdamus/zh-CN.lproj/Localizable.strings | 0
AdamusTests/EventGroupViewTests.swift | 42++++++++++++++++++++++++++++++++++++++++++
Mdevtools/export-source-translation.sh | 2+-
Mtransifex.yml | 35+++++++++++++++++++----------------
29 files changed, 756 insertions(+), 109 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 3A3040EF29A8FEE9008A0F29 /* EventDetailBarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3040EE29A8FEE9008A0F29 /* EventDetailBarTests.swift */; }; 3A3040F129A8FF97008A0F29 /* LocalizationUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3040F029A8FF97008A0F29 /* LocalizationUtil.swift */; }; 3A3040F329A91366008A0F29 /* ProfileViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3040F229A91366008A0F29 /* ProfileViewTests.swift */; }; + 3A30410129AB12AA008A0F29 /* EventGroupViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A30410029AB12AA008A0F29 /* EventGroupViewTests.swift */; }; 3A4325A82961E11400BFCD9D /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */; }; 3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA247FC297E3CFF0090C62D /* RepostsModel.swift */; }; 3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA247FE297E3D900090C62D /* RepostsView.swift */; }; @@ -282,6 +283,8 @@ 3A3040FC29A91F31008A0F29 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; 3A3040FD29A91F31008A0F29 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-TW"; path = "zh-TW.lproj/Localizable.stringsdict"; sourceTree = "<group>"; }; 3A3040FE29A91F31008A0F29 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Localizable.strings"; sourceTree = "<group>"; }; + 3A3040FF29AB02D1008A0F29 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Localizable.strings"; sourceTree = "<group>"; }; + 3A30410029AB12AA008A0F29 /* EventGroupViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventGroupViewTests.swift; sourceTree = "<group>"; }; 3A41E559299D52BE001FA465 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 3A41E55A299D52BE001FA465 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = "<group>"; }; 3A41E55B299D52BE001FA465 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = id; path = id.lproj/Localizable.stringsdict; sourceTree = "<group>"; }; @@ -1037,6 +1040,7 @@ 3A3040EC29A5CB86008A0F29 /* ReplyDescriptionTests.swift */, 3A3040EE29A8FEE9008A0F29 /* EventDetailBarTests.swift */, 3A3040F229A91366008A0F29 /* ProfileViewTests.swift */, + 3A30410029AB12AA008A0F29 /* EventGroupViewTests.swift */, ); path = damusTests; sourceTree = "<group>"; @@ -1498,6 +1502,7 @@ buildActionMask = 2147483647; files = ( 3A3040ED29A5CB86008A0F29 /* ReplyDescriptionTests.swift in Sources */, + 3A30410129AB12AA008A0F29 /* EventGroupViewTests.swift in Sources */, 3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */, DD597CBD2963D85A00C64D32 /* MarkdownTests.swift in Sources */, 3A3040EF29A8FEE9008A0F29 /* EventDetailBarTests.swift in Sources */, @@ -1612,6 +1617,7 @@ 3A827A19299FC69D00C4D171 /* ru */, 3A3040FA29A91EFC008A0F29 /* zh-HK */, 3A3040FE29A91F31008A0F29 /* zh-TW */, + 3A3040FF29AB02D1008A0F29 /* en-US */, ); name = Localizable.strings; sourceTree = "<group>"; diff --git a/damus/Util/LocalizationUtil.swift b/damus/Util/LocalizationUtil.swift @@ -7,13 +7,11 @@ import Foundation -func bundleForLocale(locale: Locale) -> Bundle { - let path = Bundle.main.path(forResource: locale.identifier, ofType: "lproj") - return path != nil ? (Bundle(path: path!) ?? Bundle.main) : Bundle.main -} +func bundleForLocale(locale: Locale?) -> Bundle { + if locale == nil { + return Bundle.main + } -func formatInt(_ int: Int) -> String { - let numberFormatter = NumberFormatter() - numberFormatter.numberStyle = .decimal - return numberFormatter.string(from: NSNumber(integerLiteral: int)) ?? "\(int)" + let path = Bundle.main.path(forResource: locale!.identifier, ofType: "lproj") + return path != nil ? (Bundle(path: path!) ?? Bundle.main) : Bundle.main } diff --git a/damus/Views/ActionBar/EventDetailBar.swift b/damus/Views/ActionBar/EventDetailBar.swift @@ -26,18 +26,16 @@ struct EventDetailBar: View { HStack { if bar.boosts > 0 { NavigationLink(destination: RepostsView(damus_state: state, model: RepostsModel(state: state, target: target))) { - let count = Text(verbatim: "\(formatInt(bar.boosts))").font(.body.bold()) let noun = Text(verbatim: "\(repostsCountString(bar.boosts))").foregroundColor(.gray) - Text("\(count) \(noun)", comment: "Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.") + Text("\(Text("\(bar.boosts)").font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.") } .buttonStyle(PlainButtonStyle()) } if bar.likes > 0 { NavigationLink(destination: ReactionsView(damus_state: state, model: ReactionsModel(state: state, target: target))) { - let count = Text(verbatim: "\(formatInt(bar.likes))").font(.body.bold()) let noun = Text(verbatim: "\(reactionsCountString(bar.likes))").foregroundColor(.gray) - Text("\(count) \(noun)", comment: "Sentence composed of 2 variables to describe how many reactions there are on a post. In source English, the first variable is the number of reactions, and the second variable is 'Reaction' or 'Reactions'.") + Text("\(Text("\(bar.likes)").font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many reactions there are on a post. In source English, the first variable is the number of reactions, and the second variable is 'Reaction' or 'Reactions'.") } .buttonStyle(PlainButtonStyle()) } @@ -45,9 +43,8 @@ struct EventDetailBar: View { if bar.zaps > 0 { let dst = ZapsView(state: state, target: .note(id: target, author: target_pk)) NavigationLink(destination: dst) { - let count = Text(verbatim: "\(formatInt(bar.zaps))").font(.body.bold()) let noun = Text(verbatim: "\(zapsCountString(bar.zaps))").foregroundColor(.gray) - Text("\(count) \(noun)", comment: "Sentence composed of 2 variables to describe how many zap payments there are on a post. In source English, the first variable is the number of zap payments, and the second variable is 'Zap' or 'Zaps'.") + Text("\(Text("\(bar.zaps)").font(.body.bold())) \(noun)", comment: "Sentence composed of 2 variables to describe how many zap payments there are on a post. In source English, the first variable is the number of zap payments, and the second variable is 'Zap' or 'Zaps'.") } .buttonStyle(PlainButtonStyle()) } diff --git a/damus/Views/Events/EventMenu.swift b/damus/Views/Events/EventMenu.swift @@ -47,9 +47,9 @@ struct EventMenuContext: View { notify(.update_bookmarks, event) } label: { let imageName = isBookmarked ? "bookmark.fill" : "bookmark" - let unBookmarkString = NSLocalizedString("Un-Bookmark", comment: "Context menu option for un-bookmarking a note") - let bookmarkString = NSLocalizedString("Bookmark", comment: "Context menu option for bookmarking a note") - Label(isBookmarked ? unBookmarkString : bookmarkString, systemImage: imageName) + let removeBookmarkString = NSLocalizedString("Remove Bookmark", comment: "Context menu option for removing a note bookmark.") + let addBookmarkString = NSLocalizedString("Add Bookmark", comment: "Context menu option for adding a note bookmark.") + Label(isBookmarked ? removeBookmarkString : addBookmarkString, systemImage: imageName) } .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { diff --git a/damus/Views/Notifications/EventGroupView.swift b/damus/Views/Notifications/EventGroupView.swift @@ -46,62 +46,86 @@ func determine_reacting_to(our_pubkey: String, ev: NostrEvent?) -> ReactingTo { return .tagged_in } -func determine_reacting_to_text(_ r: ReactingTo) -> String { - switch r { - case .tagged_in: - return "a post you were tagged in" - case .your_post: - return "your post" - case .your_profile: - return "your profile" - } -} - func event_author_name(profiles: Profiles, _ ev: NostrEvent) -> String { let alice_pk = ev.pubkey let alice_prof = profiles.lookup(id: alice_pk) return Profile.displayName(profile: alice_prof, pubkey: alice_pk) } -func reacting_to_text(profiles: Profiles, our_pubkey: String, group: EventGroupType, ev: NostrEvent?) -> String { +/** + Returns a notification string describing user actions in response to an event group type. + + The localization keys read by this function are the following (although some keys may not actually be used in practice): + + "??" - returned when there are no events associated with the specified event group type. + + "reacted_tagged_in_1" - returned when 1 reaction occurred to a post that the current user was tagged in + "reacted_tagged_in_2" - returned when 2 reactions occurred to a post that the current user was tagged in + "reacted_tagged_in_3" - returned when 3 or more reactions occurred to a post that the current user was tagged in + "reacted_your_post_1" - returned when 1 reaction occurred to the current user's post + "reacted_your_post_2" - returned when 2 reactions occurred to the current user's post + "reacted_your_post_3" - returned when 3 or more reactions occurred to the current user's post + "reacted_your_profile_1" - returned when 1 reaction occurred to the current user's profile + "reacted_your_profile_2" - returned when 2 reactions occurred to the current user's profile + "reacted_your_profile_3" - returned when 3 or more reactions occurred to the current user's profile + + "reposted_tagged_in_1" - returned when 1 repost occurred to a post that the current user was tagged in + "reposted_tagged_in_2" - returned when 2 reposts occurred to a post that the current user was tagged in + "reposted_tagged_in_3" - returned when 3 or more reposts occurred to a post that the current user was tagged in + "reposted_your_post_1" - returned when 1 repost occurred to the current user's post + "reposted_your_post_2" - returned when 2 reposts occurred to the current user's post + "reposted_your_post_3" - returned when 3 or more reposts occurred to the current user's post + "reposted_your_profile_1" - returned when 1 repost occurred to the current user's profile + "reposted_your_profile_2" - returned when 2 reposts occurred to the current user's profile + "reposted_your_profile_3" - returned when 3 or more reposts occurred to the current user's profile + + "zapped_tagged_in_1" - returned when 1 zap occurred to a post that the current user was tagged in + "zapped_tagged_in_2" - returned when 2 zaps occurred to a post that the current user was tagged in + "zapped_tagged_in_3" - returned when 3 or more zaps occurred to a post that the current user was tagged in + "zapped_your_post_1" - returned when 1 zap occurred to the current user's post + "zapped_your_post_2" - returned when 2 zaps occurred to the current user's post + "zapped_your_post_3" - returned when 3 or more zaps occurred to the current user's post + "zapped_your_profile_1" - returned when 1 zap occurred to the current user's profile + "zapped_your_profile_2" - returned when 2 zaps occurred to the current user's profile + "zapped_your_profile_3" - returned when 3 or more zaps occurred to the current user's profile + */ +func reacting_to_text(profiles: Profiles, our_pubkey: String, group: EventGroupType, ev: NostrEvent?, locale: Locale? = nil) -> String { let verb = reacting_to_verb(group: group) - let reacting_to = determine_reacting_to(our_pubkey: our_pubkey, ev: ev) - let target = determine_reacting_to_text(reacting_to) - - if group.events.count == 1 { + let localization_key = "\(verb)_\(reacting_to)_\(min(group.events.count, 3))" + let bundle = bundleForLocale(locale: locale) + + switch group.events.count { + case 0: + return NSLocalizedString("??", comment: "") + case 1: let ev = group.events.first! let profile = profiles.lookup(id: ev.pubkey) let display_name = Profile.displayName(profile: profile, pubkey: ev.pubkey) - return String(format: "%@ is %@ %@", display_name, verb, target) - } - - if group.events.count == 2 { + + return String(format: bundle.localizedString(forKey: localization_key, value: bundleForLocale(locale: Locale(identifier: "en-US")).localizedString(forKey: localization_key, value: nil, table: nil), table: nil), locale: locale, display_name) + case 2: let alice_name = event_author_name(profiles: profiles, group.events[0]) let bob_name = event_author_name(profiles: profiles, group.events[1]) - - return String(format: "%@ and %@ are %@ %@", alice_name, bob_name, verb, target) - } - - if group.events.count > 2 { + + return String(format: bundle.localizedString(forKey: localization_key, value: bundleForLocale(locale: Locale(identifier: "en-US")).localizedString(forKey: localization_key, value: nil, table: nil), table: nil), locale: locale, alice_name, bob_name) + default: let alice_name = event_author_name(profiles: profiles, group.events.first!) let count = group.events.count - 1 - - return String(format: "%@ and %d other people are %@ %@", alice_name, count, verb, target) + + return String(format: bundle.localizedString(forKey: localization_key, value: bundleForLocale(locale: Locale(identifier: "en-US")).localizedString(forKey: localization_key, value: nil, table: nil), table: nil), locale: locale, count, alice_name) } - - return "??" } func reacting_to_verb(group: EventGroupType) -> String { switch group { case .reaction: - return "reacting" + return "reacted" case .repost: - return "reposting" + return "reposted" case .zap: fallthrough case .profile_zap: - return "zapping" + return "zapped" } } @@ -111,7 +135,7 @@ struct EventGroupView: View { let group: EventGroupType var GroupDescription: some View { - Text(reacting_to_text(profiles: state.profiles, our_pubkey: state.pubkey, group: group, ev: event)) + Text(verbatim: "\(reacting_to_text(profiles: state.profiles, our_pubkey: state.pubkey, group: group, ev: event))") } func ZapIcon(_ zapgrp: ZapGroup) -> some View { @@ -168,8 +192,9 @@ struct EventGroupView: View { } let test_encoded_post = "{\"id\": \"8ba545ab96959fe0ce7db31bc10f3ac3aa5353bc4428dbf1e56a7be7062516db\",\"pubkey\": \"7e27509ccf1e297e1df164912a43406218f8bd80129424c3ef798ca3ef5c8444\",\"created_at\": 1677013417,\"kind\": 1,\"tags\": [],\"content\": \"hello\",\"sig\": \"93684f15eddf11f42afbdd81828ee9fc35350344d8650c78909099d776e9ad8d959cd5c4bff7045be3b0b255144add43d0feef97940794a1bc9c309791bebe4a\"}" -let test_repost = NostrEvent(id: "", content: test_encoded_post, pubkey: "", kind: 6, tags: [], createdAt: 1) -let test_reposts = [test_repost, test_repost] +let test_repost_1 = NostrEvent(id: "", content: test_encoded_post, pubkey: "pk1", kind: 6, tags: [], createdAt: 1) +let test_repost_2 = NostrEvent(id: "", content: test_encoded_post, pubkey: "pk2", kind: 6, tags: [], createdAt: 1) +let test_reposts = [test_repost_1, test_repost_2] let test_event_group = EventGroup(events: test_reposts) struct EventGroupView_Previews: PreviewProvider { diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift @@ -342,9 +342,8 @@ struct ProfileView: View { .foregroundColor(.gray) } else { let followerCount = followers.count! - let count_text = Text(verbatim: "\(formatInt(followerCount))").font(.subheadline.weight(.medium)) let noun_text = Text(verbatim: "\(followersCountString(followerCount))").font(.subheadline).foregroundColor(.gray) - Text("\(count_text) \(noun_text)", 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 'Follower' or 'Followers'.") + Text("\(Text("\(followerCount)").font(.subheadline.weight(.medium))) \(noun_text)", 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 'Follower' or 'Followers'.") } } } @@ -368,9 +367,8 @@ 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 { - let count_text = Text(verbatim: "\(formatInt(profile.following))").font(.subheadline.weight(.medium)) let noun_text = Text("Following", comment: "Text on the user profile page next to the number of accounts a user is following.").font(.subheadline).foregroundColor(.gray) - Text("\(count_text) \(noun_text)", 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'.") + Text("\(Text("\(profile.following)").font(.subheadline.weight(.medium))) \(noun_text)", 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()) @@ -393,9 +391,8 @@ struct ProfileView: View { if let relays = profile.relays { // Only open relay config view if the user is logged in with private key and they are looking at their own profile. - let count_text = Text(verbatim: "\(formatInt(relays.keys.count))").font(.subheadline.weight(.medium)) let noun_text = Text(verbatim: "\(relaysCountString(relays.keys.count))").font(.subheadline).foregroundColor(.gray) - let relay_text = Text("\(count_text) \(noun_text)", 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 'Relay' or 'Relays'.") + let relay_text = Text("\(Text("\(relays.keys.count)").font(.subheadline.weight(.medium))) \(noun_text)", 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 'Relay' or 'Relays'.") if profile.pubkey == damus_state.pubkey && damus_state.is_privkey_user { NavigationLink(destination: RelayConfigView(state: damus_state)) { relay_text diff --git a/damus/Views/RelayFilterView.swift b/damus/Views/RelayFilterView.swift @@ -26,7 +26,7 @@ struct RelayFilterView: View { } var body: some View { - Text("To filter your \(timeline.rawValue) feed, please choose applicable relays from the list below:", comment: "Instructions on how to filter a specific timeline feed by choosing relay servers to filter on.") + Text("Please choose relays from the list below to filter the current feed:", comment: "Instructions on how to filter a specific timeline feed by choosing relay servers to filter on.") .padding() .padding(.top, 20) .padding(.bottom, 0) diff --git a/damus/Views/SaveKeysView.swift b/damus/Views/SaveKeysView.swift @@ -38,7 +38,7 @@ struct SaveKeysView: View { .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.", comment: "Label to describe that a public key is the user's account ID and what they can do with it.") + Text("This is your account ID, you can give this to your friends so that they can follow you. Tap 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) diff --git a/damus/Views/Zaps/CustomizeZapView.swift b/damus/Views/Zaps/CustomizeZapView.swift @@ -81,16 +81,16 @@ struct CustomizeZapView: View { } var ZapTypePicker: some View { - Picker("Zap Type", selection: $zap_type) { - Text("Public").tag(ZapType.pub) - Text("Anonymous").tag(ZapType.anon) - Text("Non-Zap").tag(ZapType.non_zap) + Picker(NSLocalizedString("Zap Type", comment: "Header text to indicate that the picker below it is to choose the type of zap to send."), selection: $zap_type) { + Text("Public", comment: "Picker option to indicate that a zap should be sent publicly and identify the user as who sent it.").tag(ZapType.pub) + Text("Anonymous", comment: "Picker option to indicate that a zap should be sent anonymously and not identify the user as who sent it.").tag(ZapType.anon) + Text("Non-Zap", comment: "Picker option to indicate that sats should be sent to the user's wallet as a regular Lightning payment, not as a zap.").tag(ZapType.non_zap) } .pickerStyle(.segmented) } var AmountPicker: some View { - Picker("Zap Amount", selection: $selected_amount) { + Picker(NSLocalizedString("Zap Amount", comment: "Title of picker that allows selection of predefined amounts to zap."), selection: $selected_amount) { ForEach(zap_amounts) { entry in let fmt = format_msats_abbrev(Int64(entry.amount) * 1000) HStack(alignment: .firstTextBaseline) { @@ -156,11 +156,11 @@ struct CustomizeZapView: View { Section(content: { AmountPicker }, header: { - Text("Zap Amount in sats") + Text("Zap Amount in sats", comment: "Header text to indicate that the picker below it is to choose a pre-defined amount of sats to zap.") }) Section(content: { - TextField("100000", text: $custom_amount) + TextField(String("100000"), text: $custom_amount) .keyboardType(.numberPad) .onReceive(Just(custom_amount)) { newValue in @@ -170,27 +170,27 @@ struct CustomizeZapView: View { } } }, header: { - Text("Custom Zap Amount") + Text("Custom Zap Amount", comment: "Header text to indicate that the text field below it is to enter a custom zap amount.") }) .dismissKeyboardOnTap() Section(content: { - TextField("Awesome post!", text: $comment) + TextField(NSLocalizedString("Awesome post!", comment: "Placeholder text for a comment to send as part of a zap to the user."), text: $comment) }, header: { - Text("Comment") + Text("Comment", comment: "Header text to indicate that the text field below it is a comment that will be used to send as part of a zap to the user.") }) .dismissKeyboardOnTap() Section(content: { ZapTypePicker }, header: { - Text("Zap Type") + Text("Zap Type", comment: "Header text to indicate that the picker below it is to choose the type of zap to send.") }) if zapping { - Text("Zapping...") + Text("Zapping...", comment: "Text to indicate that the app is in the process of sending a zap.") } else { - Button("Zap") { + Button(NSLocalizedString("Zap", comment: "Button to send a zap.")) { let amount = custom_amount_sats ?? selected_amount.amount send_zap(damus_state: state, event: event, lnurl: lnurl, is_custom: true, comment: comment, amount_sats: amount, zap_type: zap_type) self.zapping = true diff --git a/damus/ar.lproj/Localizable.strings b/damus/ar.lproj/Localizable.strings Binary files differ. diff --git a/damus/cs.lproj/Localizable.strings b/damus/cs.lproj/Localizable.strings Binary files differ. diff --git a/damus/de.lproj/Localizable.strings b/damus/de.lproj/Localizable.strings Binary files differ. diff --git a/damus/el-GR.lproj/Localizable.strings b/damus/el-GR.lproj/Localizable.strings Binary files differ. diff --git a/damus/en-US.lproj/Localizable.strings b/damus/en-US.lproj/Localizable.strings Binary files differ. diff --git a/damus/en-US.lproj/Localizable.stringsdict b/damus/en-US.lproj/Localizable.stringsdict @@ -34,6 +34,54 @@ <string>Followers</string> </dict> </dict> + <key>reacted_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to a post you were tagged in</string> + </dict> + </dict> + <key>reacted_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to your post</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to your post</string> + </dict> + </dict> + <key>reacted_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to your profile</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to your profile</string> + </dict> + </dict> <key>reactions_count</key> <dict> <key>NSStringLocalizedFormatKey</key> @@ -82,6 +130,54 @@ <string>Replying to %2$@, %3$@ &amp; %1$d others</string> </dict> </dict> + <key>reposted_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others reposted a post you were tagged in</string> + </dict> + </dict> + <key>reposted_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted your post</string> + <key>other</key> + <string>%2$@ and %1$d others reposted your post</string> + </dict> + </dict> + <key>reposted_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted your profile</string> + <key>other</key> + <string>%2$@ and %1$d others reposted your profile</string> + </dict> + </dict> <key>reposts_count</key> <dict> <key>NSStringLocalizedFormatKey</key> @@ -114,6 +210,54 @@ <string>%2$@ sats</string> </dict> </dict> + <key>zapped_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others zapped a post you were tagged in</string> + </dict> + </dict> + <key>zapped_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped your post</string> + <key>other</key> + <string>%2$@ and %1$d others zapped your post</string> + </dict> + </dict> + <key>zapped_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped your profile</string> + <key>other</key> + <string>%2$@ and %1$d others zapped your profile</string> + </dict> + </dict> <key>zaps_count</key> <dict> <key>NSStringLocalizedFormatKey</key> diff --git a/damus/en-US.xcloc/Localized Contents/en-US.xliff b/damus/en-US.xcloc/Localized Contents/en-US.xliff @@ -32,6 +32,11 @@ <tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.2" build-num="14C18"/> </header> <body> + <trans-unit id="%@" xml:space="preserve"> + <source>%@</source> + <target>%@</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%@ %@" xml:space="preserve"> <source>%@ %@</source> <target>%@ %@</target> @@ -58,6 +63,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet.</target> <note>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.</note> </trans-unit> + <trans-unit id="%lld" xml:space="preserve"> + <source>%lld</source> + <target>%lld</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="%lld/%lld" xml:space="preserve"> <source>%lld/%lld</source> <target>%lld/%lld</target> @@ -73,6 +83,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>'%@' is an invalid NIP-05 identifier. It should look like an email.</target> <note>Description of why the nip05 identifier is invalid.</note> </trans-unit> + <trans-unit id="??" xml:space="preserve"> + <source>??</source> + <target>??</target> + <note>No comment provided by engineer.</note> + </trans-unit> <trans-unit id="API Key (optional)" xml:space="preserve"> <source>API Key (optional)</source> <target>API Key (optional)</target> @@ -119,6 +134,11 @@ Sentence composed of 2 variables to describe how many people are following a use <note>Button to add recommended relay server. Button to confirm adding user inputted relay.</note> </trans-unit> + <trans-unit id="Add Bookmark" xml:space="preserve"> + <source>Add Bookmark</source> + <target>Add Bookmark</target> + <note>Context menu option for adding a note bookmark.</note> + </trans-unit> <trans-unit id="Add Relay" xml:space="preserve"> <source>Add Relay</source> <target>Add Relay</target> @@ -134,6 +154,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Admin</target> <note>Label to display relay contact user.</note> </trans-unit> + <trans-unit id="Anonymous" xml:space="preserve"> + <source>Anonymous</source> + <target>Anonymous</target> + <note>Picker option to indicate that a zap should be sent anonymously and not identify the user as who sent it.</note> + </trans-unit> <trans-unit id="Any" xml:space="preserve"> <source>Any</source> <target>Any</target> @@ -144,6 +169,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Are you sure you want to repost this?</target> <note>Alert message to ask if user wants to repost a post.</note> </trans-unit> + <trans-unit id="Awesome post!" xml:space="preserve"> + <source>Awesome post!</source> + <target>Awesome post!</target> + <note>Placeholder text for a comment to send as part of a zap to the user.</note> + </trans-unit> <trans-unit id="Banner Image" xml:space="preserve"> <source>Banner Image</source> <target>Banner Image</target> @@ -201,11 +231,6 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Blue Wallet</target> <note>Dropdown option label for Lightning wallet, Blue Wallet.</note> </trans-unit> - <trans-unit id="Bookmark" xml:space="preserve"> - <source>Bookmark</source> - <target>Bookmark</target> - <note>Context menu option for bookmarking a note</note> - </trans-unit> <trans-unit id="Bookmarks" xml:space="preserve"> <source>Bookmarks</source> <target>Bookmarks</target> @@ -258,6 +283,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Clear Cache</target> <note>Section title for clearing cached data.</note> </trans-unit> + <trans-unit id="Comment" xml:space="preserve"> + <source>Comment</source> + <target>Comment</target> + <note>Header text to indicate that the text field below it is a comment that will be used to send as part of a zap to the user.</note> + </trans-unit> <trans-unit id="Contact" xml:space="preserve"> <source>Contact</source> <target>Contact</target> @@ -354,6 +384,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Custom</target> <note>Dropdown option for selecting a custom translation server.</note> </trans-unit> + <trans-unit id="Custom Zap Amount" xml:space="preserve"> + <source>Custom Zap Amount</source> + <target>Custom Zap Amount</target> + <note>Header text to indicate that the text field below it is to enter a custom zap amount.</note> + </trans-unit> <trans-unit id="DMs" xml:space="preserve"> <source>DMs</source> <target>DMs</target> @@ -632,6 +667,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>No block list found, create a new one? This will overwrite any previous block lists.</target> <note>Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists.</note> </trans-unit> + <trans-unit id="Non-Zap" xml:space="preserve"> + <source>Non-Zap</source> + <target>Non-Zap</target> + <note>Picker option to indicate that sats should be sent to the user's wallet as a regular Lightning payment, not as a zap.</note> + </trans-unit> <trans-unit id="None" xml:space="preserve"> <source>None</source> <target>None</target> @@ -687,6 +727,11 @@ Sentence composed of 2 variables to describe how many people are following a use <target>Plan</target> <note>Prompt selection of DeepL subscription plan to perform machine translations on notes</note> </trans-unit> + <trans-unit id="Please choose relays from the list below to filter the current feed:" xml:space="preserve"> + <source>Please choose relays from the list below to filter the current feed:</source> + <target>Please choose relays from the list below to filter the current feed:</target> + <note>Instructions on how to filter a specific timeline feed by choosing relay servers to filter on.</note> + </trans-unit> <trans-unit id="Post" xml:space="preserve"> <source>Post</source> <target>Post</target> @@ -734,6 +779,11 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>Profile Picture</target> <note>Label for Profile Picture section of user profile form.</note> </trans-unit> + <trans-unit id="Public" xml:space="preserve"> + <source>Public</source> + <target>Public</target> + <note>Picker option to indicate that a zap should be sent publicly and identify the user as who sent it.</note> + </trans-unit> <trans-unit id="Public Account ID" xml:space="preserve"> <source>Public Account ID</source> <target>Public Account ID</target> @@ -785,6 +835,11 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>Relays have been notified and clients will be able to use this information to filter content. Thank you!</target> <note>Description of what was done as a result of sending a report to relay servers.</note> </trans-unit> + <trans-unit id="Remove Bookmark" xml:space="preserve"> + <source>Remove Bookmark</source> + <target>Remove Bookmark</target> + <note>Context menu option for removing a note bookmark.</note> + </trans-unit> <trans-unit id="Remove all" xml:space="preserve"> <source>Remove all</source> <target>Remove all</target> @@ -997,9 +1052,9 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>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.</target> <note>Warning that the inputted account key for login is an old-style and asking user to verify if it is a public key.</note> </trans-unit> - <trans-unit id="This is your account ID, you can give this to your friends so that they can follow you. Click to copy." xml:space="preserve"> - <source>This is your account ID, you can give this to your friends so that they can follow you. Click to copy.</source> - <target>This is your account ID, you can give this to your friends so that they can follow you. Click to copy.</target> + <trans-unit id="This is your account ID, you can give this to your friends so that they can follow you. Tap to copy." xml:space="preserve"> + <source>This is your account ID, you can give this to your friends so that they can follow you. Tap to copy.</source> + <target>This is your account ID, you can give this to your friends so that they can follow you. Tap to copy.</target> <note>Label to describe that a public key is the user's account ID and what they can do with it.</note> </trans-unit> <trans-unit id="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!" xml:space="preserve"> @@ -1012,11 +1067,6 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>Thread</target> <note>Navigation bar title for note thread.</note> </trans-unit> - <trans-unit id="To filter your %@ feed, please choose applicable relays from the list below:" xml:space="preserve"> - <source>To filter your %@ feed, please choose applicable relays from the list below:</source> - <target>To filter your %@ feed, please choose applicable relays from the list below:</target> - <note>Instructions on how to filter a specific timeline feed by choosing relay servers to filter on.</note> - </trans-unit> <trans-unit id="Translate Note" xml:space="preserve"> <source>Translate Note</source> <target>Translate Note</target> @@ -1052,11 +1102,6 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>URL</target> <note>Example URL to LibreTranslate server</note> </trans-unit> - <trans-unit id="Un-Bookmark" xml:space="preserve"> - <source>Un-Bookmark</source> - <target>Un-Bookmark</target> - <note>Context menu option for un-bookmarking a note</note> - </trans-unit> <trans-unit id="Unfollow" xml:space="preserve"> <source>Unfollow</source> <target>Unfollow</target> @@ -1157,7 +1202,28 @@ Label for filter for seeing your posts and replies (instead of only your posts). <trans-unit id="Zap" xml:space="preserve"> <source>Zap</source> <target>Zap</target> - <note>Accessibility label for zap button</note> + <note>Accessibility label for zap button + Button to send a zap.</note> + </trans-unit> + <trans-unit id="Zap Amount" xml:space="preserve"> + <source>Zap Amount</source> + <target>Zap Amount</target> + <note>Title of picker that allows selection of predefined amounts to zap.</note> + </trans-unit> + <trans-unit id="Zap Amount in sats" xml:space="preserve"> + <source>Zap Amount in sats</source> + <target>Zap Amount in sats</target> + <note>Header text to indicate that the picker below it is to choose a pre-defined amount of sats to zap.</note> + </trans-unit> + <trans-unit id="Zap Type" xml:space="preserve"> + <source>Zap Type</source> + <target>Zap Type</target> + <note>Header text to indicate that the picker below it is to choose the type of zap to send.</note> + </trans-unit> + <trans-unit id="Zapping..." xml:space="preserve"> + <source>Zapping...</source> + <target>Zapping...</target> + <note>Text to indicate that the app is in the process of sending a zap.</note> </trans-unit> <trans-unit id="Zaps" xml:space="preserve"> <source>Zaps</source> @@ -1209,6 +1275,66 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>optional</target> <note>Label indicating that a form input is optional.</note> </trans-unit> + <trans-unit id="reacted_tagged_in_1" xml:space="preserve"> + <source>%@ reacted to a post you were tagged in</source> + <target>%@ reacted to a post you were tagged in</target> + <note>Notification that a user reacted to a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="reacted_tagged_in_2" xml:space="preserve"> + <source>%@ and %@ reacted to a post you were tagged in</source> + <target>%@ and %@ reacted to a post you were tagged in</target> + <note>Notification that 2 users reacted to a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="reacted_your_post_1" xml:space="preserve"> + <source>%@ reacted to your post</source> + <target>%@ reacted to your post</target> + <note>Notification that a user reacted to the current user's post</note> + </trans-unit> + <trans-unit id="reacted_your_post_2" xml:space="preserve"> + <source>%@ and %@ reacted to your post</source> + <target>%@ and %@ reacted to your post</target> + <note>Notification that 2 users reacted to the current user's profile</note> + </trans-unit> + <trans-unit id="reacted_your_profile_1" xml:space="preserve"> + <source>%@ reacted to your profile</source> + <target>%@ reacted to your profile</target> + <note>Notification that a user reacted to the current user's profile</note> + </trans-unit> + <trans-unit id="reacted_your_profile_2" xml:space="preserve"> + <source>%@ and %@ reacted to your profile</source> + <target>%@ and %@ reacted to your profile</target> + <note>Notification that 2 users reacted to the current user's profile</note> + </trans-unit> + <trans-unit id="reposted_tagged_in_1" xml:space="preserve"> + <source>%@ reposted a post you were tagged in</source> + <target>%@ reposted a post you were tagged in</target> + <note>Notification that a user reposted a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="reposted_tagged_in_2" xml:space="preserve"> + <source>%@ and %@ reposted a post you were tagged in</source> + <target>%@ and %@ reposted a post you were tagged in</target> + <note>Notification that 2 users reposted a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="reposted_your_post_1" xml:space="preserve"> + <source>%@ reposted your post</source> + <target>%@ reposted your post</target> + <note>Notification that a user reposted the current user's post</note> + </trans-unit> + <trans-unit id="reposted_your_post_2" xml:space="preserve"> + <source>%@ and %@ reposted your post</source> + <target>%@ and %@ reposted your post</target> + <note>Notification that 2 users reposted the current user's post</note> + </trans-unit> + <trans-unit id="reposted_your_profile_1" xml:space="preserve"> + <source>%@ reposted your profile</source> + <target>%@ reposted your profile</target> + <note>Notification that a user reposted the current user's profile</note> + </trans-unit> + <trans-unit id="reposted_your_profile_2" xml:space="preserve"> + <source>%@ and %@ reposted your profile</source> + <target>%@ and %@ reposted your profile</target> + <note>Notification that 2 users reposted the current user's profile</note> + </trans-unit> <trans-unit id="satoshi" xml:space="preserve"> <source>satoshi</source> <target>satoshi</target> @@ -1224,6 +1350,36 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>you</target> <note>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.</note> </trans-unit> + <trans-unit id="zapped_tagged_in_1" xml:space="preserve"> + <source>%@ zapped a post you were tagged in</source> + <target>%@ zapped a post you were tagged in</target> + <note>Notification that a user zapped a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="zapped_tagged_in_2" xml:space="preserve"> + <source>%@ and %@ zapped a post you were tagged in</source> + <target>%@ and %@ zapped a post you were tagged in</target> + <note>Notification that 2 users zapped a post that the current user was tagged in</note> + </trans-unit> + <trans-unit id="zapped_your_post_1" xml:space="preserve"> + <source>%@ zapped your post</source> + <target>%@ zapped your post</target> + <note>Notification that a user zapped the current user's post</note> + </trans-unit> + <trans-unit id="zapped_your_post_2" xml:space="preserve"> + <source>%@ and %@ zapped your post</source> + <target>%@ and %@ zapped your post</target> + <note>Notification that 2 users zapped the current user's post</note> + </trans-unit> + <trans-unit id="zapped_your_profile_1" xml:space="preserve"> + <source>%@ zapped your profile</source> + <target>%@ zapped your profile</target> + <note>Notification that a user zapped the current user's profile</note> + </trans-unit> + <trans-unit id="zapped_your_profile_2" xml:space="preserve"> + <source>%@ and %@ zapped your profile</source> + <target>%@ and %@ zapped your profile</target> + <note>Notification that 2 users zapped the current user's profile</note> + </trans-unit> <trans-unit id="⚡️ %@" xml:space="preserve"> <source>⚡️ %@</source> <target>⚡️ %@</target> @@ -1266,6 +1422,51 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>%#@FOLLOWERS@</target> <note/> </trans-unit> + <trans-unit id="/reacted_tagged_in_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REACTED@</source> + <target>%#@REACTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_tagged_in_3:dict/REACTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reacted to a post you were tagged in</source> + <target>%2$@ and %1$d other reacted to a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_tagged_in_3:dict/REACTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reacted to a post you were tagged in</source> + <target>%2$@ and %1$d others reacted to a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_post_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REACTED@</source> + <target>%#@REACTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_post_3:dict/REACTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reacted to your post</source> + <target>%2$@ and %1$d other reacted to your post</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_post_3:dict/REACTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reacted to your post</source> + <target>%2$@ and %1$d others reacted to your post</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_profile_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REACTED@</source> + <target>%#@REACTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_profile_3:dict/REACTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reacted to your profile</source> + <target>%2$@ and %1$d other reacted to your profile</target> + <note/> + </trans-unit> + <trans-unit id="/reacted_your_profile_3:dict/REACTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reacted to your profile</source> + <target>%2$@ and %1$d others reacted to your profile</target> + <note/> + </trans-unit> <trans-unit id="/reactions_count:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> <source>%#@REACTIONS@</source> <target>%#@REACTIONS@</target> @@ -1311,6 +1512,51 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>Replying to %2$@, %3$@ &amp; %1$d others</target> <note/> </trans-unit> + <trans-unit id="/reposted_tagged_in_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REPOSTED@</source> + <target>%#@REPOSTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_tagged_in_3:dict/REPOSTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reposted a post you were tagged in</source> + <target>%2$@ and %1$d other reposted a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_tagged_in_3:dict/REPOSTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reposted a post you were tagged in</source> + <target>%2$@ and %1$d others reposted a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_post_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REPOSTED@</source> + <target>%#@REPOSTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_post_3:dict/REPOSTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reposted your post</source> + <target>%2$@ and %1$d other reposted your post</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_post_3:dict/REPOSTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reposted your post</source> + <target>%2$@ and %1$d others reposted your post</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_profile_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@REPOSTED@</source> + <target>%#@REPOSTED@</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_profile_3:dict/REPOSTED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other reposted your profile</source> + <target>%2$@ and %1$d other reposted your profile</target> + <note/> + </trans-unit> + <trans-unit id="/reposted_your_profile_3:dict/REPOSTED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others reposted your profile</source> + <target>%2$@ and %1$d others reposted your profile</target> + <note/> + </trans-unit> <trans-unit id="/reposts_count:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> <source>%#@REPOSTS@</source> <target>%#@REPOSTS@</target> @@ -1341,6 +1587,51 @@ Label for filter for seeing your posts and replies (instead of only your posts). <target>%2$@ sats</target> <note/> </trans-unit> + <trans-unit id="/zapped_tagged_in_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@ZAPPED@</source> + <target>%#@ZAPPED@</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_tagged_in_3:dict/ZAPPED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other zapped a post you were tagged in</source> + <target>%2$@ and %1$d other zapped a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_tagged_in_3:dict/ZAPPED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others zapped a post you were tagged in</source> + <target>%2$@ and %1$d others zapped a post you were tagged in</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_post_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@ZAPPED@</source> + <target>%#@ZAPPED@</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_post_3:dict/ZAPPED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other zapped your post</source> + <target>%2$@ and %1$d other zapped your post</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_post_3:dict/ZAPPED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others zapped your post</source> + <target>%2$@ and %1$d others zapped your post</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_profile_3:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> + <source>%#@ZAPPED@</source> + <target>%#@ZAPPED@</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_profile_3:dict/ZAPPED:dict/one:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d other zapped your profile</source> + <target>%2$@ and %1$d other zapped your profile</target> + <note/> + </trans-unit> + <trans-unit id="/zapped_your_profile_3:dict/ZAPPED:dict/other:dict/:string" xml:space="preserve"> + <source>%2$@ and %1$d others zapped your profile</source> + <target>%2$@ and %1$d others zapped your profile</target> + <note/> + </trans-unit> <trans-unit id="/zaps_count:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve"> <source>%#@ZAPS@</source> <target>%#@ZAPS@</target> diff --git a/damus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.strings b/damus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.strings Binary files differ. diff --git a/damus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.stringsdict b/damus/en-US.xcloc/Source Contents/damus/en-US.lproj/Localizable.stringsdict @@ -34,6 +34,54 @@ <string>Followers</string> </dict> </dict> + <key>reacted_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to a post you were tagged in</string> + </dict> + </dict> + <key>reacted_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to your post</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to your post</string> + </dict> + </dict> + <key>reacted_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REACTED@</string> + <key>REACTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reacted to your profile</string> + <key>other</key> + <string>%2$@ and %1$d others reacted to your profile</string> + </dict> + </dict> <key>reactions_count</key> <dict> <key>NSStringLocalizedFormatKey</key> @@ -82,6 +130,54 @@ <string>Replying to %2$@, %3$@ &amp; %1$d others</string> </dict> </dict> + <key>reposted_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others reposted a post you were tagged in</string> + </dict> + </dict> + <key>reposted_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted your post</string> + <key>other</key> + <string>%2$@ and %1$d others reposted your post</string> + </dict> + </dict> + <key>reposted_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@REPOSTED@</string> + <key>REPOSTED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other reposted your profile</string> + <key>other</key> + <string>%2$@ and %1$d others reposted your profile</string> + </dict> + </dict> <key>reposts_count</key> <dict> <key>NSStringLocalizedFormatKey</key> @@ -114,6 +210,54 @@ <string>%2$@ sats</string> </dict> </dict> + <key>zapped_tagged_in_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped a post you were tagged in</string> + <key>other</key> + <string>%2$@ and %1$d others zapped a post you were tagged in</string> + </dict> + </dict> + <key>zapped_your_post_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped your post</string> + <key>other</key> + <string>%2$@ and %1$d others zapped your post</string> + </dict> + </dict> + <key>zapped_your_profile_3</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@ZAPPED@</string> + <key>ZAPPED</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>%2$@ and %1$d other zapped your profile</string> + <key>other</key> + <string>%2$@ and %1$d others zapped your profile</string> + </dict> + </dict> <key>zaps_count</key> <dict> <key>NSStringLocalizedFormatKey</key> diff --git a/damus/es-419.lproj/Localizable.strings b/damus/es-419.lproj/Localizable.strings Binary files differ. diff --git a/damus/fa.lproj/InfoPlist.strings b/damus/fa.lproj/InfoPlist.strings Binary files differ. diff --git a/damus/fa.lproj/Localizable.strings b/damus/fa.lproj/Localizable.strings Binary files differ. diff --git a/damus/ja.lproj/Localizable.strings b/damus/ja.lproj/Localizable.strings Binary files differ. diff --git a/damus/nl.lproj/Localizable.strings b/damus/nl.lproj/Localizable.strings Binary files differ. diff --git a/damus/pl-PL.lproj/Localizable.strings b/damus/pl-PL.lproj/Localizable.strings Binary files differ. diff --git a/damus/uk.lproj/InfoPlist.strings b/damus/uk.lproj/InfoPlist.strings Binary files differ. diff --git a/damus/zh-CN.lproj/Localizable.strings b/damus/zh-CN.lproj/Localizable.strings Binary files differ. diff --git a/damusTests/EventGroupViewTests.swift b/damusTests/EventGroupViewTests.swift @@ -0,0 +1,42 @@ +// +// EventGroupViewTests.swift +// damusTests +// +// Created by Terry Yiu on 2/26/23. +// + +import XCTest +@testable import damus + +final class EventGroupViewTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testReactingToText() throws { + let enUsLocale = Locale(identifier: "en-US") + let damusState = test_damus_state() + + let encodedPost = "{\"id\": \"8ba545ab96959fe0ce7db31bc10f3ac3aa5353bc4428dbf1e56a7be7062516db\",\"pubkey\": \"7e27509ccf1e297e1df164912a43406218f8bd80129424c3ef798ca3ef5c8444\",\"created_at\": 1677013417,\"kind\": 1,\"tags\": [],\"content\": \"hello\",\"sig\": \"93684f15eddf11f42afbdd81828ee9fc35350344d8650c78909099d776e9ad8d959cd5c4bff7045be3b0b255144add43d0feef97940794a1bc9c309791bebe4a\"}" + let repost1 = NostrEvent(id: "", content: encodedPost, pubkey: "pk1", kind: NostrKind.boost.rawValue, tags: [], createdAt: 1) + let repost2 = NostrEvent(id: "", content: encodedPost, pubkey: "pk2", kind: NostrKind.boost.rawValue, tags: [], createdAt: 1) + + XCTAssertEqual(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [])), ev: test_event, locale: enUsLocale), "??") + XCTAssertEqual(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1])), ev: test_event, locale: enUsLocale), "pk1:pk1 reposted a post you were tagged in") + XCTAssertEqual(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1, repost2])), ev: test_event, locale: enUsLocale), "pk1:pk1 and pk2:pk2 reposted a post you were tagged in") + XCTAssertEqual(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1, repost2, repost2])), ev: test_event, locale: enUsLocale), "pk1:pk1 and 2 others reposted a post you were tagged in") + + Bundle.main.localizations.map { Locale(identifier: $0) }.forEach { + XCTAssertNoThrow(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [])), ev: test_event, locale: $0), "??") + XCTAssertNoThrow(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1])), ev: test_event, locale: $0)) + XCTAssertNoThrow(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1, repost2])), ev: test_event, locale: $0)) + XCTAssertNoThrow(reacting_to_text(profiles: damusState.profiles, our_pubkey: damusState.pubkey, group: .repost(EventGroup(events: [repost1, repost2, repost2])), ev: test_event, locale: $0)) + } + } + +} diff --git a/devtools/export-source-translation.sh b/devtools/export-source-translation.sh @@ -4,4 +4,4 @@ xcodebuild -exportLocalizations -project damus.xcodeproj -localizationPath "damus" -exportLanguage en-US # Generates all SwiftUI Text() wrapped localized strings. -genstrings -o "damus/en-US.xcloc/Source Contents/damus/en-US.lproj/" -SwiftUI **/*.swift +genstrings -a -d -o "damus/en-US.xcloc/Source Contents/damus/en-US.lproj/" -SwiftUI **/*.swift diff --git a/transifex.yml b/transifex.yml @@ -4,25 +4,27 @@ git: file_format: STRINGSDICT source_file_extension: stringsdict source_language: en_US - source_file_dir: damus/en-US.xcloc/Source Contents/damus/en-US.lproj/ - translation_files_expression: damus/<lang>.lproj/ + source_file_dir: 'damus/en-US.xcloc/Source Contents/damus/en-US.lproj/' + translation_files_expression: 'damus/<lang>.lproj/' - filter_type: dir file_format: STRINGS source_file_extension: strings source_language: en_US - source_file_dir: damus/en-US.xcloc/Source Contents/damus/en-US.lproj/ - translation_files_expression: damus/<lang>.lproj/ + source_file_dir: 'damus/en-US.xcloc/Source Contents/damus/en-US.lproj/' + translation_files_expression: 'damus/<lang>.lproj/' -settings: - language_mapping: - de_AT: de-AT - el_GR: el-GR - es_419: es-419 - fr_FR: fr-FR - it_IT: it-IT - lv_LV: lv-LV - pl_PL: pl-PL - pt_PT: pt-PT - tr_TR: tr-TR - zh_CN: zh-CN + settings: + language_mapping: + en_US: en-US + el_GR: el-GR + es_419: es-419 + fr_FR: fr-FR + it_IT: it-IT + lv_LV: lv-LV + pl_PL: pl-PL + pt_PT: pt-PT + tr_TR: tr-TR + zh_CN: zh-CN + zh_HK: zh-HK + zh_TW: zh-TW+ \ No newline at end of file