Add MyMemory translation API

This commit is contained in:
niksedk 2023-10-07 11:47:40 +02:00
parent 1b0d70a562
commit 612120e334
6 changed files with 355 additions and 7 deletions

View File

@ -0,0 +1,215 @@
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Core.Http;
using Nikse.SubtitleEdit.Core.SubtitleFormats;
using Nikse.SubtitleEdit.Core.Translate;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Nikse.SubtitleEdit.Core.AutoTranslate
{
public class MyMemoryApi : IAutoTranslator
{
private IDownloader _httpClient;
public string Name { get; set; } = "MyMemory Translate";
public string Url => "https://mymemory.translated.net/";
public void Initialize()
{
_httpClient = DownloaderFactory.MakeHttpClient();
_httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=UTF-8");
_httpClient.BaseAddress = new Uri("https://api.mymemory.translated.net/get");
}
public List<TranslationPair> GetSupportedSourceLanguages()
{
return GetTranslationPairs();
}
public List<TranslationPair> GetSupportedTargetLanguages()
{
return GetTranslationPairs();
}
private static List<TranslationPair> GetTranslationPairs()
{
return new List<TranslationPair>
{
MakeLanguage("af-ZA", "Afrikaans"),
MakeLanguage("sq-AL", "Albanian"),
MakeLanguage("am-ET", "Amharic"),
MakeLanguage("ar-SA", "Arabic"),
MakeLanguage("hy-AM", "Armenian"),
MakeLanguage("az-AZ", "Azerbaijani"),
MakeLanguage("bjs-BB", "Bajan"),
MakeLanguage("rm-RO", "Balkan Gipsy"),
MakeLanguage("eu-ES", "Basque"),
MakeLanguage("bem-ZM", "Bemba"),
MakeLanguage("bn-IN", "Bengali"),
MakeLanguage("be-BY", "Bielarus"),
MakeLanguage("bi-VU", "Bislama"),
MakeLanguage("bs-BA", "Bosnian"),
MakeLanguage("br-FR", "Breton"),
MakeLanguage("bg-BG", "Bulgarian"),
MakeLanguage("my-MM", "Burmese"),
MakeLanguage("ca-ES", "Catalan"),
MakeLanguage("ceb-PH", "Cebuano"),
MakeLanguage("ch-GU", "Chamorro"),
MakeLanguage("zh-CN", "Chinese (Simplified)"),
MakeLanguage("zh-TW", "Chinese Traditional"),
MakeLanguage("zdj-KM", "Comorian (Ngazidja)"),
MakeLanguage("cop-EG", "Coptic"),
MakeLanguage("aig-AG", "Creole English (Antigua and Barbuda)"),
MakeLanguage("bah-BS", "Creole English (Bahamas)"),
MakeLanguage("gcl-GD", "Creole English (Grenadian)"),
MakeLanguage("gyn-GY", "Creole English (Guyanese)"),
MakeLanguage("jam-JM", "Creole English (Jamaican)"),
MakeLanguage("svc-VC", "Creole English (Vincentian)"),
MakeLanguage("vic-US", "Creole English (Virgin Islands)"),
MakeLanguage("ht-HT", "Creole French (Haitian)"),
MakeLanguage("acf-LC", "Creole French (Saint Lucian)"),
MakeLanguage("crs-SC", "Creole French (Seselwa)"),
MakeLanguage("pov-GW", "Creole Portuguese (Upper Guinea)"),
MakeLanguage("hr-HR", "Croatian"),
MakeLanguage("cs-CZ", "Czech"),
MakeLanguage("da-DK", "Danish"),
MakeLanguage("nl-NL", "Dutch"),
MakeLanguage("dz-BT", "Dzongkha"),
MakeLanguage("en-GB", "English"),
MakeLanguage("eo-EU", "Esperanto"),
MakeLanguage("et-EE", "Estonian"),
MakeLanguage("fn-FNG", "Fanagalo"),
MakeLanguage("fo-FO", "Faroese"),
MakeLanguage("fi-FI", "Finnish"),
MakeLanguage("fr-FR", "French"),
MakeLanguage("gl-ES", "Galician"),
MakeLanguage("ka-GE", "Georgian"),
MakeLanguage("de-DE", "German"),
MakeLanguage("el-GR", "Greek"),
MakeLanguage("grc-GR", "Greek (Classical)"),
MakeLanguage("gu-IN", "Gujarati"),
MakeLanguage("ha-NE", "Hausa"),
MakeLanguage("haw-US", "Hawaiian"),
MakeLanguage("he-IL", "Hebrew"),
MakeLanguage("hi-IN", "Hindi"),
MakeLanguage("hu-HU", "Hungarian"),
MakeLanguage("is-IS", "Icelandic"),
MakeLanguage("id-ID", "Indonesian"),
MakeLanguage("kl-GL", "Inuktitut (Greenlandic)"),
MakeLanguage("ga-IE", "Irish Gaelic"),
MakeLanguage("it-IT", "Italian"),
MakeLanguage("ja-JP", "Japanese"),
MakeLanguage("jv-ID", "Javanese"),
MakeLanguage("kea-CV", "Kabuverdianu"),
MakeLanguage("kab-DZ", "Kabylian"),
MakeLanguage("kn-IN", "Kannada"),
MakeLanguage("kk-KZ", "Kazakh"),
MakeLanguage("km-KM", "Khmer"),
MakeLanguage("rw-RW", "Kinyarwanda"),
MakeLanguage("rn-BI", "Kirundi"),
MakeLanguage("ko-KR", "Korean"),
MakeLanguage("ku-TR", "Kurdish"),
MakeLanguage("ckb-IQ", "Kurdish Sorani"),
MakeLanguage("ky-KG", "Kyrgyz"),
MakeLanguage("lo-LA", "Lao"),
MakeLanguage("la-VA", "Latin"),
MakeLanguage("lv-LV", "Latvian"),
MakeLanguage("lt-LT", "Lithuanian"),
MakeLanguage("lb-LU", "Luxembourgish"),
MakeLanguage("mk-MK", "Macedonian"),
MakeLanguage("mg-MG", "Malagasy"),
MakeLanguage("ms-MY", "Malay"),
MakeLanguage("dv-MV", "Maldivian"),
MakeLanguage("mt-MT", "Maltese"),
MakeLanguage("gv-IM", "Manx Gaelic"),
MakeLanguage("mi-NZ", "Maori"),
MakeLanguage("mh-MH", "Marshallese"),
MakeLanguage("men-SL", "Mende"),
MakeLanguage("mn-MN", "Mongolian"),
MakeLanguage("mfe-MU", "Morisyen"),
MakeLanguage("ne-NP", "Nepali"),
MakeLanguage("niu-NU", "Niuean"),
MakeLanguage("no-NO", "Norwegian"),
MakeLanguage("ny-MW", "Nyanja"),
MakeLanguage("ur-PK", "Pakistani"),
MakeLanguage("pau-PW", "Palauan"),
MakeLanguage("pa-IN", "Panjabi"),
MakeLanguage("pap-CW", "Papiamentu"),
MakeLanguage("ps-PK", "Pashto"),
MakeLanguage("fa-IR", "Persian"),
MakeLanguage("pis-SB", "Pijin"),
MakeLanguage("pl-PL", "Polish"),
MakeLanguage("pt-PT", "Portuguese"),
MakeLanguage("pot-US", "Potawatomi"),
MakeLanguage("qu-PE", "Quechua"),
MakeLanguage("ro-RO", "Romanian"),
MakeLanguage("ru-RU", "Russian"),
MakeLanguage("sm-WS", "Samoan"),
MakeLanguage("sg-CF", "Sango"),
MakeLanguage("gd-GB", "Scots Gaelic"),
MakeLanguage("sr-RS", "Serbian"),
MakeLanguage("sn-ZW", "Shona"),
MakeLanguage("si-LK", "Sinhala"),
MakeLanguage("sk-SK", "Slovak"),
MakeLanguage("sl-SI", "Slovenian"),
MakeLanguage("so-SO", "Somali"),
MakeLanguage("st-ST", "Sotho, Southern"),
MakeLanguage("es-ES", "Spanish"),
MakeLanguage("srn-SR", "Sranan Tongo"),
MakeLanguage("sw-SZ", "Swahili"),
MakeLanguage("sv-SE", "Swedish"),
MakeLanguage("de-CH", "Swiss German"),
MakeLanguage("syc-TR", "Syriac (Aramaic)"),
MakeLanguage("tl-PH", "Tagalog"),
MakeLanguage("tg-TJ", "Tajik"),
MakeLanguage("tmh-DZ", "Tamashek (Tuareg)"),
MakeLanguage("ta-LK", "Tamil"),
MakeLanguage("te-IN", "Telugu"),
MakeLanguage("tet-TL", "Tetum"),
MakeLanguage("th-TH", "Thai"),
MakeLanguage("bo-CN", "Tibetan"),
MakeLanguage("ti-TI", "Tigrinya"),
MakeLanguage("tpi-PG", "Tok Pisin"),
MakeLanguage("tkl-TK", "Tokelauan"),
MakeLanguage("to-TO", "Tongan"),
MakeLanguage("tn-BW", "Tswana"),
MakeLanguage("tr-TR", "Turkish"),
MakeLanguage("tk-TM", "Turkmen"),
MakeLanguage("tvl-TV", "Tuvaluan"),
MakeLanguage("uk-UA", "Ukrainian"),
MakeLanguage("ppk-ID", "Uma"),
MakeLanguage("uz-UZ", "Uzbek"),
MakeLanguage("vi-VN", "Vietnamese"),
MakeLanguage("wls-WF", "Wallisian"),
MakeLanguage("cy-GB", "Welsh"),
MakeLanguage("wo-SN", "Wolof"),
MakeLanguage("xh-ZA", "Xhosa"),
MakeLanguage("yi-YD", "Yiddish"),
MakeLanguage("zu-ZA", "Zulu"),
};
}
private static TranslationPair MakeLanguage(string code, string name)
{
return new TranslationPair(name, code);
}
public Task<string> Translate(string text, string sourceLanguageCode, string targetLanguageCode)
{
var apiKey = string.Empty;
if (!string.IsNullOrEmpty(Configuration.Settings.Tools.AutoTranslateLibreApiKey))
{
apiKey = "&api_key=" + Configuration.Settings.Tools.AutoTranslateMyMemoryApiKey;
}
var url = $"?langpair={sourceLanguageCode}|{targetLanguageCode}{apiKey}&q={Utilities.UrlEncode(text)}";
var jsonResultString = _httpClient.GetStringAsync(url).Result;
var parser = new SeJsonParser();
var textResult = parser.GetFirstObject(jsonResultString, "translatedText");
var result = Json.DecodeJsonText(textResult);
return Task.FromResult(result);
}
}
}

View File

@ -159,6 +159,7 @@ namespace Nikse.SubtitleEdit.Core.Common
public string AutoTranslateNllbServeModel { get; set; }
public string AutoTranslateLibreUrl { get; set; }
public string AutoTranslateLibreApiKey { get; set; }
public string AutoTranslateMyMemoryApiKey { get; set; }
public bool TranslateAllowSplit { get; set; }
public string TranslateLastService { get; set; }
public string TranslateMergeStrategy { get; set; }
@ -5106,6 +5107,12 @@ $HorzAlign = Center
settings.Tools.AutoTranslateLibreApiKey = subNode.InnerText;
}
subNode = node.SelectSingleNode("AutoTranslateMyMemoryApiKey");
if (subNode != null)
{
settings.Tools.AutoTranslateMyMemoryApiKey = subNode.InnerText;
}
subNode = node.SelectSingleNode("TranslateAllowSplit");
if (subNode != null)
{
@ -11367,6 +11374,7 @@ $HorzAlign = Center
textWriter.WriteElementString("AutoTranslateNllbServeModel", settings.Tools.AutoTranslateNllbServeModel);
textWriter.WriteElementString("AutoTranslateLibreUrl", settings.Tools.AutoTranslateLibreUrl);
textWriter.WriteElementString("AutoTranslateLibreApiKey", settings.Tools.AutoTranslateLibreApiKey);
textWriter.WriteElementString("AutoTranslateMyMemoryApiKey", settings.Tools.AutoTranslateMyMemoryApiKey);
textWriter.WriteElementString("TranslateAllowSplit", settings.Tools.TranslateAllowSplit.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("TranslateLastService", settings.Tools.TranslateLastService);
textWriter.WriteElementString("TranslateMergeStrategy", settings.Tools.TranslateMergeStrategy);

View File

@ -37,11 +37,29 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
text = text.Replace("<br />", Environment.NewLine);
text = text.Replace("<br>", Environment.NewLine);
text = text.Replace("<br/>", Environment.NewLine);
text = text.Replace("\\r\\n", Environment.NewLine);
text = text.Replace("\\n", Environment.NewLine);
bool keepNext = false;
var sb = new StringBuilder(text.Length);
var list = text.SplitToLines();
for (var index = 0; index < list.Count; index++)
{
var line = list[index];
DecodeJsonText(line, sb);
if (index < list.Count - 1)
{
sb.AppendLine();
}
}
return sb.ToString();
}
private static void DecodeJsonText(string text, StringBuilder sb)
{
text = string.Join(Environment.NewLine, text.SplitToLines());
var keepNext = false;
var hexLetters = "01234567890abcdef";
int i = 0;
var i = 0;
while (i < text.Length)
{
char c = text[i];
@ -68,8 +86,6 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
i++;
}
return sb.ToString();
}
public override string ToText(Subtitle subtitle, string title)

View File

@ -473,6 +473,11 @@
this.labelNllbApiUrl = new System.Windows.Forms.Label();
this.linkLabelNllbApi = new System.Windows.Forms.LinkLabel();
this.label5 = new System.Windows.Forms.Label();
this.groupBoxMyMemory = new System.Windows.Forms.GroupBox();
this.nikseTextBoxMyMemoryApiKey = new Nikse.SubtitleEdit.Controls.NikseTextBox();
this.labelMyMemoryApiKey = new System.Windows.Forms.Label();
this.linkLabelMyMemoryTranslate = new System.Windows.Forms.LinkLabel();
this.label8 = new System.Windows.Forms.Label();
this.panelGeneral.SuspendLayout();
this.groupBoxMiscellaneous.SuspendLayout();
this.groupBoxGeneralRules.SuspendLayout();
@ -552,6 +557,7 @@
this.groupBoxLibreTranslate.SuspendLayout();
this.groupBoxNllbServe.SuspendLayout();
this.groupBoxNllbApi.SuspendLayout();
this.groupBoxMyMemory.SuspendLayout();
this.SuspendLayout();
//
// buttonOK
@ -6411,6 +6417,7 @@
//
// panelAutoTranslate
//
this.panelAutoTranslate.Controls.Add(this.groupBoxMyMemory);
this.panelAutoTranslate.Controls.Add(this.groupBoxLibreTranslate);
this.panelAutoTranslate.Controls.Add(this.groupBoxNllbServe);
this.panelAutoTranslate.Controls.Add(this.groupBoxNllbApi);
@ -6617,6 +6624,58 @@
this.label5.Size = new System.Drawing.Size(0, 13);
this.label5.TabIndex = 25;
//
// groupBoxMyMemory
//
this.groupBoxMyMemory.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBoxMyMemory.Controls.Add(this.nikseTextBoxMyMemoryApiKey);
this.groupBoxMyMemory.Controls.Add(this.labelMyMemoryApiKey);
this.groupBoxMyMemory.Controls.Add(this.linkLabelMyMemoryTranslate);
this.groupBoxMyMemory.Controls.Add(this.label8);
this.groupBoxMyMemory.Location = new System.Drawing.Point(431, 174);
this.groupBoxMyMemory.Name = "groupBoxMyMemory";
this.groupBoxMyMemory.Size = new System.Drawing.Size(408, 95);
this.groupBoxMyMemory.TabIndex = 38;
this.groupBoxMyMemory.TabStop = false;
this.groupBoxMyMemory.Text = "MyMemory API";
//
// nikseTextBoxMyMemoryApiKey
//
this.nikseTextBoxMyMemoryApiKey.FocusedColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
this.nikseTextBoxMyMemoryApiKey.Location = new System.Drawing.Point(8, 55);
this.nikseTextBoxMyMemoryApiKey.Name = "nikseTextBoxMyMemoryApiKey";
this.nikseTextBoxMyMemoryApiKey.Size = new System.Drawing.Size(376, 21);
this.nikseTextBoxMyMemoryApiKey.TabIndex = 36;
//
// labelMyMemoryApiKey
//
this.labelMyMemoryApiKey.AutoSize = true;
this.labelMyMemoryApiKey.Location = new System.Drawing.Point(6, 37);
this.labelMyMemoryApiKey.Name = "labelMyMemoryApiKey";
this.labelMyMemoryApiKey.Size = new System.Drawing.Size(44, 13);
this.labelMyMemoryApiKey.TabIndex = 35;
this.labelMyMemoryApiKey.Text = "API key";
//
// linkLabelMyMemoryTranslate
//
this.linkLabelMyMemoryTranslate.AutoSize = true;
this.linkLabelMyMemoryTranslate.Location = new System.Drawing.Point(332, 16);
this.linkLabelMyMemoryTranslate.Name = "linkLabelMyMemoryTranslate";
this.linkLabelMyMemoryTranslate.Size = new System.Drawing.Size(52, 13);
this.linkLabelMyMemoryTranslate.TabIndex = 24;
this.linkLabelMyMemoryTranslate.TabStop = true;
this.linkLabelMyMemoryTranslate.Text = "More info";
this.linkLabelMyMemoryTranslate.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelMyMemoryTranslate_LinkClicked);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(16, 106);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(0, 13);
this.label8.TabIndex = 25;
//
// Settings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -6764,6 +6823,8 @@
this.groupBoxNllbServe.PerformLayout();
this.groupBoxNllbApi.ResumeLayout(false);
this.groupBoxNllbApi.PerformLayout();
this.groupBoxMyMemory.ResumeLayout(false);
this.groupBoxMyMemory.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -7215,5 +7276,10 @@
private Controls.NikseTextBox nikseTextBoxNllbServeModel;
private Controls.NikseTextBox nikseTextBoxLibreTranslateApiKey;
private System.Windows.Forms.Label labelLibreApiKey;
private System.Windows.Forms.GroupBox groupBoxMyMemory;
private Controls.NikseTextBox nikseTextBoxMyMemoryApiKey;
private System.Windows.Forms.Label labelMyMemoryApiKey;
private System.Windows.Forms.LinkLabel linkLabelMyMemoryTranslate;
private System.Windows.Forms.Label label8;
}
}

View File

@ -908,6 +908,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
labelLibreUrl.Text = LanguageSettings.Current.Main.Url;
labelNllbApiUrl.Text = LanguageSettings.Current.Main.Url;
labelNllbServeUrl.Text = LanguageSettings.Current.Main.Url;
labelMyMemoryApiKey.Text = language.GoogleTranslateApiKey;
groupBoxBing.Text = language.MicrosoftBingTranslator;
labelBingApiKey.Text = language.MicrosoftTranslateApiKey;
@ -1123,6 +1124,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
nikseTextBoxNllbServeModel.Text = Configuration.Settings.Tools.AutoTranslateNllbServeModel;
nikseTextBoxLibreTranslateUrl.Text = Configuration.Settings.Tools.AutoTranslateLibreUrl;
nikseTextBoxLibreTranslateApiKey.Text = Configuration.Settings.Tools.AutoTranslateLibreApiKey;
nikseTextBoxMyMemoryApiKey.Text = Configuration.Settings.Tools.AutoTranslateMyMemoryApiKey;
buttonReset.Text = LanguageSettings.Current.Settings.RestoreDefaultSettings;
buttonOK.Text = LanguageSettings.Current.General.Ok;
@ -2288,6 +2290,7 @@ namespace Nikse.SubtitleEdit.Forms.Options
toolsSettings.AutoTranslateNllbServeModel = nikseTextBoxNllbServeModel.Text;
toolsSettings.AutoTranslateLibreUrl = nikseTextBoxLibreTranslateUrl.Text;
toolsSettings.AutoTranslateLibreApiKey = nikseTextBoxLibreTranslateApiKey.Text.Trim();
toolsSettings.AutoTranslateMyMemoryApiKey = nikseTextBoxMyMemoryApiKey.Text;
var proxy = Configuration.Settings.Proxy;
proxy.ProxyAddress = textBoxProxyAddress.Text;
@ -3947,5 +3950,10 @@ namespace Nikse.SubtitleEdit.Forms.Options
{
UiUtil.OpenUrl(new LibreTranslate().Url);
}
private void linkLabelMyMemoryTranslate_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
UiUtil.OpenUrl(new MyMemoryApi().Url);
}
}
}

View File

@ -107,6 +107,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate
new LibreTranslate(),
new NoLanguageLeftBehindServe(),
new NoLanguageLeftBehindApi(),
new MyMemoryApi(),
};
if (!string.IsNullOrEmpty(Configuration.Settings.Tools.MicrosoftTranslatorApiKey) &&
@ -197,6 +198,13 @@ namespace Nikse.SubtitleEdit.Forms.Translate
return;
}
if (engineType == typeof(MyMemoryApi))
{
labelUrl.Visible = false;
nikseComboBoxUrl.Visible = false;
return;
}
throw new Exception($"Engine {_autoTranslator.Name} not handled!");
}
@ -238,8 +246,6 @@ namespace Nikse.SubtitleEdit.Forms.Translate
Configuration.Settings.Tools.AutoTranslateLibreUrl = url;
return;
}
throw new Exception($"Engine {engine.Name} not handled!");
}
private void SetupLanguageSettings()
@ -259,12 +265,41 @@ namespace Nikse.SubtitleEdit.Forms.Translate
var threeLetterLanguageCode = Iso639Dash2LanguageCode.GetThreeLetterCodeFromTwoLetterCode(languageIsoCode);
foreach (TranslationPair item in comboBox.Items)
{
if (item.Code.Contains('-'))
{
var arr = item.Code.ToLowerInvariant().Split('-');
if (arr[0].Length == 2 && arr[0] == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;
}
if (arr[0].Length == 3 && arr[0] == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;
}
if (arr[1].Length == 2 && arr[1] == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;
}
if (arr[1].Length == 3 && arr[1] == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;
}
}
if (languageIsoCode.Length == 2 && item.Code == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;
}
else if (item.Code.StartsWith(threeLetterLanguageCode) || item.Code == languageIsoCode)
if (item.Code.StartsWith(threeLetterLanguageCode) || item.Code == languageIsoCode)
{
comboBox.SelectedIndex = i;
return;