diff --git a/Changelog.txt b/Changelog.txt
index 47ccf4112..b2639bf8c 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -4,6 +4,7 @@
4.0.9 (xth December 2024) BETA
* NEW:
* Add "Move all shot changes" shortcuts - thx acetilo
+ * Add DeepLX translate - thx rifatozkancomtr
* IMPROVED:
* Update Portuguese translation - thx hugok79
* Update Bulgarian translation - thx Калин
@@ -33,6 +34,7 @@
* Fix wrong dialog info text in FCE
* Fix for divide by zero in TTS
* Fix bug in "Change casing" - thx Hlsgs
+ * Fix enter in textbox in FCE - thx p1nkyy/Roger
4.0.8 (6th September 2024)
diff --git a/Dictionaries/hrv_OCRFixReplaceList.xml b/Dictionaries/hrv_OCRFixReplaceList.xml
index 5807bed34..16411bfae 100644
--- a/Dictionaries/hrv_OCRFixReplaceList.xml
+++ b/Dictionaries/hrv_OCRFixReplaceList.xml
@@ -2435,6 +2435,7 @@
+
@@ -4007,6 +4008,8 @@
+
+
@@ -5575,6 +5578,7 @@
+
@@ -5825,6 +5829,7 @@
+
@@ -5843,9 +5848,7 @@
-
-
-
+
diff --git a/LanguageBaseEnglish.xml b/LanguageBaseEnglish.xml
index b7a0591e3..ac88c29c2 100644
--- a/LanguageBaseEnglish.xml
+++ b/LanguageBaseEnglish.xml
@@ -3188,6 +3188,8 @@ Continue?
Auto-continue
Regenerate
Speed
+ Stability
+ Similarity
SMPTE timing
diff --git a/src/libse/AudioToText/WhisperPurfviewFasterWhisperModel.cs b/src/libse/AudioToText/WhisperPurfviewFasterWhisperModel.cs
index 684e6f12c..fc25160e6 100644
--- a/src/libse/AudioToText/WhisperPurfviewFasterWhisperModel.cs
+++ b/src/libse/AudioToText/WhisperPurfviewFasterWhisperModel.cs
@@ -1,7 +1,6 @@
using Nikse.SubtitleEdit.Core.Common;
using System.Collections.Generic;
using System.IO;
-using static System.Net.WebRequestMethods;
namespace Nikse.SubtitleEdit.Core.AudioToText
{
diff --git a/src/libse/AutoTranslate/DeepLXTranslate.cs b/src/libse/AutoTranslate/DeepLXTranslate.cs
new file mode 100644
index 000000000..5daba0ecb
--- /dev/null
+++ b/src/libse/AutoTranslate/DeepLXTranslate.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Nikse.SubtitleEdit.Core.Common;
+using Nikse.SubtitleEdit.Core.Translate;
+
+namespace Nikse.SubtitleEdit.Core.AutoTranslate
+{
+ ///
+ /// DeepLX translator - see https://github.com/OwO-Network/DeepLX
+ ///
+ public class DeepLXTranslate : IAutoTranslator
+ {
+ private string _apiUrl;
+ private HttpClient _client;
+
+ public static string StaticName { get; set; } = "DeepLX translate";
+ public override string ToString() => StaticName;
+ public string Name => StaticName;
+ public string Url => "https://github.com/OwO-Network/DeepLX";
+ public string Error { get; set; }
+ public int MaxCharacters => 1500;
+
+ public void Initialize()
+ {
+ if (string.IsNullOrEmpty(Configuration.Settings.Tools.AutoTranslateDeepLXUrl))
+ {
+ Configuration.Settings.Tools.AutoTranslateDeepLXUrl = "http://localhost:1188";
+ }
+ _apiUrl = Configuration.Settings.Tools.AutoTranslateDeepLXUrl;
+
+ _client = new HttpClient();
+ _client.BaseAddress = new Uri(_apiUrl.Trim().TrimEnd('/'));
+ }
+
+ public List GetSupportedSourceLanguages()
+ {
+ return new DeepLTranslate().GetSupportedSourceLanguages();
+ }
+
+ public List GetSupportedTargetLanguages()
+ {
+ return new DeepLTranslate().GetSupportedTargetLanguages();
+ }
+
+ public Task Translate(string text, string sourceLanguageCode, string targetLanguageCode, CancellationToken cancellationToken)
+ {
+ var postContent = new FormUrlEncodedContent(new[]
+ {
+ new KeyValuePair("text", text),
+ new KeyValuePair("target_lang", targetLanguageCode),
+ new KeyValuePair("source_lang", sourceLanguageCode),
+ });
+ var result = _client.PostAsync("/v2/translate", postContent, cancellationToken).Result;
+ var resultContent = result.Content.ReadAsStringAsync().Result;
+
+ if (!result.IsSuccessStatusCode)
+ {
+ SeLogger.Error("DeepLTranslate error: " + resultContent);
+ }
+
+ if (result.StatusCode == HttpStatusCode.Forbidden)
+ {
+ Error = resultContent;
+ throw new Exception("Forbidden! " + Environment.NewLine + Environment.NewLine + resultContent);
+ }
+
+ var resultList = new List();
+ var parser = new JsonParser();
+ var x = (Dictionary)parser.Parse(resultContent);
+ foreach (var k in x.Keys)
+ {
+ if (x[k] is List