diff --git a/BetterGenshinImpact/App.xaml b/BetterGenshinImpact/App.xaml
index a9c8ca584e..dd12713789 100644
--- a/BetterGenshinImpact/App.xaml
+++ b/BetterGenshinImpact/App.xaml
@@ -25,6 +25,7 @@
+
diff --git a/BetterGenshinImpact/App.xaml.cs b/BetterGenshinImpact/App.xaml.cs
index b4a1f38caa..02f735bd5b 100644
--- a/BetterGenshinImpact/App.xaml.cs
+++ b/BetterGenshinImpact/App.xaml.cs
@@ -86,7 +86,13 @@ public partial class App : Application
}
Log.Logger = loggerConfiguration.CreateLogger();
- services.AddLogging(c => c.AddSerilog());
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddLogging(logging =>
+ {
+ logging.ClearProviders();
+ logging.Services.AddSingleton();
+ });
services.AddLocalization();
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index 056924e35f..c3ebcbb766 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -84,6 +84,7 @@
+
@@ -200,6 +201,9 @@
Always
+
+ PreserveNewest
+
diff --git a/BetterGenshinImpact/Core/Config/OtherConfig.cs b/BetterGenshinImpact/Core/Config/OtherConfig.cs
index 491e68886b..ac65d2b77b 100644
--- a/BetterGenshinImpact/Core/Config/OtherConfig.cs
+++ b/BetterGenshinImpact/Core/Config/OtherConfig.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Model;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -121,4 +121,4 @@ public partial class Ocr : ObservableObject
///
[ObservableProperty]
private string _uiCultureInfoName = "zh-Hans";
-}
\ No newline at end of file
+}
diff --git a/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs
index 4d411ff0db..75266cd1fa 100644
--- a/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs
+++ b/BetterGenshinImpact/Core/Script/ScriptRepoUpdater.cs
@@ -21,7 +21,6 @@
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
-using Windows.UI.Xaml.Automation;
using BetterGenshinImpact.View.Windows;
using LibGit2Sharp;
using LibGit2Sharp.Handlers;
diff --git a/BetterGenshinImpact/Helpers/TranslatingSerilogLoggerProvider.cs b/BetterGenshinImpact/Helpers/TranslatingSerilogLoggerProvider.cs
new file mode 100644
index 0000000000..6b72fc443e
--- /dev/null
+++ b/BetterGenshinImpact/Helpers/TranslatingSerilogLoggerProvider.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using BetterGenshinImpact.Service.Interface;
+using Microsoft.Extensions.Logging;
+using Serilog;
+using Serilog.Events;
+
+namespace BetterGenshinImpact.Helpers;
+
+public sealed class TranslatingSerilogLoggerProvider : ILoggerProvider
+{
+ private readonly ITranslationService _translationService;
+
+ public TranslatingSerilogLoggerProvider(ITranslationService translationService)
+ {
+ _translationService = translationService;
+ }
+
+ public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName)
+ {
+ return new TranslatingSerilogLogger(categoryName, _translationService);
+ }
+
+ public void Dispose()
+ {
+ }
+
+ private sealed class TranslatingSerilogLogger : Microsoft.Extensions.Logging.ILogger
+ {
+ private readonly ITranslationService _translationService;
+ private readonly Serilog.ILogger _logger;
+
+ public TranslatingSerilogLogger(string categoryName, ITranslationService translationService)
+ {
+ _translationService = translationService;
+ _logger = Serilog.Log.Logger.ForContext("SourceContext", categoryName);
+ }
+
+ public IDisposable BeginScope(TState state) where TState : notnull
+ {
+ return NullScope.Instance;
+ }
+
+ public bool IsEnabled(LogLevel logLevel)
+ {
+ return logLevel != LogLevel.None;
+ }
+
+ public void Log(
+ LogLevel logLevel,
+ EventId eventId,
+ TState state,
+ Exception? exception,
+ Func formatter)
+ {
+ if (!IsEnabled(logLevel))
+ {
+ return;
+ }
+
+ var serilogLevel = ConvertLevel(logLevel);
+ if (serilogLevel == null)
+ {
+ return;
+ }
+
+ var (template, values) = ExtractTemplateAndValues(state, formatter, exception);
+ var translatedTemplate = _translationService.Translate(template, TranslationSourceInfo.From(MissingTextSource.Log));
+
+ if (values.Length == 0)
+ {
+ _logger.Write(serilogLevel.Value, exception, translatedTemplate);
+ return;
+ }
+
+ _logger.Write(serilogLevel.Value, exception, translatedTemplate, values);
+ }
+
+ private (string Template, object?[] Values) ExtractTemplateAndValues(
+ TState state,
+ Func formatter,
+ Exception? exception)
+ {
+ if (state is IReadOnlyList> kvps)
+ {
+ var original = kvps.FirstOrDefault(kv => string.Equals(kv.Key, "{OriginalFormat}", StringComparison.Ordinal));
+ var template = original.Value as string;
+ if (string.IsNullOrEmpty(template))
+ {
+ template = formatter(state, exception);
+ }
+
+ var values = kvps
+ .Where(kv =>
+ !string.Equals(kv.Key, "{OriginalFormat}", StringComparison.Ordinal) &&
+ !string.Equals(kv.Key, "EventId", StringComparison.Ordinal))
+ .Select(kv => kv.Value)
+ .ToArray();
+
+ return (template ?? string.Empty, values);
+ }
+
+ return (formatter(state, exception), Array.Empty