diff --git a/dotnet/src/Easydict.TranslationService/Services/DeepLService.cs b/dotnet/src/Easydict.TranslationService/Services/DeepLService.cs index 542af83..3ad67cb 100644 --- a/dotnet/src/Easydict.TranslationService/Services/DeepLService.cs +++ b/dotnet/src/Easydict.TranslationService/Services/DeepLService.cs @@ -156,10 +156,10 @@ private async Task TranslateWebAsync( TranslationRequest request, CancellationToken cancellationToken) { - var targetCode = GetDeepLWebLanguageCode(request.ToLanguage); + var targetCode = GetDeepLLanguageCode(request.ToLanguage, isWeb: true); var sourceCode = request.FromLanguage == Language.Auto ? "auto" - : GetDeepLWebLanguageCode(request.FromLanguage); + : GetDeepLLanguageCode(request.FromLanguage, isWeb: true); // Generate anti-detection values (matching macOS implementation) var requestId = GetRandomRequestId(); @@ -385,9 +385,10 @@ private TranslationResult ParseWebResponse(string json, TranslationRequest reque } /// - /// Get language code for official DeepL API. + /// Get language code for DeepL API or web JSON-RPC. + /// The only difference is Portuguese: API uses "PT", web uses "PT-PT". /// - private static string GetDeepLLanguageCode(Language language) => language switch + private static string GetDeepLLanguageCode(Language language, bool isWeb = false) => language switch { Language.SimplifiedChinese => "ZH", Language.TraditionalChinese => "ZH-HANT", @@ -396,40 +397,7 @@ private TranslationResult ParseWebResponse(string json, TranslationRequest reque Language.Korean => "KO", Language.French => "FR", Language.Spanish => "ES", - Language.Portuguese => "PT", - Language.Italian => "IT", - Language.German => "DE", - Language.Russian => "RU", - Language.Dutch => "NL", - Language.Polish => "PL", - Language.Bulgarian => "BG", - Language.Czech => "CS", - Language.Danish => "DA", - Language.Finnish => "FI", - Language.Greek => "EL", - Language.Hungarian => "HU", - Language.Indonesian => "ID", - Language.Norwegian => "NB", - Language.Romanian => "RO", - Language.Swedish => "SV", - Language.Turkish => "TR", - Language.Ukrainian => "UK", - _ => language.ToIso639().ToUpper() - }; - - /// - /// Get language code for DeepL web JSON-RPC (slightly different format). - /// - private static string GetDeepLWebLanguageCode(Language language) => language switch - { - Language.SimplifiedChinese => "ZH", - Language.TraditionalChinese => "ZH-HANT", - Language.English => "EN", - Language.Japanese => "JA", - Language.Korean => "KO", - Language.French => "FR", - Language.Spanish => "ES", - Language.Portuguese => "PT-PT", + Language.Portuguese => isWeb ? "PT-PT" : "PT", Language.Italian => "IT", Language.German => "DE", Language.Russian => "RU", diff --git a/dotnet/src/Easydict.TranslationService/Services/GeminiService.cs b/dotnet/src/Easydict.TranslationService/Services/GeminiService.cs index 9ee4329..8dd62f4 100644 --- a/dotnet/src/Easydict.TranslationService/Services/GeminiService.cs +++ b/dotnet/src/Easydict.TranslationService/Services/GeminiService.cs @@ -169,6 +169,7 @@ private static async IAsyncEnumerable ParseGeminiStreamAsync( { using var reader = new StreamReader(stream); + while (!reader.EndOfStream) { var line = await reader.ReadLineAsync(cancellationToken); diff --git a/dotnet/src/Easydict.WinUI/Services/HotkeyService.cs b/dotnet/src/Easydict.WinUI/Services/HotkeyService.cs index c20228d..4986417 100644 --- a/dotnet/src/Easydict.WinUI/Services/HotkeyService.cs +++ b/dotnet/src/Easydict.WinUI/Services/HotkeyService.cs @@ -26,8 +26,8 @@ public sealed class HotkeyService : IDisposable private readonly Window _window; private readonly nint _hwnd; - private bool _isDisposed; - private bool _isInitialized; + private volatile bool _isDisposed; + private volatile bool _isInitialized; // Window subclass delegate - must keep reference to prevent GC private delegate nint SubclassProc(nint hWnd, uint uMsg, nint wParam, nint lParam, nuint uIdSubclass, nuint dwRefData); diff --git a/dotnet/tests/Easydict.TranslationService.Tests/Services/DoubaoServiceTests.cs b/dotnet/tests/Easydict.TranslationService.Tests/Services/DoubaoServiceTests.cs index 808234d..f31d751 100644 --- a/dotnet/tests/Easydict.TranslationService.Tests/Services/DoubaoServiceTests.cs +++ b/dotnet/tests/Easydict.TranslationService.Tests/Services/DoubaoServiceTests.cs @@ -387,6 +387,37 @@ public async Task TranslateStreamAsync_SendsBearerToken() auth.Should().Be("Bearer my-doubao-key"); } + [Fact] + public async Task TranslateAsync_TrimsWhitespace_WhenNoSurroundingQuotes() + { + // Arrange + _service.Configure("test-key"); + + var sseContent = new StringBuilder(); + sseContent.AppendLine("event: response.output_text.delta"); + sseContent.AppendLine("""data: {"delta":" Hello World \n"}"""); + sseContent.AppendLine(); + sseContent.AppendLine("data: [DONE]"); + + var response = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(sseContent.ToString(), Encoding.UTF8, "text/event-stream") + }; + _mockHandler.EnqueueResponse(response); + + var request = new TranslationRequest + { + Text = "你好世界", + ToLanguage = Language.English + }; + + // Act + var result = await _service.TranslateAsync(request); + + // Assert - whitespace should be trimmed even without surrounding quotes + result.TranslatedText.Should().Be("Hello World"); + } + [Theory] [InlineData(Language.SimplifiedChinese, "zh")] [InlineData(Language.TraditionalChinese, "zh-Hant")]