From df50a7a922af6985096d9a9222fbd7484cb63b3f Mon Sep 17 00:00:00 2001 From: Nikolaj Olsson Date: Sun, 17 Dec 2023 12:48:53 +0100 Subject: [PATCH] Add "Formality" for DeepL --- LanguageBaseEnglish.xml | 1 + SubtitleEdit.sln.DotSettings | 1 + src/libse/AutoTranslate/DeepLTranslate.cs | 25 +++-- src/libse/Translate/TranslationPair.cs | 9 ++ .../Forms/Translate/AutoTranslate.Designer.cs | 59 +++++++++-- src/ui/Forms/Translate/AutoTranslate.cs | 98 ++++++++++++++++++- src/ui/Logic/Language.cs | 1 + src/ui/Logic/LanguageDeserializer.cs | 3 + src/ui/Logic/LanguageStructure.cs | 1 + 9 files changed, 181 insertions(+), 17 deletions(-) diff --git a/LanguageBaseEnglish.xml b/LanguageBaseEnglish.xml index b5bbba54c..eb0514792 100644 --- a/LanguageBaseEnglish.xml +++ b/LanguageBaseEnglish.xml @@ -1074,6 +1074,7 @@ To use an API key, go to "Options -> Settings -> Tools" to enter your Goog "{0}" requires a web server running locally! "{0}" requires an API key. Read more? + Formality Google vs Microsoft translate diff --git a/SubtitleEdit.sln.DotSettings b/SubtitleEdit.sln.DotSettings index b878fbaf2..9d0156b2c 100644 --- a/SubtitleEdit.sln.DotSettings +++ b/SubtitleEdit.sln.DotSettings @@ -22,6 +22,7 @@ True True True + True True True True diff --git a/src/libse/AutoTranslate/DeepLTranslate.cs b/src/libse/AutoTranslate/DeepLTranslate.cs index 0be2b6810..383de3255 100644 --- a/src/libse/AutoTranslate/DeepLTranslate.cs +++ b/src/libse/AutoTranslate/DeepLTranslate.cs @@ -59,28 +59,28 @@ namespace Nikse.SubtitleEdit.Core.AutoTranslate MakeTranslationPair("Chinese", "zh"), MakeTranslationPair("Czech", "cs"), MakeTranslationPair("Danish", "da"), - MakeTranslationPair("Dutch", "nl"), - MakeTranslationPair("English", "en"), + MakeTranslationPair("Dutch", "nl", true), + MakeTranslationPair("English", "en", true), MakeTranslationPair("Estonian", "et"), MakeTranslationPair("Finnish", "fi"), - MakeTranslationPair("French", "fr"), - MakeTranslationPair("German", "de"), + MakeTranslationPair("French", "fr", true), + MakeTranslationPair("German", "de", true), MakeTranslationPair("Greek", "el"), MakeTranslationPair("Hungarian", "hu"), MakeTranslationPair("Indonesian", "id"), - MakeTranslationPair("Italian", "it"), - MakeTranslationPair("Japanese", "ja"), + MakeTranslationPair("Italian", "it", true), + MakeTranslationPair("Japanese", "ja", true), MakeTranslationPair("Korean", "ko"), MakeTranslationPair("Latvian", "lv"), MakeTranslationPair("Lithuanian", "lt"), MakeTranslationPair("Norwegian (Bokmål)", "nb"), - MakeTranslationPair("Polish", "pl"), - MakeTranslationPair("Portuguese", "pt"), + MakeTranslationPair("Polish", "pl", true), + MakeTranslationPair("Portuguese", "pt", true), MakeTranslationPair("Romanian", "ro"), - MakeTranslationPair("Russian", "ru"), + MakeTranslationPair("Russian", "ru", true), MakeTranslationPair("Slovak", "sk"), MakeTranslationPair("Slovenian", "sl"), - MakeTranslationPair("Spanish", "es"), + MakeTranslationPair("Spanish", "es", true), MakeTranslationPair("Swedish", "sv"), MakeTranslationPair("Turkish", "tr"), MakeTranslationPair("Ukranian", "uk"), @@ -92,6 +92,11 @@ namespace Nikse.SubtitleEdit.Core.AutoTranslate return new TranslationPair(name, code, code); } + private static TranslationPair MakeTranslationPair(string name, string code, bool hasFormality) + { + return new TranslationPair(name, code, hasFormality); + } + public Task Translate(string text, string sourceLanguageCode, string targetLanguageCode) { var postContent = new FormUrlEncodedContent(new[] diff --git a/src/libse/Translate/TranslationPair.cs b/src/libse/Translate/TranslationPair.cs index d1051d3e9..1d270eb2e 100644 --- a/src/libse/Translate/TranslationPair.cs +++ b/src/libse/Translate/TranslationPair.cs @@ -9,6 +9,7 @@ namespace Nikse.SubtitleEdit.Core.Translate public string Code { get; } public string TwoLetterIsoLanguageName { get; } + public bool? HasFormality { get; set; } public TranslationPair(string name, string code) { @@ -23,6 +24,14 @@ namespace Nikse.SubtitleEdit.Core.Translate TwoLetterIsoLanguageName = twoLetterIsoLanguageName; } + public TranslationPair(string name, string code, bool hasFormality) + { + Name = name ?? string.Empty; + Code = code; + TwoLetterIsoLanguageName = code; + HasFormality = hasFormality; + } + public override string ToString() => Name.ToLowerInvariant().Replace('_', ' ').CapitalizeFirstLetter(); public bool Equals(TranslationPair other) => other != null && Code.Equals(other.Code); diff --git a/src/ui/Forms/Translate/AutoTranslate.Designer.cs b/src/ui/Forms/Translate/AutoTranslate.Designer.cs index 82eef78ec..ad0575bfc 100644 --- a/src/ui/Forms/Translate/AutoTranslate.Designer.cs +++ b/src/ui/Forms/Translate/AutoTranslate.Designer.cs @@ -58,6 +58,8 @@ this.comboBoxTarget = new Nikse.SubtitleEdit.Controls.NikseComboBox(); this.subtitleListViewTarget = new Nikse.SubtitleEdit.Controls.SubtitleListView(); this.subtitleListViewSource = new Nikse.SubtitleEdit.Controls.SubtitleListView(); + this.comboBoxFormality = new Nikse.SubtitleEdit.Controls.NikseComboBox(); + this.labelFormality = new Nikse.SubtitleEdit.Controls.NikseLabel(); this.contextMenuStrip2.SuspendLayout(); this.contextMenuStrip1.SuspendLayout(); this.SuspendLayout(); @@ -133,7 +135,7 @@ // this.labelUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelUrl.AutoSize = true; - this.labelUrl.Location = new System.Drawing.Point(14, 533); + this.labelUrl.Location = new System.Drawing.Point(14, 513); this.labelUrl.Name = "labelUrl"; this.labelUrl.Size = new System.Drawing.Size(23, 13); this.labelUrl.TabIndex = 106; @@ -242,7 +244,7 @@ // this.labelApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelApiKey.AutoSize = true; - this.labelApiKey.Location = new System.Drawing.Point(360, 533); + this.labelApiKey.Location = new System.Drawing.Point(360, 513); this.labelApiKey.Name = "labelApiKey"; this.labelApiKey.Size = new System.Drawing.Size(47, 13); this.labelApiKey.TabIndex = 111; @@ -252,7 +254,7 @@ // this.nikseTextBoxApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.nikseTextBoxApiKey.FocusedColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215))))); - this.nikseTextBoxApiKey.Location = new System.Drawing.Point(409, 532); + this.nikseTextBoxApiKey.Location = new System.Drawing.Point(409, 512); this.nikseTextBoxApiKey.Name = "nikseTextBoxApiKey"; this.nikseTextBoxApiKey.Size = new System.Drawing.Size(360, 20); this.nikseTextBoxApiKey.TabIndex = 110; @@ -295,7 +297,7 @@ this.nikseComboBoxUrl.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; this.nikseComboBoxUrl.DropDownWidth = 280; this.nikseComboBoxUrl.FormattingEnabled = true; - this.nikseComboBoxUrl.Location = new System.Drawing.Point(56, 528); + this.nikseComboBoxUrl.Location = new System.Drawing.Point(56, 508); this.nikseComboBoxUrl.MaxLength = 32767; this.nikseComboBoxUrl.Name = "nikseComboBoxUrl"; this.nikseComboBoxUrl.SelectedIndex = -1; @@ -352,6 +354,7 @@ this.comboBoxTarget.Size = new System.Drawing.Size(121, 23); this.comboBoxTarget.TabIndex = 95; this.comboBoxTarget.UsePopupWindow = false; + this.comboBoxTarget.SelectedIndexChanged += new System.EventHandler(this.comboBoxTarget_SelectedIndexChanged); // // subtitleListViewTarget // @@ -366,7 +369,7 @@ this.subtitleListViewTarget.Location = new System.Drawing.Point(465, 53); this.subtitleListViewTarget.Name = "subtitleListViewTarget"; this.subtitleListViewTarget.OwnerDraw = true; - this.subtitleListViewTarget.Size = new System.Drawing.Size(428, 458); + this.subtitleListViewTarget.Size = new System.Drawing.Size(428, 446); this.subtitleListViewTarget.SubtitleFontBold = false; this.subtitleListViewTarget.SubtitleFontName = "Tahoma"; this.subtitleListViewTarget.SubtitleFontSize = 8; @@ -389,7 +392,7 @@ this.subtitleListViewSource.Location = new System.Drawing.Point(12, 53); this.subtitleListViewSource.Name = "subtitleListViewSource"; this.subtitleListViewSource.OwnerDraw = true; - this.subtitleListViewSource.Size = new System.Drawing.Size(430, 458); + this.subtitleListViewSource.Size = new System.Drawing.Size(430, 446); this.subtitleListViewSource.SubtitleFontBold = false; this.subtitleListViewSource.SubtitleFontName = "Tahoma"; this.subtitleListViewSource.SubtitleFontSize = 8; @@ -400,12 +403,54 @@ this.subtitleListViewSource.Click += new System.EventHandler(this.subtitleListViewSource_Click); this.subtitleListViewSource.DoubleClick += new System.EventHandler(this.subtitleListViewSource_DoubleClick); // + // comboBoxFormality + // + this.comboBoxFormality.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.comboBoxFormality.BackColor = System.Drawing.SystemColors.Window; + this.comboBoxFormality.BackColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240))))); + this.comboBoxFormality.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179))))); + this.comboBoxFormality.BorderColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(120)))), ((int)(((byte)(120))))); + this.comboBoxFormality.ButtonForeColor = System.Drawing.SystemColors.ControlText; + this.comboBoxFormality.ButtonForeColorDown = System.Drawing.Color.Orange; + this.comboBoxFormality.ButtonForeColorOver = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215))))); + this.comboBoxFormality.DropDownHeight = 400; + this.comboBoxFormality.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxFormality.DropDownWidth = 280; + this.comboBoxFormality.FormattingEnabled = true; + this.comboBoxFormality.Items.AddRange(new object[] { + "default", + "more", + "less", + "prefer_more", + "prefer_less"}); + this.comboBoxFormality.Location = new System.Drawing.Point(71, 537); + this.comboBoxFormality.MaxLength = 32767; + this.comboBoxFormality.Name = "comboBoxFormality"; + this.comboBoxFormality.SelectedIndex = -1; + this.comboBoxFormality.SelectedItem = null; + this.comboBoxFormality.SelectedText = ""; + this.comboBoxFormality.Size = new System.Drawing.Size(280, 21); + this.comboBoxFormality.TabIndex = 112; + this.comboBoxFormality.UsePopupWindow = false; + // + // labelFormality + // + this.labelFormality.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.labelFormality.AutoSize = true; + this.labelFormality.Location = new System.Drawing.Point(14, 540); + this.labelFormality.Name = "labelFormality"; + this.labelFormality.Size = new System.Drawing.Size(51, 13); + this.labelFormality.TabIndex = 113; + this.labelFormality.Text = "Formality:"; + // // AutoTranslate // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1058, 563); this.ContextMenuStrip = this.contextMenuStrip1; + this.Controls.Add(this.labelFormality); + this.Controls.Add(this.comboBoxFormality); this.Controls.Add(this.labelApiKey); this.Controls.Add(this.nikseTextBoxApiKey); this.Controls.Add(this.linkLabelPoweredBy); @@ -472,5 +517,7 @@ private System.Windows.Forms.ToolStripMenuItem translateSingleLinesToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private System.Windows.Forms.ToolStripMenuItem translateSingleLinesToolStripMenuItem1; + private Nikse.SubtitleEdit.Controls.NikseComboBox comboBoxFormality; + private Nikse.SubtitleEdit.Controls.NikseLabel labelFormality; } } \ No newline at end of file diff --git a/src/ui/Forms/Translate/AutoTranslate.cs b/src/ui/Forms/Translate/AutoTranslate.cs index b61c998ea..f63311a08 100644 --- a/src/ui/Forms/Translate/AutoTranslate.cs +++ b/src/ui/Forms/Translate/AutoTranslate.cs @@ -48,6 +48,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate toolStripMenuItemStartLibre.Text = string.Format(LanguageSettings.Current.GoogleTranslate.StartWebServerX, new LibreTranslate().Name); toolStripMenuItemStartNLLBServe.Text = string.Format(LanguageSettings.Current.GoogleTranslate.StartWebServerX, new NoLanguageLeftBehindServe().Name); toolStripMenuItemStartNLLBApi.Text = string.Format(LanguageSettings.Current.GoogleTranslate.StartWebServerX, new NoLanguageLeftBehindApi().Name); + labelFormality.Text = LanguageSettings.Current.GoogleTranslate.Formality; + comboBoxFormality.Left = labelFormality.Right + 3; subtitleListViewSource.InitializeLanguage(LanguageSettings.Current.General, Configuration.Settings); subtitleListViewTarget.InitializeLanguage(LanguageSettings.Current.General, Configuration.Settings); @@ -153,6 +155,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate nikseComboBoxUrl.Visible = false; nikseTextBoxApiKey.Top = nikseComboBoxUrl.Top; labelApiKey.Text = LanguageSettings.Current.Settings.GoogleTranslateApiKey; + labelFormality.Visible = false; + comboBoxFormality.Visible = false; var engineType = _autoTranslator.GetType(); if (engineType == typeof(GoogleTranslateV1)) @@ -182,6 +186,9 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (engineType == typeof(DeepLTranslate)) { + labelFormality.Visible = true; + comboBoxFormality.Visible = true; + FillUrls(new List { Configuration.Settings.Tools.AutoTranslateDeepLUrl, @@ -193,6 +200,9 @@ namespace Nikse.SubtitleEdit.Forms.Translate nikseTextBoxApiKey.Left = labelApiKey.Right + 3; labelApiKey.Visible = true; nikseTextBoxApiKey.Visible = true; + + SelectFormality(); + return; } @@ -285,6 +295,19 @@ namespace Nikse.SubtitleEdit.Forms.Translate throw new Exception($"Engine {_autoTranslator.Name} not handled!"); } + private void SelectFormality() + { + comboBoxFormality.SelectedIndex = 0; + for (var i = 0; i < comboBoxFormality.Items.Count; i++) + { + if (comboBoxFormality.Items[i].ToString() == Configuration.Settings.Tools.AutoTranslateDeepLFormality) + { + comboBoxFormality.SelectedIndex = i; + break; + } + } + } + private void FillUrls(List list) { nikseComboBoxUrl.Items.Clear(); @@ -511,7 +534,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate subtitleListViewSource.Width = width; subtitleListViewTarget.Width = width; - var height = Height - (subtitleListViewSource.Top + buttonTranslate.Height + 60); + var height = Height - (subtitleListViewSource.Top + buttonTranslate.Height + 80); subtitleListViewSource.Height = height; subtitleListViewTarget.Height = height; @@ -576,6 +599,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (comboBoxSource.SelectedItem is TranslationPair source && comboBoxTarget.SelectedItem is TranslationPair target) { + SetFormality(target); + var mergeErrorCount = 0; Configuration.Settings.Tools.GoogleTranslateLastTargetLanguage = target.TwoLetterIsoLanguageName ?? target.Code; @@ -1044,5 +1069,76 @@ namespace Nikse.SubtitleEdit.Forms.Translate { SyncListViews(subtitleListViewSource, subtitleListViewTarget); } + + private void SetFormality(TranslationPair target) + { + if (comboBoxFormality.Visible && target?.HasFormality == true && comboBoxFormality.SelectedIndex > 0) + { + if (_autoTranslator.Name == DeepLTranslate.StaticName) + { + var f = string.Empty; + if (comboBoxFormality.SelectedIndex == 0) + { + f = string.Empty; + } + else if (comboBoxFormality.SelectedIndex == 1) + { + f = "more"; + } + else if (comboBoxFormality.SelectedIndex == 2) + { + f = "less"; + } + else if (comboBoxFormality.SelectedIndex == 3) + { + f = "prefer_more"; + } + else if (comboBoxFormality.SelectedIndex == 4) + { + f = "prefer_less"; + } + + Configuration.Settings.Tools.AutoTranslateDeepLFormality = f; + } + + } + } + + private void comboBoxTarget_SelectedIndexChanged(object sender, EventArgs e) + { + if (_autoTranslator.Name == DeepLTranslate.StaticName && comboBoxTarget.SelectedItem is TranslationPair target) + { + if (target.HasFormality == null || target.HasFormality == false) + { + labelFormality.Enabled = false; + comboBoxFormality.Enabled = false; + return; + } + + labelFormality.Enabled = true; + comboBoxFormality.Enabled = true; + + if (target.TwoLetterIsoLanguageName == "ja" && comboBoxFormality.Items.Count != 3) + { + comboBoxFormality.Items.Clear(); + comboBoxFormality.Items.Add("default"); + comboBoxFormality.Items.Add("more"); + comboBoxFormality.Items.Add("less"); + + SelectFormality(); + } + else if (comboBoxFormality.Items.Count != 3) + { + comboBoxFormality.Items.Clear(); + comboBoxFormality.Items.Add("default"); + comboBoxFormality.Items.Add("more"); + comboBoxFormality.Items.Add("less"); + comboBoxFormality.Items.Add("prefer_more"); + comboBoxFormality.Items.Add("prefer_less"); + + SelectFormality(); + } + } + } } } diff --git a/src/ui/Logic/Language.cs b/src/ui/Logic/Language.cs index 6f91e72f0..436c39d47 100644 --- a/src/ui/Logic/Language.cs +++ b/src/ui/Logic/Language.cs @@ -1331,6 +1331,7 @@ namespace Nikse.SubtitleEdit.Logic XRequiresALocalWebServer = "\"{0}\" requires a web server running locally!", XRequiresAnApiKey = "\"{0}\" requires an API key.", ReadMore = "Read more?", + Formality = "Formality", }; GoogleOrMicrosoftTranslate = new LanguageStructure.GoogleOrMicrosoftTranslate diff --git a/src/ui/Logic/LanguageDeserializer.cs b/src/ui/Logic/LanguageDeserializer.cs index 0d170fa5e..bc80a3905 100644 --- a/src/ui/Logic/LanguageDeserializer.cs +++ b/src/ui/Logic/LanguageDeserializer.cs @@ -2827,6 +2827,9 @@ namespace Nikse.SubtitleEdit.Logic case "GoogleTranslate/ReadMore": language.GoogleTranslate.ReadMore = reader.Value; break; + case "GoogleTranslate/Formality": + language.GoogleTranslate.Formality = reader.Value; + break; case "GoogleOrMicrosoftTranslate/Title": language.GoogleOrMicrosoftTranslate.Title = reader.Value; break; diff --git a/src/ui/Logic/LanguageStructure.cs b/src/ui/Logic/LanguageStructure.cs index 5a36115b6..9275a1401 100644 --- a/src/ui/Logic/LanguageStructure.cs +++ b/src/ui/Logic/LanguageStructure.cs @@ -1153,6 +1153,7 @@ public string XRequiresALocalWebServer { get; set; } public string XRequiresAnApiKey { get; set; } public string ReadMore { get; set; } + public string Formality { get; set; } } public class GoogleOrMicrosoftTranslate