From 0051740cb0206b17133ec65af2220a6c76a03aff Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 5 Feb 2026 16:28:31 +0800 Subject: [PATCH] :recycle: Replaced the SetCultureInfo with the new localization engine --- .../Chat/ChatRoomController.cs | 25 ++++++++-------- .../Account/AccountEventService.cs | 25 +++++++--------- DysonNetwork.Pass/Account/AccountService.cs | 24 ++++----------- .../Account/MagicSpellService.cs | 1 - DysonNetwork.Pass/Auth/AuthController.cs | 24 +++++++-------- DysonNetwork.Pass/Realm/RealmService.cs | 10 +++---- DysonNetwork.Pass/Realm/RealmServiceGrpc.cs | 4 +-- DysonNetwork.Shared/CultureService.cs | 19 ------------ DysonNetwork.Sphere/Post/PostService.cs | 29 +++++++++---------- .../Publisher/PublisherSubscriptionService.cs | 5 ++-- 10 files changed, 60 insertions(+), 106 deletions(-) delete mode 100644 DysonNetwork.Shared/CultureService.cs diff --git a/DysonNetwork.Messager/Chat/ChatRoomController.cs b/DysonNetwork.Messager/Chat/ChatRoomController.cs index 5bcf0d19..cfe2dc83 100644 --- a/DysonNetwork.Messager/Chat/ChatRoomController.cs +++ b/DysonNetwork.Messager/Chat/ChatRoomController.cs @@ -40,7 +40,7 @@ public class ChatRoomController( if (chatRoom.Type != ChatRoomType.DirectMessage) return Ok(chatRoom); chatRoom = await crs.LoadChatRealms(chatRoom); - + if (HttpContext.Items["CurrentUser"] is Account currentUser) chatRoom = await crs.LoadDirectMessageMembers(chatRoom, Guid.Parse(currentUser.Id)); @@ -142,7 +142,7 @@ public class ChatRoomController( var invitedMember = dmRoom.Members.First(m => m.AccountId == request.RelatedUserId); invitedMember.ChatRoom = dmRoom; - await _SendInviteNotify(invitedMember, currentUser); + await SendInviteNotify(invitedMember, currentUser); return Ok(dmRoom); } @@ -168,7 +168,7 @@ public class ChatRoomController( public class ChatRoomRequest { - [Required] [MaxLength(1024)] public string? Name { get; set; } + [Required][MaxLength(1024)] public string? Name { get; set; } [MaxLength(4096)] public string? Description { get; set; } [MaxLength(32)] public string? PictureId { get; set; } [MaxLength(32)] public string? BackgroundId { get; set; } @@ -583,7 +583,7 @@ public class ChatRoomController( existingMember.JoinedAt = null; db.ChatMembers.Update(existingMember); await db.SaveChangesAsync(); - await _SendInviteNotify(existingMember, currentUser); + await SendInviteNotify(existingMember, currentUser); _ = als.CreateActionLogAsync(new CreateActionLogRequest { @@ -612,7 +612,7 @@ public class ChatRoomController( await db.SaveChangesAsync(); newMember.ChatRoom = chatRoom; - await _SendInviteNotify(newMember, currentUser); + await SendInviteNotify(newMember, currentUser); _ = als.CreateActionLogAsync(new CreateActionLogRequest { @@ -814,7 +814,7 @@ public class ChatRoomController( return NoContent(); } - + [HttpDelete("{roomId:guid}/members/{memberId:guid}/timeout")] [Authorize] public async Task RemoveChatMemberTimeout(Guid roomId, Guid memberId) @@ -1003,14 +1003,13 @@ public class ChatRoomController( return NoContent(); } - private async Task _SendInviteNotify(SnChatMember member, Account sender) + private async Task SendInviteNotify(SnChatMember member, Account sender) { var account = await accounts.GetAccountAsync(new GetAccountRequest { Id = member.AccountId.ToString() }); - CultureService.SetCultureInfo(account); - var title = "Chat Invite"; - var body = member.ChatRoom.Type == ChatRoomType.DirectMessage - ? $"{sender.Nick} sent you a direct message" - : $"You have been invited to {member.ChatRoom.Name ?? "Unnamed"}"; + var title = "Chat Invite"; + var body = member.ChatRoom.Type == ChatRoomType.DirectMessage + ? $"{sender.Nick} sent you a direct message" + : $"You have been invited to {member.ChatRoom.Name ?? "Unnamed"}"; await pusher.SendPushNotificationToUserAsync( @@ -1031,4 +1030,4 @@ public class ChatRoomController( } ); } -} \ No newline at end of file +} diff --git a/DysonNetwork.Pass/Account/AccountEventService.cs b/DysonNetwork.Pass/Account/AccountEventService.cs index 1027ece0..aaa8bba9 100644 --- a/DysonNetwork.Pass/Account/AccountEventService.cs +++ b/DysonNetwork.Pass/Account/AccountEventService.cs @@ -302,9 +302,9 @@ public class AccountEventService( private const string CheckInLockKey = "checkin:lock:"; - public async Task CheckInDaily(SnAccount user, Instant? backdated = null) + public async Task CheckInDaily(SnAccount account, Instant? backdated = null) { - var lockKey = $"{CheckInLockKey}{user.Id}"; + var lockKey = $"{CheckInLockKey}{account.Id}"; try { @@ -322,12 +322,9 @@ public class AccountEventService( await using var lockObj = await cache.AcquireLockAsync(lockKey, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(5)) ?? throw new InvalidOperationException("Check-in was in progress."); - var cultureInfo = new CultureInfo(user.Language, false); - CultureInfo.CurrentCulture = cultureInfo; - CultureInfo.CurrentUICulture = cultureInfo; var accountProfile = await db.AccountProfiles - .Where(x => x.AccountId == user.Id) + .Where(x => x.AccountId == account.Id) .Select(x => new { x.Birthday, x.TimeZone }) .FirstOrDefaultAsync(); @@ -360,7 +357,7 @@ public class AccountEventService( { IsPositive = true, Title = localizer.Get("fortuneTipSpecialTitleBirthday"), - Content = localizer.Get("fortuneTipSpecialContentBirthday", args: new { user.Nick }), + Content = localizer.Get("fortuneTipSpecialContentBirthday", args: new { account.Nick }), } ]; } @@ -374,8 +371,8 @@ public class AccountEventService( tips = positiveIndices.Select(index => new CheckInFortuneTip { IsPositive = true, - Title = localizer.Get($"fortuneTipPositiveTitle{index}"), - Content = localizer.Get($"fortuneTipPositiveContent{index}") + Title = localizer.Get($"fortuneTipPositiveTitle{index}", account.Language), + Content = localizer.Get($"fortuneTipPositiveContent{index}", account.Language) }).ToList(); // Generate 2 negative tips @@ -387,8 +384,8 @@ public class AccountEventService( tips.AddRange(negativeIndices.Select(index => new CheckInFortuneTip { IsPositive = false, - Title = localizer.Get($"fortuneTipNegativeTitle{index}"), - Content = localizer.Get($"fortuneTipNegativeContent{index}") + Title = localizer.Get($"fortuneTipNegativeTitle{index}", account.Language), + Content = localizer.Get($"fortuneTipNegativeContent{index}", account.Language) })); // The 5 is specialized, keep it alone. @@ -409,7 +406,7 @@ public class AccountEventService( { Tips = tips, Level = checkInLevel, - AccountId = user.Id, + AccountId = account.Id, RewardExperience = 100, RewardPoints = backdated.HasValue ? null : 10, BackdatedFrom = backdated.HasValue ? SystemClock.Instance.GetCurrentInstant() : null, @@ -421,7 +418,7 @@ public class AccountEventService( if (result.RewardPoints.HasValue) await payment.CreateTransactionWithAccount( null, - user.Id.ToString(), + account.Id.ToString(), WalletCurrency.SourcePoint, result.RewardPoints.Value.ToString(CultureInfo.InvariantCulture), $"Check-in reward on {now:yyyy/MM/dd}" @@ -439,7 +436,7 @@ public class AccountEventService( "check-in", $"Check-in reward on {now:yyyy/MM/dd}", result.RewardExperience.Value, - user.Id + account.Id ); // The lock will be automatically released by the await using statement diff --git a/DysonNetwork.Pass/Account/AccountService.cs b/DysonNetwork.Pass/Account/AccountService.cs index dd49e444..5da0058a 100644 --- a/DysonNetwork.Pass/Account/AccountService.cs +++ b/DysonNetwork.Pass/Account/AccountService.cs @@ -34,18 +34,6 @@ public class AccountService( INatsConnection nats ) { - public static void SetCultureInfo(SnAccount account) - { - SetCultureInfo(account.Language); - } - - public static void SetCultureInfo(string? languageCode) - { - var info = new CultureInfo(languageCode ?? "en-us", false); - CultureInfo.CurrentCulture = info; - CultureInfo.CurrentUICulture = info; - } - public const string AccountCachePrefix = "account:"; public async Task PurgeAccountCache(SnAccount account) @@ -123,7 +111,7 @@ public class AccountService( ).CountAsync(); if (dupeEmailCount > 0) throw new InvalidOperationException("Account email has already been used."); - + var account = new SnAccount { Name = name, @@ -432,8 +420,8 @@ public class AccountService( Notification = new PushNotification { Topic = "auth.verification", - Title = localizer.Get("authCodeTitle", account.Language), - Body = localizer.Get("authCodeBody", locale: account.Language, args: new { code }), + Title = localizer.Get("authCodeTitle", account.Language), + Body = localizer.Get("authCodeBody", locale: account.Language, args: new { code }), IsSavable = false } } @@ -554,7 +542,7 @@ public class AccountService( { if (!await IsDeviceActive(session.ClientId.Value)) await pusher.UnsubscribePushNotificationsAsync(new UnsubscribePushNotificationsRequest() - { DeviceId = session.Client!.DeviceId } + { DeviceId = session.Client!.DeviceId } ); } @@ -790,11 +778,11 @@ public class AccountService( { var accountIds = accounts.Select(a => a.Id).ToList(); var subscriptions = await remoteSubscription.GetPerkSubscriptions(accountIds); - + var subscriptionDict = subscriptions .Where(s => s != null) .ToDictionary( - s => Guid.Parse(s.AccountId), + s => Guid.Parse(s.AccountId), s => SnWalletSubscription.FromProtoValue(s).ToReference() ); diff --git a/DysonNetwork.Pass/Account/MagicSpellService.cs b/DysonNetwork.Pass/Account/MagicSpellService.cs index edaa70f9..37f4640b 100644 --- a/DysonNetwork.Pass/Account/MagicSpellService.cs +++ b/DysonNetwork.Pass/Account/MagicSpellService.cs @@ -87,7 +87,6 @@ public class MagicSpellService( .Where(a => a.Id == spell.AccountId) .Select(a => a.Language) .FirstOrDefaultAsync(); - AccountService.SetCultureInfo(accountLanguage); try { diff --git a/DysonNetwork.Pass/Auth/AuthController.cs b/DysonNetwork.Pass/Auth/AuthController.cs index 83ed5faa..12d1c98d 100644 --- a/DysonNetwork.Pass/Auth/AuthController.cs +++ b/DysonNetwork.Pass/Auth/AuthController.cs @@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; using NodaTime; using Microsoft.EntityFrameworkCore; -using DysonNetwork.Pass.Localization; using DysonNetwork.Shared.Geometry; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Localization; @@ -31,8 +30,8 @@ public class AuthController( public class ChallengeRequest { [Required] public Shared.Models.ClientPlatform Platform { get; set; } - [Required] [MaxLength(256)] public string Account { get; set; } = null!; - [Required] [MaxLength(512)] public string DeviceId { get; set; } = null!; + [Required][MaxLength(256)] public string Account { get; set; } = null!; + [Required][MaxLength(512)] public string DeviceId { get; set; } = null!; [MaxLength(1024)] public string? DeviceName { get; set; } public List Audiences { get; set; } = []; public List Scopes { get; set; } = []; @@ -231,16 +230,15 @@ public class AuthController( if (challenge.StepRemain == 0) { - AccountService.SetCultureInfo(challenge.Account); await pusher.SendPushNotificationToUserAsync(new SendPushNotificationToUserRequest + { + Notification = new PushNotification { - 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 - }, + 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, @@ -270,7 +268,7 @@ public class AuthController( public class NewSessionRequest { - [Required] [MaxLength(512)] public string DeviceId { get; set; } = null!; + [Required][MaxLength(512)] public string DeviceId { get; set; } = null!; [MaxLength(1024)] public string? DeviceName { get; set; } [Required] public Shared.Models.ClientPlatform Platform { get; set; } public Instant? ExpiredAt { get; set; } @@ -357,4 +355,4 @@ public class AuthController( return Ok(new TokenExchangeResponse { Token = tk }); } -} \ No newline at end of file +} diff --git a/DysonNetwork.Pass/Realm/RealmService.cs b/DysonNetwork.Pass/Realm/RealmService.cs index f959f620..9a4aad15 100644 --- a/DysonNetwork.Pass/Realm/RealmService.cs +++ b/DysonNetwork.Pass/Realm/RealmService.cs @@ -17,7 +17,7 @@ public class RealmService( ) { private const string CacheKeyPrefix = "account:realms:"; - + public async Task> GetUserRealms(Guid accountId) { var cacheKey = $"{CacheKeyPrefix}{accountId}"; @@ -34,19 +34,17 @@ public class RealmService( // Cache the result for 5 minutes await cache.SetAsync(cacheKey, realms, TimeSpan.FromMinutes(5)); - + return realms; } - + public async Task SendInviteNotify(SnRealmMember member) { var account = await db.Accounts .Include(a => a.Profile) .FirstOrDefaultAsync(a => a.Id == member.AccountId); - + if (account == null) throw new InvalidOperationException("Account not found"); - - CultureService.SetCultureInfo(account.Language); await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest diff --git a/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs index 8ec2ea57..f2366be4 100644 --- a/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs +++ b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs @@ -118,8 +118,6 @@ public class RealmServiceGrpc( if (account == null) throw new RpcException(new Status(StatusCode.NotFound, "Account not found")); - CultureService.SetCultureInfo(account.Language); - await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { @@ -188,4 +186,4 @@ public class RealmServiceGrpc( return response; } -} \ No newline at end of file +} diff --git a/DysonNetwork.Shared/CultureService.cs b/DysonNetwork.Shared/CultureService.cs deleted file mode 100644 index 2c6db7dd..00000000 --- a/DysonNetwork.Shared/CultureService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Globalization; -using DysonNetwork.Shared.Proto; - -namespace DysonNetwork.Shared; - -public static class CultureService -{ - public static void SetCultureInfo(string? languageCode) - { - var info = new CultureInfo(languageCode ?? "en-us", false); - CultureInfo.CurrentCulture = info; - CultureInfo.CurrentUICulture = info; - } - - public static void SetCultureInfo(Account account) - { - SetCultureInfo(account.Language); - } -} \ No newline at end of file diff --git a/DysonNetwork.Sphere/Post/PostService.cs b/DysonNetwork.Sphere/Post/PostService.cs index 68ccbe0c..c4b66d8d 100644 --- a/DysonNetwork.Sphere/Post/PostService.cs +++ b/DysonNetwork.Sphere/Post/PostService.cs @@ -222,7 +222,6 @@ public partial class PostService( foreach (var member in queryResponse.Accounts) { if (member is null) continue; - CultureService.SetCultureInfo(member); await nty.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { @@ -230,7 +229,7 @@ public partial class PostService( Notification = new PushNotification { Topic = "post.replies", - Title = localizer.Get("postReplyTitle", args: new { user = sender!.Nick }), + Title = localizer.Get("postReplyTitle", locale: member.Language, args: new { user = sender!.Nick }), Body = ChopPostForNotification(post).content, IsSavable = true, ActionUri = $"/posts/{post.Id}" @@ -695,7 +694,6 @@ public partial class PostService( foreach (var member in queryResponse.Accounts) { if (member is null) continue; - CultureService.SetCultureInfo(member); await nty.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest @@ -704,10 +702,10 @@ public partial class PostService( Notification = new PushNotification { Topic = "posts.reactions.new", - Title = localizer.Get("postReactTitle", args: new { user = sender.Nick }), + Title = localizer.Get("postReactTitle", locale: member.Language, args: new { user = sender.Nick }), Body = string.IsNullOrWhiteSpace(post.Title) - ? localizer.Get("postReactBody", args: new { user = sender.Nick, reaction = reaction.Symbol }) - : localizer.Get("postReactContentBody", args: new { user = sender.Nick, reaction = reaction.Symbol, title = post.Title }), + ? localizer.Get("postReactBody", locale: member.Language, args: new { user = sender.Nick, reaction = reaction.Symbol }) + : localizer.Get("postReactContentBody", locale: member.Language, args: new { user = sender.Nick, reaction = reaction.Symbol, title = post.Title }), IsSavable = true, ActionUri = $"/posts/{post.Id}" } @@ -884,7 +882,7 @@ public partial class PostService( if (currentUser is not null) { var friendsResponse = await accounts.ListFriendsAsync(new ListRelationshipSimpleRequest - { AccountId = currentUser.Id }); + { AccountId = currentUser.Id }); userFriends = friendsResponse.AccountsId.Select(Guid.Parse).ToList(); publishers = await ps.GetUserPublishers(Guid.Parse(currentUser.Id)); } @@ -961,7 +959,7 @@ public partial class PostService( return false; if (post.Visibility == Shared.Models.PostVisibility.Friends && - !(post.Publisher.AccountId.HasValue && userFriends.Contains(post.Publisher.AccountId.Value) || isMember)) + !(post.Publisher is not null && post.Publisher.AccountId.HasValue && userFriends.Contains(post.Publisher.AccountId.Value) || isMember)) return false; // Public and Unlisted are allowed @@ -1148,7 +1146,6 @@ public partial class PostService( foreach (var member in queryResponse.Accounts) { if (member is null) continue; - CultureService.SetCultureInfo(member); await nty.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest @@ -1157,10 +1154,10 @@ public partial class PostService( Notification = new PushNotification { Topic = "posts.awards.new", - Title = localizer.Get("postAwardedTitle", args: new { user = sender.Nick }), + Title = localizer.Get("postAwardedTitle", locale: member.Language, args: new { user = sender.Nick }), Body = string.IsNullOrWhiteSpace(post.Title) - ? localizer.Get("postAwardedBody", args: new { user = sender.Nick, amount }) - : localizer.Get("postAwardedContentBody", args: new { user = sender.Nick, amount, title = post.Title }), + ? localizer.Get("postAwardedBody", locale: member.Language, args: new { user = sender.Nick, amount }) + : localizer.Get("postAwardedContentBody", locale: member.Language, args: new { user = sender.Nick, amount, title = post.Title }), IsSavable = true, ActionUri = $"/posts/{post.Id}" } @@ -1209,9 +1206,9 @@ public static class PostQueryExtensions .Where(e => (e.PublishedAt != null && now >= e.PublishedAt) || (e.PublisherId.HasValue && publishersId.Contains(e.PublisherId.Value))) .Where(e => e.Visibility != Shared.Models.PostVisibility.Private || - publishersId.Contains(e.PublisherId.Value)) + publishersId.Contains(e.PublisherId!.Value)) .Where(e => e.Visibility != Shared.Models.PostVisibility.Friends || - (e.Publisher.AccountId != null && userFriends.Contains(e.Publisher.AccountId.Value)) || - publishersId.Contains(e.PublisherId.Value)); + (e.Publisher!.AccountId != null && userFriends.Contains(e.Publisher.AccountId.Value)) || + publishersId.Contains(e.PublisherId!.Value)); } -} \ No newline at end of file +} diff --git a/DysonNetwork.Sphere/Publisher/PublisherSubscriptionService.cs b/DysonNetwork.Sphere/Publisher/PublisherSubscriptionService.cs index 50851005..e21f5bd9 100644 --- a/DysonNetwork.Sphere/Publisher/PublisherSubscriptionService.cs +++ b/DysonNetwork.Sphere/Publisher/PublisherSubscriptionService.cs @@ -114,11 +114,10 @@ public class PublisherSubscriptionService( { try { - CultureService.SetCultureInfo(target.Key); var notification = new PushNotification { Topic = "posts.new", - Title = localizer.Get("postSubscriptionTitle", args: new { publisher = post.Publisher!.Nick, title }), + Title = localizer.Get("postSubscriptionTitle", locale: target.Key, args: new { publisher = post.Publisher!.Nick, title }), Body = message, Meta = GrpcTypeHelper.ConvertObjectToByteString(data), IsSavable = true, @@ -215,4 +214,4 @@ public class PublisherSubscriptionService( return true; } -} \ No newline at end of file +}