diff --git a/DysonNetwork.Pass/Account/AccountEventService.cs b/DysonNetwork.Pass/Account/AccountEventService.cs index d23c49ce..1027ece0 100644 --- a/DysonNetwork.Pass/Account/AccountEventService.cs +++ b/DysonNetwork.Pass/Account/AccountEventService.cs @@ -330,11 +330,11 @@ public class AccountEventService( .Where(x => x.AccountId == user.Id) .Select(x => new { x.Birthday, x.TimeZone }) .FirstOrDefaultAsync(); - + var accountBirthday = accountProfile?.Birthday; var now = SystemClock.Instance.GetCurrentInstant(); - + var userTimeZone = DateTimeZone.Utc; if (!string.IsNullOrEmpty(accountProfile?.TimeZone)) { @@ -343,9 +343,9 @@ public class AccountEventService( var todayInUserTz = now.InZone(userTimeZone).Date; var birthdayDate = accountBirthday?.InZone(userTimeZone).Date; - - var isBirthday = birthdayDate.HasValue && - birthdayDate.Value.Month == todayInUserTz.Month && + + var isBirthday = birthdayDate.HasValue && + birthdayDate.Value.Month == todayInUserTz.Month && birthdayDate.Value.Day == todayInUserTz.Day; List tips; @@ -561,7 +561,7 @@ public class AccountEventService( { var userActivities = activitiesByUser.GetValueOrDefault(userId, new List()); results[userId] = userActivities; - + // Update cache for this user var cacheKey = $"{ActivityCacheKey}{userId}"; await cache.SetWithGroupsAsync(cacheKey, userActivities, [$"{AccountService.AccountCachePrefix}{userId}"], diff --git a/DysonNetwork.Pass/Account/AccountService.cs b/DysonNetwork.Pass/Account/AccountService.cs index 3678b008..9d344fd2 100644 --- a/DysonNetwork.Pass/Account/AccountService.cs +++ b/DysonNetwork.Pass/Account/AccountService.cs @@ -432,8 +432,8 @@ public class AccountService( Notification = new PushNotification { Topic = "auth.verification", - Title = localizer.Get("authCodeTitle"), - Body = localizer.Get("authCodeBody", args: new { code }), + Title = localizer.Get("authCodeTitle", account.Language), + Body = localizer.Get("authCodeBody", locale: account.Language, args: new { code }), IsSavable = false } } @@ -464,8 +464,9 @@ public class AccountService( .SendRazorTemplateEmailAsync( account.Nick, contact.Content, - localizer.Get("codeEmailTitle"), + localizer.Get("codeEmailTitle", account.Language), "FactorCode", + account.Language, new VerificationEmailModel { Name = account.Name, diff --git a/DysonNetwork.Pass/Account/MagicSpellService.cs b/DysonNetwork.Pass/Account/MagicSpellService.cs index 686862ae..cd122f26 100644 --- a/DysonNetwork.Pass/Account/MagicSpellService.cs +++ b/DysonNetwork.Pass/Account/MagicSpellService.cs @@ -97,8 +97,9 @@ public class MagicSpellService( await email.SendRazorTemplateEmailAsync( contact.Account.Nick, contact.Content, - localizer.Get("regConfirmTitle"), + localizer.Get("regConfirmTitle", accountLanguage), "Welcome", + accountLanguage, new LandingEmailModel { Name = contact.Account.Name, @@ -110,8 +111,9 @@ public class MagicSpellService( await email.SendRazorTemplateEmailAsync( contact.Account.Nick, contact.Content, - localizer.Get("accountDeletionTitle"), + localizer.Get("accountDeletionTitle", accountLanguage), "AccountDeletion", + accountLanguage, new AccountDeletionEmailModel { Name = contact.Account.Name, @@ -123,8 +125,9 @@ public class MagicSpellService( await email.SendRazorTemplateEmailAsync( contact.Account.Nick, contact.Content, - localizer.Get("passwordResetTitle"), + localizer.Get("passwordResetTitle", accountLanguage), "PasswordReset", + accountLanguage, new PasswordResetEmailModel { Name = contact.Account.Name, @@ -138,8 +141,9 @@ public class MagicSpellService( await email.SendRazorTemplateEmailAsync( contact.Account.Nick, contactMethod!, - localizer.Get("contractMethodVerificationTitle"), + localizer.Get("contractMethodVerificationTitle", accountLanguage), "ContactVerification", + accountLanguage, new ContactVerificationEmailModel { Name = contact.Account.Name, diff --git a/DysonNetwork.Pass/Account/RelationshipService.cs b/DysonNetwork.Pass/Account/RelationshipService.cs index d1869801..2f10582c 100644 --- a/DysonNetwork.Pass/Account/RelationshipService.cs +++ b/DysonNetwork.Pass/Account/RelationshipService.cs @@ -117,8 +117,8 @@ public class RelationshipService( Notification = new PushNotification { Topic = "relationships.friends.request", - Title = localizer.Get("friendRequestTitle", args: new { sender.Nick }), - Body = localizer.Get("friendRequestBody"), + Title = localizer.Get("friendRequestTitle", locale: sender.Language, args: new { sender.Nick }), + Body = localizer.Get("friendRequestBody", locale: sender.Language), ActionUri = "/account/relationships", IsSavable = true } diff --git a/DysonNetwork.Pass/Auth/AuthController.cs b/DysonNetwork.Pass/Auth/AuthController.cs index c3874bff..83ed5faa 100644 --- a/DysonNetwork.Pass/Auth/AuthController.cs +++ b/DysonNetwork.Pass/Auth/AuthController.cs @@ -233,14 +233,14 @@ public class AuthController( { AccountService.SetCultureInfo(challenge.Account); await pusher.SendPushNotificationToUserAsync(new SendPushNotificationToUserRequest - { - Notification = new PushNotification { - Topic = "auth.login", - Title = localizer.Get("newLoginTitle"), - Body = localizer.Get("newLoginBody", args: new { deviceName = challenge.DeviceName ?? "unknown", ipAddress = challenge.IpAddress ?? "unknown" }), - IsSavable = true - }, + Notification = new PushNotification + { + Topic = "auth.login", + Title = localizer.Get("newLoginTitle", challenge.Account.Language), + Body = localizer.Get("newLoginBody", locale: challenge.Account.Language, args: new { deviceName = challenge.DeviceName ?? "unknown", ipAddress = challenge.IpAddress ?? "unknown" }), + IsSavable = true + }, UserId = challenge.AccountId.ToString() }); als.CreateActionLogFromRequest(ActionLogType.NewLogin, diff --git a/DysonNetwork.Pass/Realm/RealmService.cs b/DysonNetwork.Pass/Realm/RealmService.cs index 44fdfbb0..f959f620 100644 --- a/DysonNetwork.Pass/Realm/RealmService.cs +++ b/DysonNetwork.Pass/Realm/RealmService.cs @@ -55,8 +55,8 @@ public class RealmService( Notification = new PushNotification { Topic = "invites.realms", - Title = localizer.Get("realmInviteTitle"), - Body = localizer.Get("realmInviteBody", args: new { realmName = member.Realm.Name }), + Title = localizer.Get("realmInviteTitle", account.Language), + Body = localizer.Get("realmInviteBody", locale: account.Language, args: new { realmName = member.Realm.Name }), ActionUri = "/realms", IsSavable = true } diff --git a/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs index aba6e242..60e87316 100644 --- a/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs +++ b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs @@ -127,8 +127,8 @@ public class RealmServiceGrpc( Notification = new PushNotification { Topic = "invites.realms", - Title = localizer.Get("realmInviteTitle"), - Body = localizer.Get("realmInviteBody", args: new { realmName = member.Realm?.Name ?? "Unknown Realm" }), + Title = localizer.Get("realmInviteTitle", account.Language), + Body = localizer.Get("realmInviteBody", locale: account.Language, args: new { realmName = member?.Name ?? "Unknown Realm" }), ActionUri = "/realms", IsSavable = true } diff --git a/DysonNetwork.Pass/Resources/Locales/en.json b/DysonNetwork.Pass/Resources/Locales/en.json index 72547f82..f5e94605 100644 --- a/DysonNetwork.Pass/Resources/Locales/en.json +++ b/DysonNetwork.Pass/Resources/Locales/en.json @@ -23,5 +23,94 @@ "emailAccountDeletionTitle": "Confirm your account deletion", "passwordResetTitle": "Reset your password", "contractMethodVerificationTitle": "Verify Contact Method", - "codeEmailTitle": "Your email one-time-password" + "codeEmailTitle": "Your email one-time-password", + "friendRequestTitle": "{sender} requested to be your friend", + "friendRequestBody": "You can go to relationships page and decide accept their request or not.", + "newLoginTitle": "New login detected", + "newLoginBody": "Your account logged on to a device named {deviceName} at {ipAddress}", + "chatInviteTitle": "New Chat Invitation", + "chatInviteBody": "You just got invited to join {channel}", + "chatInviteDirectBody": "{user} sent an direct message invitation to you", + "postSubscriptionTitle": "{publisher}: {title}", + "postReplyTitle": "{user} replied your post", + "postReactTitle": "{user} reacted to your post", + "postReactBody": "{user} reacted with {reaction}", + "postReactContentBody": "{user} reacted with {reaction} to \"{title}\"", + "postAwardedTitle": "{user} awarded your post", + "postAwardedBody": "{user} awarded {amount} points", + "postAwardedContentBody": "{user} awarded {amount} points to \"{title}\"", + "realmInviteTitle": "Realm Invitation", + "realmInviteBody": "You have been invited to join {realm}", + "authCodeTitle": "Disposable Verification Code", + "authCodeBody": "{code} is your disposable code, it will expires in 5 minutes", + "subscriptionAppliedTitle": "Subscription {plan} just activated for your account", + "subscriptionAppliedBody": "Thank for supporting Solar Network! Your {days} days {plan} subscription just begun, feel free to explore the newly unlocked features!", + "orderPaidTitle": "Order {orderId} recipient", + "orderPaidBody": "Paid {amount} {currency} for {remark}", + "orderReceivedTitle": "Order {orderId} recipient", + "orderReceivedBody": "Received {amount} {currency} for {remark}", + "giftClaimedTitle": "Gift Claimed", + "giftClaimedBody": "Your gift {subscription} has been claimed by {user}", + "fortuneTipSpecialTitleBirthday": "Have a Birthday Party", + "fortuneTipSpecialContentBirthday": "Happy Birthday, {user}!", + "fortuneTipPositiveTitle1": "Gacha", + "fortuneTipPositiveContent1": "Comes at your first roll", + "fortuneTipPositiveTitle2": "Gaming", + "fortuneTipPositiveContent2": "Ranking up as god", + "fortuneTipPositiveTitle3": "Lottery", + "fortuneTipPositiveContent3": "Never miss a first", + "fortuneTipPositiveTitle4": "Speech", + "fortuneTipPositiveContent4": "Flowing at precision", + "fortuneTipPositiveTitle5": "Drawing", + "fortuneTipPositiveContent5": "Expectation is envisioned", + "fortuneTipPositiveTitle6": "Coding", + "fortuneTipPositiveContent6": "0 error(s), 0 warning(s)", + "fortuneTipPositiveTitle7": "Shopping", + "fortuneTipPositiveContent7": "No taxes and extra fees", + "fortuneTipPositiveTitle8": "Studying", + "fortuneTipPositiveContent8": "Efficiency X", + "fortuneTipPositiveTitle9": "Music composing", + "fortuneTipPositiveContent9": "No need to re-listen", + "fortuneTipPositiveTitle10": "Imaging", + "fortuneTipPositiveContent10": "Perfect every shot", + "fortuneTipPositiveTitle11": "PCB welding", + "fortuneTipPositiveContent11": "Solders, fluxes, GO!", + "fortuneTipPositiveTitle12": "After Effects", + "fortuneTipPositiveContent12": "@ 60 fps", + "fortuneTipPositiveTitle13": "Drone shot", + "fortuneTipPositiveContent13": "Ready to Go", + "fortuneTipPositiveTitle14": "Color grading", + "fortuneTipPositiveContent14": "In this format, at this color", + "fortuneTipPositiveTitle15": "Waterlogging", + "fortuneTipPositiveContent15": "0 waterlogging", + "fortuneTipNegativeTitle1": "Gacha", + "fortuneTipNegativeContent1": "Won't get at 80, but 200", + "fortuneTipNegativeTitle2": "Gaming", + "fortuneTipNegativeContent2": "Ground's limit", + "fortuneTipNegativeTitle3": "Lottery", + "fortuneTipNegativeContent3": "Zero in multiple ten", + "fortuneTipNegativeTitle4": "Speech", + "fortuneTipNegativeContent4": "Be careful what you say", + "fortuneTipNegativeTitle5": "Drawing", + "fortuneTipNegativeContent5": "Your pen is sticky", + "fortuneTipNegativeTitle6": "Coding", + "fortuneTipNegativeContent6": "114 error(s), 514 warning(s)", + "fortuneTipNegativeTitle7": "Shopping", + "fortuneTipNegativeContent7": "245% tariff", + "fortuneTipNegativeTitle8": "Studying", + "fortuneTipNegativeContent8": "Studying Fatigue III", + "fortuneTipNegativeTitle9": "Music composing", + "fortuneTipNegativeContent9": "FL Studio is not responding", + "fortuneTipNegativeTitle10": "Imaging", + "fortuneTipNegativeContent10": "Card cannot be accessed", + "fortuneTipNegativeTitle11": "PCB welding", + "fortuneTipNegativeContent11": "Hand welding", + "fortuneTipNegativeTitle12": "After Effects", + "fortuneTipNegativeContent12": "Baaah!", + "fortuneTipNegativeTitle13": "Drone shot", + "fortuneTipNegativeContent13": "Low battery level, Auto Landing in 16s", + "fortuneTipNegativeTitle14": "Color grading", + "fortuneTipNegativeContent14": "Crummy screen now", + "fortuneTipNegativeTitle15": "Washing film", + "fortuneTipNegativeContent15": "Why is there still something in the box?" } diff --git a/DysonNetwork.Pass/Resources/Locales/zh-hans.json b/DysonNetwork.Pass/Resources/Locales/zh-hans.json index 4bdf7665..c8f66090 100644 --- a/DysonNetwork.Pass/Resources/Locales/zh-hans.json +++ b/DysonNetwork.Pass/Resources/Locales/zh-hans.json @@ -23,5 +23,94 @@ "emailAccountDeletionTitle": "确认删除您的账户", "passwordResetTitle": "重置您的密码", "contractMethodVerificationTitle": "验证联系方式", - "codeEmailTitle": "您的邮箱一次性密码" + "codeEmailTitle": "您的邮箱一次性密码", + "friendRequestTitle": "{sender} 请求成为您的朋友", + "friendRequestBody": "您可以前往关系页面决定接受或拒绝其请求。", + "newLoginTitle": "检测到新登录", + "newLoginBody": "您的账户已在名为 {deviceName} 的设备上登录,位置为 {ipAddress}", + "chatInviteTitle": "新聊天邀请", + "chatInviteBody": "您刚刚被邀请加入 {channel}", + "chatInviteDirectBody": "{user} 向您发送了私信邀请", + "postSubscriptionTitle": "{publisher}: {title}", + "postReplyTitle": "{user} 回复了您的帖子", + "postReactTitle": "{user} 对您的帖子做出了反应", + "postReactBody": "{user} 用 {reaction} 做出了反应", + "postReactContentBody": "{user} 用 {reaction} 对 \"{title}\" 做出了反应", + "postAwardedTitle": "{user} 打赏了您的帖子", + "postAwardedBody": "{user} 打赏了 {amount} 积分", + "postAwardedContentBody": "{user} 打赏了 {amount} 积分给 \"{title}\"", + "realmInviteTitle": "领域邀请", + "realmInviteBody": "您被邀请加入 {realm}", + "authCodeTitle": "一次性验证码", + "authCodeBody": "{code} 是您的一次性验证码,将在5分钟后过期", + "subscriptionAppliedTitle": "订阅 {plan} 刚刚为您的账户激活", + "subscriptionAppliedBody": "感谢您支持 Solar Network!您的 {days} 天 {plan} 订阅刚刚开始,请尽情探索新解锁的功能!", + "orderPaidTitle": "订单 {orderId} 收件人", + "orderPaidBody": "支付了 {amount} {currency} 用于 {remark}", + "orderReceivedTitle": "订单 {orderId} 收件人", + "orderReceivedBody": "收到了 {amount} {currency} 用于 {remark}", + "giftClaimedTitle": "礼物已领取", + "giftClaimedBody": "您的 {subscription} 礼物已被 {user} 领取", + "fortuneTipSpecialTitleBirthday": "举办生日派对", + "fortuneTipSpecialContentBirthday": "生日快乐,{user}!", + "fortuneTipPositiveTitle1": "抽卡", + "fortuneTipPositiveContent1": "一抽就中", + "fortuneTipPositiveTitle2": "游戏", + "fortuneTipPositiveContent2": "封神", + "fortuneTipPositiveTitle3": "抽奖", + "fortuneTipPositiveContent3": "绝不错过首抽", + "fortuneTipPositiveTitle4": "配音", + "fortuneTipPositiveContent4": "行云流水", + "fortuneTipPositiveTitle5": "作画", + "fortuneTipPositiveContent5": "预期被实现", + "fortuneTipPositiveTitle6": "编程", + "fortuneTipPositiveContent6": "0个错误,0个警告", + "fortuneTipPositiveTitle7": "购物", + "fortuneTipPositiveContent7": "无税,无额外费用", + "fortuneTipPositiveTitle8": "学习", + "fortuneTipPositiveContent8": "效率X", + "fortuneTipPositiveTitle9": "音乐创作", + "fortuneTipPositiveContent9": "无需重新上线", + "fortuneTipPositiveTitle10": "图像处理", + "fortuneTipPositiveContent10": "每张都很完美", + "fortuneTipPositiveTitle11": "手工焊接", + "fortuneTipPositiveContent11": "焊工、焊料、起飞!", + "fortuneTipPositiveTitle12": "后期", + "fortuneTipPositiveContent12": "@ 60帧", + "fortuneTipPositiveTitle13": "云台", + "fortuneTipPositiveContent13": "准备出发", + "fortuneTipPositiveTitle14": "调色", + "fortuneTipPositiveContent14": "在此格式,进行调色", + "fortuneTipPositiveTitle15": "无水纹", + "fortuneTipPositiveContent15": "0个水印", + "fortuneTipNegativeTitle1": "抽卡", + "fortuneTipNegativeContent1": "保底80却出200", + "fortuneTipNegativeTitle2": "游戏", + "fortuneTipNegativeContent2": "地板", + "fortuneTipNegativeTitle3": "抽奖", + "fortuneTipNegativeContent3": "十连没出", + "fortuneTipNegativeTitle4": "配音", + "fortuneTipNegativeContent4": "慎言", + "fortuneTipNegativeTitle5": "作画", + "fortuneTipNegativeContent5": "笔尖不顺畅", + "fortuneTipNegativeTitle6": "编程", + "fortuneTipNegativeContent6": "114个错误,514个警告", + "fortuneTipNegativeTitle7": "购物", + "fortuneTipNegativeContent7": "245%关税", + "fortuneTipNegativeTitle8": "学习", + "fortuneTipNegativeContent8": "学习疲劳III", + "fortuneTipNegativeTitle9": "音乐创作", + "fortuneTipNegativeContent9": "FL Studio没有响应", + "fortuneTipNegativeTitle10": "图像处理", + "fortuneTipNegativeContent10": "无法读取SD卡", + "fortuneTipNegativeTitle11": "手工焊接", + "fortuneTipNegativeContent11": "手工焊接", + "fortuneTipNegativeTitle12": "后期", + "fortuneTipNegativeContent12": "啊啊啊!", + "fortuneTipNegativeTitle13": "云台", + "fortuneTipNegativeContent13": "电量低,自动降落16秒", + "fortuneTipNegativeTitle14": "调色", + "fortuneTipNegativeContent14": "屏幕现在很烂", + "fortuneTipNegativeTitle15": "洗胶片", + "fortuneTipNegativeContent15": "为什么盒子里还有东西?" } diff --git a/DysonNetwork.Sphere/Post/PostService.cs b/DysonNetwork.Sphere/Post/PostService.cs index 719827b6..54a79dfa 100644 --- a/DysonNetwork.Sphere/Post/PostService.cs +++ b/DysonNetwork.Sphere/Post/PostService.cs @@ -118,15 +118,16 @@ public partial class PostService( public (string title, string content) ChopPostForNotification(SnPost post) { + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var content = !string.IsNullOrEmpty(post.Description) ? post.Description?.Length >= 40 ? post.Description[..37] + "..." : post.Description : post.Content?.Length >= 100 ? string.Concat(post.Content.AsSpan(0, 97), "...") : post.Content; var title = post.Title ?? (post.Content?.Length >= 10 ? post.Content[..10] + "..." : post.Content); - title ??= localizer.Get("postOnlyMedia"); + title ??= localizer.Get("postOnlyMedia", locale: locale); if (string.IsNullOrWhiteSpace(content)) - content = localizer.Get("postOnlyMedia"); + content = localizer.Get("postOnlyMedia", locale: locale); return (title, content); } diff --git a/DysonNetwork.Sphere/Resources/Locales/en.json b/DysonNetwork.Sphere/Resources/Locales/en.json index 4b90358a..bbdbe93e 100644 --- a/DysonNetwork.Sphere/Resources/Locales/en.json +++ b/DysonNetwork.Sphere/Resources/Locales/en.json @@ -9,5 +9,16 @@ "postAwardedContentBody": "{user} awarded {amount} points to \"{title}\"", "postSubscriptionTitle": "{publisher}: {title}", "realmInviteTitle": "Realm Invitation", - "realmInviteBody": "You have been invited to join {realm}" + "realmInviteBody": "You have been invited to join {realm}", + "chatInviteTitle": "New Chat Invitation", + "chatInviteBody": "You just got invited to join {channel}", + "chatInviteDirectBody": "{user} sent an direct message invitation to you", + "postReplyBody": "{user} replied: {content}", + "postReplyContentBody": "{user} replied post \"{title}\": {content}", + "authCodeTitle": "Disposable Verification Code", + "authCodeBody": "{code} is your disposable code, it will expires in 5 minutes", + "subscriptionAppliedTitle": "Subscription {plan} just activated for your account", + "subscriptionAppliedBody": "Thank for supporting the Solar Network! Your {days} days {plan} subscription just begun, feel free to explore the newly unlocked features!", + "orderPaidTitle": "Order {orderId} recipient", + "orderPaidBody": "{amount} {currency} was removed from your wallet to pay for {item}" } diff --git a/DysonNetwork.Sphere/Resources/Locales/zh-hans.json b/DysonNetwork.Sphere/Resources/Locales/zh-hans.json index f0281706..075a4381 100644 --- a/DysonNetwork.Sphere/Resources/Locales/zh-hans.json +++ b/DysonNetwork.Sphere/Resources/Locales/zh-hans.json @@ -9,5 +9,16 @@ "postAwardedContentBody": "{user} 打赏了 {amount} 积分给 \"{title}\"", "postSubscriptionTitle": "{publisher}: {title}", "realmInviteTitle": "领域邀请", - "realmInviteBody": "您被邀请加入 {realm}" + "realmInviteBody": "您被邀请加入 {realm}", + "chatInviteTitle": "新聊天邀请", + "chatInviteBody": "您刚刚被邀请加入 {channel}", + "chatInviteDirectBody": "{user} 向您发送了私信邀请", + "postReplyBody": "{user} 回复:{content}", + "postReplyContentBody": "{user} 回复了帖子 \"{title}\":{content}", + "authCodeTitle": "一次性验证码", + "authCodeBody": "{code} 是您的一次性验证码,将在5分钟后过期", + "subscriptionAppliedTitle": "订阅 {plan} 刚刚为您的账户激活", + "subscriptionAppliedBody": "感谢您支持 Solar Network!您的 {days} 天 {plan} 订阅刚刚开始,请尽情探索新解锁的功能!", + "orderPaidTitle": "订单 {orderId} 收件人", + "orderPaidBody": "{amount} {currency} 已从您的钱包中扣除以支付 {item}" } diff --git a/DysonNetwork.Wallet/Payment/PaymentService.cs b/DysonNetwork.Wallet/Payment/PaymentService.cs index 6830a575..e23b894e 100644 --- a/DysonNetwork.Wallet/Payment/PaymentService.cs +++ b/DysonNetwork.Wallet/Payment/PaymentService.cs @@ -180,8 +180,9 @@ public class PaymentService( { // Due to ID is uuid, it longer than 8 words for sure var readableTransactionId = transaction.Id.ToString().Replace("-", "")[..8]; + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var readableTransactionRemark = transaction.Remarks ?? $"#{readableTransactionId}"; - + await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { @@ -189,13 +190,13 @@ public class PaymentService( Notification = new PushNotification { Topic = "wallets.transactions", - Title = localizer.Get("transactionNewTitle", args: new { remark = readableTransactionRemark }), + Title = localizer.Get("transactionNewTitle", locale: locale, args: new { remark = readableTransactionRemark }), Body = transaction.Amount > 0 - ? localizer.Get("transactionNewBodyMinus", args: new { + ? localizer.Get("transactionNewBodyMinus", locale: locale, args: new { amount = transaction.Amount.ToString(CultureInfo.InvariantCulture), currency = transaction.Currency }) - : localizer.Get("transactionNewBodyPlus", args: new { + : localizer.Get("transactionNewBodyPlus", locale: locale, args: new { amount = transaction.Amount.ToString(CultureInfo.InvariantCulture), currency = transaction.Currency }), @@ -208,9 +209,10 @@ public class PaymentService( if (payeeWallet is not null) { // Due to ID is uuid, it longer than 8 words for sure + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var readableTransactionId = transaction.Id.ToString().Replace("-", "")[..8]; var readableTransactionRemark = transaction.Remarks ?? $"#{readableTransactionId}"; - + await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { @@ -218,13 +220,13 @@ public class PaymentService( Notification = new PushNotification { Topic = "wallets.transactions", - Title = localizer.Get("transactionNewTitle", args: new { remark = readableTransactionRemark }), + Title = localizer.Get("transactionNewTitle", locale: locale, args: new { remark = readableTransactionRemark }), Body = transaction.Amount > 0 - ? localizer.Get("transactionNewBodyPlus", args: new { + ? localizer.Get("transactionNewBodyPlus", locale: locale, args: new { amount = transaction.Amount.ToString(CultureInfo.InvariantCulture), currency = transaction.Currency }) - : localizer.Get("transactionNewBodyMinus", args: new { + : localizer.Get("transactionNewBodyMinus", locale: locale, args: new { amount = transaction.Amount.ToString(CultureInfo.InvariantCulture), currency = transaction.Currency }), @@ -339,9 +341,36 @@ public class PaymentService( if (payeeWallet is not null) { // Due to ID is uuid, it longer than 8 words for sure + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var readableOrderId = order.Id.ToString().Replace("-", "")[..8]; var readableOrderRemark = order.Remarks ?? $"#{readableOrderId}"; + + await pusher.SendPushNotificationToUserAsync( + new SendPushNotificationToUserRequest + { + UserId = payerWallet.AccountId.ToString(), + Notification = new PushNotification + { + Topic = "wallets.orders.paid", + Title = localizer.Get("orderPaidTitle", locale: locale, args: new { orderId = $"#{readableOrderId}" }), + Body = localizer.Get("orderPaidBody", locale: locale, args: new { + amount = order.Amount.ToString(CultureInfo.InvariantCulture), + currency = order.Currency, + remark = readableOrderRemark + }), + IsSavable = true + } + } + ); + } + if (payeeWallet is not null) + { + // Due to ID is uuid, it longer than 8 words for sure + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; + var readableOrderId = order.Id.ToString().Replace("-", "")[..8]; + var readableOrderRemark = order.Remarks ?? $"#{readableOrderId}"; + await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { @@ -349,8 +378,8 @@ public class PaymentService( Notification = new PushNotification { Topic = "wallets.orders.received", - Title = localizer.Get("orderReceivedTitle", args: new { orderId = $"#{readableOrderId}" }), - Body = localizer.Get("orderReceivedBody", args: new { + Title = localizer.Get("orderReceivedTitle", locale: locale, args: new { orderId = $"#{readableOrderId}" }), + Body = localizer.Get("orderReceivedBody", locale: locale, args: new { amount = order.Amount.ToString(CultureInfo.InvariantCulture), currency = order.Currency, remark = readableOrderRemark diff --git a/DysonNetwork.Wallet/Payment/SubscriptionService.cs b/DysonNetwork.Wallet/Payment/SubscriptionService.cs index 2a438a21..4e71c1c1 100644 --- a/DysonNetwork.Wallet/Payment/SubscriptionService.cs +++ b/DysonNetwork.Wallet/Payment/SubscriptionService.cs @@ -420,11 +420,12 @@ public class SubscriptionService( ? subscription.EndedAt.Value.Minus(subscription.BegunAt).Days.ToString() : "infinite"; + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var notification = new PushNotification { Topic = "subscriptions.begun", - Title = localizer.Get("subscriptionAppliedTitle", args: new { subscriptionName = humanReadableName }), - Body = localizer.Get("subscriptionAppliedBody", args: new { duration, subscriptionName = humanReadableName }), + Title = localizer.Get("subscriptionAppliedTitle", locale: locale, args: new { subscriptionName = humanReadableName }), + Body = localizer.Get("subscriptionAppliedBody", locale: locale, args: new { duration, subscriptionName = humanReadableName }), Meta = GrpcTypeHelper.ConvertObjectToByteString(new Dictionary { ["subscription_id"] = subscription.Id.ToString() @@ -917,11 +918,12 @@ public class SubscriptionService( ? humanReadable : subscription.Identifier; + var locale = System.Globalization.CultureInfo.CurrentUICulture.Name; var notification = new PushNotification { Topic = "gifts.claimed", - Title = localizer.Get("giftClaimedTitle"), - Body = localizer.Get("giftClaimedBody", args: new { subscriptionName = humanReadableName, redeemerName = redeemer.Name }), + Title = localizer.Get("giftClaimedTitle", locale: locale), + Body = localizer.Get("giftClaimedBody", locale: locale, args: new { subscriptionName = humanReadableName, redeemerName = redeemer.Name }), Meta = GrpcTypeHelper.ConvertObjectToByteString(new Dictionary { ["gift_id"] = gift.Id.ToString(),