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

This commit is contained in:
William Casarin
2023-02-26 15:48:55 -08:00
29 changed files with 755 additions and 109 deletions

View File

@@ -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())
}

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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