From f98c0a1eda5b31174733378861fe0e87cf9e2bbe Mon Sep 17 00:00:00 2001 From: Nikolaj Olsson Date: Thu, 7 Dec 2023 19:33:43 +0100 Subject: [PATCH] Work on translate --- Changelog.txt | 1 + src/libse/AutoTranslate/LibreTranslate.cs | 2 +- src/libse/Common/Settings.cs | 8 + src/libse/Translate/Formatting.cs | 2 +- src/ui/Forms/ExportPngXml.cs | 4 +- src/ui/Forms/Main.cs | 75 +++ src/ui/Forms/Options/Settings.cs | 1 + .../Forms/Translate/AutoTranslate.Designer.cs | 82 +-- src/ui/Forms/Translate/AutoTranslate.cs | 68 ++- src/ui/Forms/Translate/MergeAndSplitHelper.cs | 575 +++++------------- src/ui/Forms/Translate/MergeResult.cs | 17 + src/ui/Forms/Translate/MergeResultItem.cs | 21 + src/ui/Logic/MainShortcuts.cs | 2 + src/ui/SubtitleEdit.csproj | 2 + 14 files changed, 380 insertions(+), 480 deletions(-) create mode 100644 src/ui/Forms/Translate/MergeResult.cs create mode 100644 src/ui/Forms/Translate/MergeResultItem.cs diff --git a/Changelog.txt b/Changelog.txt index 5b6ac5e08..3764680c6 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -30,6 +30,7 @@ * Fix for unwanted "
" in MS translator - thx Miguel * Only add recent file if saved - thx F5System * Fix for mouse wheel scroll direction in video player - thx Peter + * Fix for ASSA border width in export to image based format - thx Christian 4.0.2 (19th November 2023) diff --git a/src/libse/AutoTranslate/LibreTranslate.cs b/src/libse/AutoTranslate/LibreTranslate.cs index 23bbffffd..ee522eefd 100644 --- a/src/libse/AutoTranslate/LibreTranslate.cs +++ b/src/libse/AutoTranslate/LibreTranslate.cs @@ -24,7 +24,7 @@ namespace Nikse.SubtitleEdit.Core.AutoTranslate public void Initialize() { _httpClient?.Dispose(); - _httpClient = new HttpClient(); //DownloaderFactory.MakeHttpClient(); + _httpClient = new HttpClient(); _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json"); _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", "application/json"); _httpClient.BaseAddress = new Uri(Configuration.Settings.Tools.AutoTranslateLibreUrl); diff --git a/src/libse/Common/Settings.cs b/src/libse/Common/Settings.cs index ffe95248e..385d23612 100644 --- a/src/libse/Common/Settings.cs +++ b/src/libse/Common/Settings.cs @@ -2632,6 +2632,7 @@ $HorzAlign = Center public string MainAdjustViaEndAutoStart { get; set; } public string MainAdjustViaEndAutoStartAndGoToNext { get; set; } public string MainAdjustSetEndMinusGapAndStartNextHere { get; set; } + public string MainAdjustSetEndAndStartOfNextPlusGap { get; set; } public string MainAdjustSetStartAutoDurationAndGoToNext { get; set; } public string MainAdjustSetEndNextStartAndGoToNext { get; set; } public string MainAdjustStartDownEndUpAndGoToNext { get; set; } @@ -10686,6 +10687,12 @@ $HorzAlign = Center shortcuts.MainAdjustSetEndMinusGapAndStartNextHere = subNode.InnerText; } + subNode = node.SelectSingleNode("MainAdjustSetEndAndStartOfNextPlusGap"); + if (subNode != null) + { + shortcuts.MainAdjustSetEndAndStartOfNextPlusGap = subNode.InnerText; + } + subNode = node.SelectSingleNode("MainAdjustSetStartAutoDurationAndGoToNext"); if (subNode != null) { @@ -12701,6 +12708,7 @@ $HorzAlign = Center textWriter.WriteElementString("MainAdjustViaEndAutoStart", shortcuts.MainAdjustViaEndAutoStart); textWriter.WriteElementString("MainAdjustViaEndAutoStartAndGoToNext", shortcuts.MainAdjustViaEndAutoStartAndGoToNext); textWriter.WriteElementString("MainAdjustSetEndMinusGapAndStartNextHere", shortcuts.MainAdjustSetEndMinusGapAndStartNextHere); + textWriter.WriteElementString("MainAdjustSetEndAndStartOfNextPlusGap", shortcuts.MainAdjustSetEndAndStartOfNextPlusGap); textWriter.WriteElementString("MainAdjustSetStartAutoDurationAndGoToNext", shortcuts.MainAdjustSetStartAutoDurationAndGoToNext); textWriter.WriteElementString("MainAdjustSetEndNextStartAndGoToNext", shortcuts.MainAdjustSetEndNextStartAndGoToNext); textWriter.WriteElementString("MainAdjustStartDownEndUpAndGoToNext", shortcuts.MainAdjustStartDownEndUpAndGoToNext); diff --git a/src/libse/Translate/Formatting.cs b/src/libse/Translate/Formatting.cs index f04cd3c22..5f56f06dc 100644 --- a/src/libse/Translate/Formatting.cs +++ b/src/libse/Translate/Formatting.cs @@ -49,7 +49,7 @@ namespace Nikse.SubtitleEdit.Core.Translate public string SetTagsAndReturnTrimmed(string input, string sourceLanguage) { - if (string.IsNullOrEmpty(HtmlUtil.RemoveHtmlTags(input, true))) + if (string.IsNullOrWhiteSpace(HtmlUtil.RemoveHtmlTags(input, true).Replace("♪", string.Empty).Replace("♫", string.Empty))) { ReplaceAllText = input; return "..."; diff --git a/src/ui/Forms/ExportPngXml.cs b/src/ui/Forms/ExportPngXml.cs index 0e0daeab8..af3c275b5 100644 --- a/src/ui/Forms/ExportPngXml.cs +++ b/src/ui/Forms/ExportPngXml.cs @@ -2484,12 +2484,12 @@ $DROP=[DROPVALUE]" + Environment.NewLine + Environment.NewLine + return 0; } - if (float.TryParse(comboBoxBorderWidth.SelectedItem.ToString(), out var f)) + if (float.TryParse(comboBoxBorderWidth.SelectedItem.ToString().Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var f)) { return f; } - if (float.TryParse(Utilities.RemoveNonNumbers(comboBoxBorderWidth.SelectedItem.ToString()), out f)) + if (float.TryParse(Utilities.RemoveNonNumbers(comboBoxBorderWidth.SelectedItem.ToString()).Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out f)) { return f; } diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs index 63fda4adf..5544e2b55 100644 --- a/src/ui/Forms/Main.cs +++ b/src/ui/Forms/Main.cs @@ -18803,6 +18803,11 @@ namespace Nikse.SubtitleEdit.Forms SetEndMinusGapAndStartNextHere(FirstSelectedIndex); e.SuppressKeyPress = true; } + else if (mediaPlayer.VideoPlayer != null && _shortcuts.MainAdjustSetEndAndStartOfNextPlusGap == e.KeyData) + { + MainAdjustSetEndAndStartOfNextPlusGap(FirstSelectedIndex); + e.SuppressKeyPress = true; + } else if (mediaPlayer.VideoPlayer != null && _shortcuts.MainAdjustSetStartAutoDurationAndGoToNext == e.KeyData) { SetCurrentStartAutoDurationAndGotoNext(FirstSelectedIndex); @@ -29763,6 +29768,76 @@ namespace Nikse.SubtitleEdit.Forms UpdateSourceView(); } + public void MainAdjustSetEndAndStartOfNextPlusGap(int index) + { + var p = _subtitle.GetParagraphOrDefault(index); + if (p == null) + { + return; + } + + if (mediaPlayer.VideoPlayer == null || string.IsNullOrEmpty(_videoFileName)) + { + MessageBox.Show(_languageGeneral.NoVideoLoaded); + return; + } + + double totalMillisecondsEnd = mediaPlayer.CurrentPosition * TimeCode.BaseUnit; + var oldParagraph = new Paragraph(p, false); + var newDurationMs = totalMillisecondsEnd - p.StartTime.TotalMilliseconds; + if (!p.StartTime.IsMaxTime && + newDurationMs < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds && + newDurationMs > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds) + { + return; + } + + var tc = new TimeCode(totalMillisecondsEnd); + MakeHistoryForUndo(_language.BeforeSetEndAndVideoPosition + " " + tc); + _makeHistoryPaused = true; + + if (p.StartTime.IsMaxTime) + { + p.EndTime.TotalMilliseconds = totalMillisecondsEnd; + p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds - Utilities.GetOptimalDisplayMilliseconds(p.Text); + } + else + { + p.EndTime.TotalMilliseconds = totalMillisecondsEnd; + } + + timeUpDownStartTime.TimeCode = p.StartTime; + var durationInSeconds = (decimal)p.DurationTotalSeconds; + if (durationInSeconds >= numericUpDownDuration.Minimum && durationInSeconds <= numericUpDownDuration.Maximum) + { + SetDurationInSeconds((double)durationInSeconds); + } + + var next = _subtitle.GetParagraphOrDefault(index + 1); + Paragraph oldNextParagraph = null; + if (next != null && (next.StartTime.IsMaxTime || next.StartTime.TotalMilliseconds - totalMillisecondsEnd < 5_000)) + { + oldNextParagraph = new Paragraph(next, false); + next.StartTime.TotalMilliseconds = totalMillisecondsEnd + MinGapBetweenLines; + + if (next.StartTime.IsMaxTime) + { + next.EndTime.TotalMilliseconds = totalMillisecondsEnd + MinGapBetweenLines + Configuration.Settings.General.NewEmptyDefaultMs; + } + } + + RestartHistory(); + + UpdateOriginalTimeCodes(oldParagraph, oldNextParagraph); + SubtitleListview1.SetStartTimeAndDuration(index - 1, _subtitle.GetParagraphOrDefault(index - 1), _subtitle.GetParagraphOrDefault(index), _subtitle.GetParagraphOrDefault(index - 2)); + SubtitleListview1.SetStartTimeAndDuration(index, _subtitle.GetParagraphOrDefault(index), _subtitle.GetParagraphOrDefault(index + 1), _subtitle.GetParagraphOrDefault(index - 1)); + SubtitleListview1.SetStartTimeAndDuration(index + 1, _subtitle.GetParagraphOrDefault(index + 1), _subtitle.GetParagraphOrDefault(index + 2), _subtitle.GetParagraphOrDefault(index)); + RefreshSelectedParagraph(); + ShowStatus(string.Format(_language.VideoControls.AdjustedViaEndTime, p.StartTime.ToShortString())); + audioVisualizer.Invalidate(); + UpdateSourceView(); + } + public void SetCurrentViaEndPositionAndGotoNext(int index, bool goToNext) { var p = _subtitle.GetParagraphOrDefault(index); diff --git a/src/ui/Forms/Options/Settings.cs b/src/ui/Forms/Options/Settings.cs index 8e4d7356e..0285eb882 100644 --- a/src/ui/Forms/Options/Settings.cs +++ b/src/ui/Forms/Options/Settings.cs @@ -1844,6 +1844,7 @@ namespace Nikse.SubtitleEdit.Forms.Options AddNode(createAndAdjustNode, language.AdjustSetEndAndOffsetTheRestAndGoToNext, nameof(Configuration.Settings.Shortcuts.MainAdjustSetEndAndOffsetTheRestAndGoToNext)); AddNode(createAndAdjustNode, language.AdjustSetEndNextStartAndGoToNext, nameof(Configuration.Settings.Shortcuts.MainAdjustSetEndNextStartAndGoToNext)); AddNode(createAndAdjustNode, language.AdjustSetEndMinusGapAndStartNextHere, nameof(Configuration.Settings.Shortcuts.MainAdjustSetEndMinusGapAndStartNextHere)); + AddNode(createAndAdjustNode, "Set end and start of next after gap", nameof(Configuration.Settings.Shortcuts.MainAdjustSetEndAndStartOfNextPlusGap)); AddNode(createAndAdjustNode, language.AdjustViaEndAutoStart, nameof(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStart)); AddNode(createAndAdjustNode, language.AdjustViaEndAutoStartAndGoToNext, nameof(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext)); AddNode(createAndAdjustNode, language.AdjustSelected100MsBack, nameof(Configuration.Settings.Shortcuts.MainAdjustSelected100MsBack)); diff --git a/src/ui/Forms/Translate/AutoTranslate.Designer.cs b/src/ui/Forms/Translate/AutoTranslate.Designer.cs index 8b05a5d2b..82eef78ec 100644 --- a/src/ui/Forms/Translate/AutoTranslate.Designer.cs +++ b/src/ui/Forms/Translate/AutoTranslate.Designer.cs @@ -42,10 +42,15 @@ this.toolStripMenuItemStartLibre = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItemStartNLLBServe = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItemStartNLLBApi = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.translateSingleLinesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.startLibreTranslateServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.startNLLBServeServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.startNLLBAPIServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.translateSingleLinesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.labelApiKey = new System.Windows.Forms.Label(); this.nikseTextBoxApiKey = new Nikse.SubtitleEdit.Controls.NikseTextBox(); this.nikseComboBoxEngine = new Nikse.SubtitleEdit.Controls.NikseComboBox(); this.nikseComboBoxUrl = new Nikse.SubtitleEdit.Controls.NikseComboBox(); @@ -53,11 +58,6 @@ this.comboBoxTarget = new Nikse.SubtitleEdit.Controls.NikseComboBox(); this.subtitleListViewTarget = new Nikse.SubtitleEdit.Controls.SubtitleListView(); this.subtitleListViewSource = new Nikse.SubtitleEdit.Controls.SubtitleListView(); - this.labelApiKey = new System.Windows.Forms.Label(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.translateSingleLinesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.translateSingleLinesToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip2.SuspendLayout(); this.contextMenuStrip1.SuspendLayout(); this.SuspendLayout(); @@ -159,7 +159,7 @@ this.toolStripSeparator1, this.translateSingleLinesToolStripMenuItem}); this.contextMenuStrip2.Name = "contextMenuStrip1"; - this.contextMenuStrip2.Size = new System.Drawing.Size(197, 120); + this.contextMenuStrip2.Size = new System.Drawing.Size(197, 98); this.contextMenuStrip2.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip2_Opening); // // toolStripMenuItemStartLibre @@ -182,6 +182,18 @@ this.toolStripMenuItemStartNLLBApi.Size = new System.Drawing.Size(196, 22); this.toolStripMenuItemStartNLLBApi.Text = "Start NLLB API server"; // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(193, 6); + // + // translateSingleLinesToolStripMenuItem + // + this.translateSingleLinesToolStripMenuItem.Name = "translateSingleLinesToolStripMenuItem"; + this.translateSingleLinesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.translateSingleLinesToolStripMenuItem.Text = "Translate single lines"; + this.translateSingleLinesToolStripMenuItem.Click += new System.EventHandler(this.translateSingleLinesToolStripMenuItem_Click); + // // contextMenuStrip1 // this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -214,6 +226,28 @@ this.startNLLBAPIServerToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.startNLLBAPIServerToolStripMenuItem.Text = "Start NLLB API server"; // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(193, 6); + // + // translateSingleLinesToolStripMenuItem1 + // + this.translateSingleLinesToolStripMenuItem1.Name = "translateSingleLinesToolStripMenuItem1"; + this.translateSingleLinesToolStripMenuItem1.Size = new System.Drawing.Size(196, 22); + this.translateSingleLinesToolStripMenuItem1.Text = "Translate single lines"; + this.translateSingleLinesToolStripMenuItem1.Click += new System.EventHandler(this.translateSingleLinesToolStripMenuItem1_Click); + // + // labelApiKey + // + 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.Name = "labelApiKey"; + this.labelApiKey.Size = new System.Drawing.Size(47, 13); + this.labelApiKey.TabIndex = 111; + this.labelApiKey.Text = "API key:"; + // // nikseTextBoxApiKey // this.nikseTextBoxApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); @@ -363,40 +397,8 @@ this.subtitleListViewSource.UseCompatibleStateImageBehavior = false; this.subtitleListViewSource.UseSyntaxColoring = true; this.subtitleListViewSource.View = System.Windows.Forms.View.Details; - // - // labelApiKey - // - 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.Name = "labelApiKey"; - this.labelApiKey.Size = new System.Drawing.Size(47, 13); - this.labelApiKey.TabIndex = 111; - this.labelApiKey.Text = "API key:"; - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(193, 6); - // - // translateSingleLinesToolStripMenuItem - // - this.translateSingleLinesToolStripMenuItem.Name = "translateSingleLinesToolStripMenuItem"; - this.translateSingleLinesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); - this.translateSingleLinesToolStripMenuItem.Text = "Translate single lines"; - this.translateSingleLinesToolStripMenuItem.Click += new System.EventHandler(this.translateSingleLinesToolStripMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(193, 6); - // - // translateSingleLinesToolStripMenuItem1 - // - this.translateSingleLinesToolStripMenuItem1.Name = "translateSingleLinesToolStripMenuItem1"; - this.translateSingleLinesToolStripMenuItem1.Size = new System.Drawing.Size(196, 22); - this.translateSingleLinesToolStripMenuItem1.Text = "Translate single lines"; - this.translateSingleLinesToolStripMenuItem1.Click += new System.EventHandler(this.translateSingleLinesToolStripMenuItem1_Click); + this.subtitleListViewSource.Click += new System.EventHandler(this.subtitleListViewSource_Click); + this.subtitleListViewSource.DoubleClick += new System.EventHandler(this.subtitleListViewSource_DoubleClick); // // AutoTranslate // diff --git a/src/ui/Forms/Translate/AutoTranslate.cs b/src/ui/Forms/Translate/AutoTranslate.cs index f8f1928a2..51a264058 100644 --- a/src/ui/Forms/Translate/AutoTranslate.cs +++ b/src/ui/Forms/Translate/AutoTranslate.cs @@ -99,6 +99,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate subtitleListViewSource.Fill(_subtitle); AutoTranslate_Resize(null, null); UpdateTranslation(); + MergeAndSplitHelper.MergeSplitProblems = false; } private void InitializeAutoTranslatorEngines() @@ -151,6 +152,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate labelApiKey.Visible = false; nikseComboBoxUrl.Visible = false; nikseTextBoxApiKey.Top = nikseComboBoxUrl.Top; + labelApiKey.Text = LanguageSettings.Current.Settings.GoogleTranslateApiKey; var engineType = _autoTranslator.GetType(); if (engineType == typeof(GoogleTranslateV1)) @@ -228,16 +230,17 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (engineType == typeof(PapagoTranslate)) { - + nikseComboBoxUrl.Items.Clear(); nikseComboBoxUrl.Items.Add(Configuration.Settings.Tools.AutoTranslatePapagoApiKeyId); nikseComboBoxUrl.SelectedIndex = 0; nikseComboBoxUrl.Visible = true; labelUrl.Visible = true; - labelUrl.Text = "API Key ID"; + labelUrl.Text = "Client ID"; nikseComboBoxUrl.Left = labelUrl.Right + 3; labelApiKey.Left = nikseComboBoxUrl.Right + 12; + labelApiKey.Text = "Client secret"; nikseTextBoxApiKey.Text = Configuration.Settings.Tools.AutoTranslatePapagoApiKey; nikseTextBoxApiKey.Left = labelApiKey.Right + 3; labelApiKey.Visible = true; @@ -557,7 +560,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate timerUpdate.Tick += TimerUpdate_Tick; timerUpdate.Start(); var linesTranslated = 0; - var forceSingleLineMode = translateSingleLinesToolStripMenuItem.Checked; + var forceSingleLineMode = translateSingleLinesToolStripMenuItem.Checked || _autoTranslator.Name == NoLanguageLeftBehindApi.StaticName; var delaySeconds = 0; if (_autoTranslator.Name == ChatGptTranslate.StaticName) { @@ -566,6 +569,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (comboBoxSource.SelectedItem is TranslationPair source && comboBoxTarget.SelectedItem is TranslationPair target) { + var mergeErrorCount = 0; + Configuration.Settings.Tools.GoogleTranslateLastTargetLanguage = target.TwoLetterIsoLanguageName ?? target.Code; try { @@ -573,23 +578,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate var index = start; while (index < _subtitle.Paragraphs.Count) { - if (index > start && delaySeconds > 0) - { - for (var i = delaySeconds; i > 0; i--) - { - labelPleaseWait.Text = LanguageSettings.Current.GoogleTranslate.PleaseWait + $" ({i})"; - labelPleaseWait.Refresh(); - Application.DoEvents(); - System.Threading.Thread.Sleep(1000); - if (_breakTranslation) - { - break; - } - } - - labelPleaseWait.Text = LanguageSettings.Current.GoogleTranslate.PleaseWait; - Application.DoEvents(); - } + Delay(delaySeconds, start, index); if (_breakTranslation) { @@ -605,6 +594,12 @@ namespace Nikse.SubtitleEdit.Forms.Translate continue; } + mergeErrorCount++; + if (mergeErrorCount > 20) + { + forceSingleLineMode = true; + } + var p = _subtitle.Paragraphs[index]; var f = new Formatting(); var unformattedText = f.SetTagsAndReturnTrimmed(p.Text, source.Code); @@ -657,6 +652,27 @@ namespace Nikse.SubtitleEdit.Forms.Translate buttonOK.Focus(); } + private void Delay(int delaySeconds, int start, int index) + { + if (index > start && delaySeconds > 0) + { + for (var i = delaySeconds; i > 0; i--) + { + labelPleaseWait.Text = LanguageSettings.Current.GoogleTranslate.PleaseWait + $" ({i})"; + labelPleaseWait.Refresh(); + Application.DoEvents(); + System.Threading.Thread.Sleep(1000); + if (_breakTranslation) + { + break; + } + } + + labelPleaseWait.Text = LanguageSettings.Current.GoogleTranslate.PleaseWait; + Application.DoEvents(); + } + } + private void HandleError(Exception exception, int linesTranslate, Type engineType) { SeLogger.Error(exception); @@ -684,7 +700,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate Environment.NewLine + LanguageSettings.Current.GoogleTranslate.ReadMore + Environment.NewLine + Environment.NewLine + - "AutoTranslatePapagoApiKeyId and AutoTranslatePapagoApiKey needs to be filled out in Settings.xml" + Environment.NewLine + + "Client ID and Client secrect are required" + Environment.NewLine + Environment.NewLine + _autoTranslator.Error, Text, @@ -962,5 +978,15 @@ namespace Nikse.SubtitleEdit.Forms.Translate { ToggleTranslateSingleLines(); } + + private void subtitleListViewSource_DoubleClick(object sender, EventArgs e) + { + SyncListViews(subtitleListViewSource, subtitleListViewTarget); + } + + private void subtitleListViewSource_Click(object sender, EventArgs e) + { + SyncListViews(subtitleListViewSource, subtitleListViewTarget); + } } } diff --git a/src/ui/Forms/Translate/MergeAndSplitHelper.cs b/src/ui/Forms/Translate/MergeAndSplitHelper.cs index 388686dd6..5a8c223cf 100644 --- a/src/ui/Forms/Translate/MergeAndSplitHelper.cs +++ b/src/ui/Forms/Translate/MergeAndSplitHelper.cs @@ -9,84 +9,66 @@ using Nikse.SubtitleEdit.Core.Translate; namespace Nikse.SubtitleEdit.Forms.Translate { - public static class MergeAndSplitHelper + public static partial class MergeAndSplitHelper { + public static bool MergeSplitProblems { get; set; } + public static async Task MergeAndTranslateIfPossible(Subtitle sourceSubtitle, Subtitle targetSubtitle, TranslationPair source, TranslationPair target, int index, IAutoTranslator autoTranslator, bool forceSingleLineMode) { - var noSentenceEndingSource = IsNonMergeLanguage(source.Code); - var noSentenceEndingTarget = IsNonMergeLanguage(target.Code); - if (forceSingleLineMode) { - noSentenceEndingSource = true; // will add separator between lines + return 0; } - var p = sourceSubtitle.Paragraphs[index]; - char? splitAtChar = null; - var mergeCount = 0; - var allItalic = false; - var allBold = false; - var text = string.Empty; - var linesTranslate = 0; - - MergeResult mergeResult = null; - List formattings = null; - + var noSentenceEndingSource = IsNonMergeLanguage(source); + var noSentenceEndingTarget = IsNonMergeLanguage(target); // Try to handle (remove and save info for later restore) italics, bold, alignment, and more where possible var tempSubtitle = new Subtitle(sourceSubtitle); - formattings = HandleFormatting(tempSubtitle, index, target.Code); + List formattings = HandleFormatting(tempSubtitle, index, target.Code); // Merge text for better translation and save info enough to split again later - mergeResult = MergeMultipleLines(tempSubtitle, index, autoTranslator.MaxCharacters, noSentenceEndingSource, noSentenceEndingTarget); - mergeCount = mergeResult.ParagraphCount; - text = mergeResult.Text; - - //TODO: handle mergeResult.Error !!! - - - if (mergeCount == 0) + var maxChars = autoTranslator.MaxCharacters; + if (MergeSplitProblems) { - if (MergeWithThreeNext(sourceSubtitle, index, source.Code)) + MergeSplitProblems = false; + if (maxChars > 500) { - mergeCount = 3; - allItalic = HasAllLinesTag(sourceSubtitle, index, mergeCount, "i"); - allBold = HasAllLinesTag(sourceSubtitle, index, mergeCount, "b"); - text = MergeLines(sourceSubtitle, index, mergeCount, allItalic, allBold); - } - else if (MergeWithTwoNext(sourceSubtitle, index, source.Code)) - { - mergeCount = 2; - allItalic = HasAllLinesTag(sourceSubtitle, index, mergeCount, "i"); - allBold = HasAllLinesTag(sourceSubtitle, index, mergeCount, "b"); - text = MergeLines(sourceSubtitle, index, mergeCount, allItalic, allBold); - } - else if (MergeWithNext(sourceSubtitle, index, source.Code)) - { - mergeCount = 1; - allItalic = HasAllLinesTag(sourceSubtitle, index, mergeCount, "i"); - allBold = HasAllLinesTag(sourceSubtitle, index, mergeCount, "b"); - text = MergeLines(sourceSubtitle, index, mergeCount, allItalic, allBold); + maxChars = maxChars / 2; } } - // just take next sentence too - var next = sourceSubtitle.GetParagraphOrDefault(index + 1); - if (mergeCount == 0 && MergeWithNextOneLineEnding(sourceSubtitle, index, source.Code, out char splitChar)) + MergeResult mergeResult = MergeMultipleLines(tempSubtitle, index, maxChars, noSentenceEndingSource, noSentenceEndingTarget); + var mergeCount = mergeResult.ParagraphCount; + var text = mergeResult.Text; + + if (mergeResult.HasError) { - splitAtChar = splitChar; - mergeCount = 1; - allItalic = HasAllLinesTag(sourceSubtitle, index, mergeCount, "i"); - allBold = HasAllLinesTag(sourceSubtitle, index, mergeCount, "b"); - text = Utilities.UnbreakLine(p.Text) + Environment.NewLine + Utilities.UnbreakLine(next.Text); + MergeSplitProblems = true; + + if (!noSentenceEndingSource) + { + noSentenceEndingSource = true; + mergeResult = MergeMultipleLines(tempSubtitle, index, maxChars, noSentenceEndingSource, noSentenceEndingTarget); + mergeCount = mergeResult.ParagraphCount; + text = mergeResult.Text; + } + + if (mergeResult.HasError) + { + return 0; + } } + var linesTranslate = 0; if (mergeResult != null) { var mergedTranslation = await autoTranslator.Translate(text, source.Code, target.Code); var splitResult = SplitMultipleLines(mergeResult, mergedTranslation, target.Code); - if (splitResult.Count == mergeCount) + if (splitResult.Count == mergeCount && HasSameEmptyLines(splitResult, tempSubtitle, index)) { + // Split by line ending chars + var idx = 0; foreach (var line in splitResult) { @@ -99,55 +81,93 @@ namespace Nikse.SubtitleEdit.Forms.Translate return linesTranslate; } + + var translatedLines = mergedTranslation.SplitToLines(); + if (translatedLines.Count == mergeResult.Text.SplitToLines().Count) + { + // Split per number of lines + + var newSub = new Subtitle(); + for (var i = 0; i < mergeResult.ParagraphCount; i++) + { + newSub.Paragraphs.Add(new Paragraph()); + } + + var translatedLinesIdx = 0; + var paragraphIdx = 0; + foreach (var mergeItem in mergeResult.MergeResultItems) + { + var numberOfParagraphs = mergeItem.EndIndex - mergeItem.StartIndex + 1; + var numberOfLines = mergeItem.Text.SplitToLines().Count; + + var sb = new StringBuilder(); + for (var j = 0; j < numberOfLines && translatedLinesIdx < translatedLines.Count; j++) + { + sb.AppendLine(translatedLines[translatedLinesIdx]); + translatedLinesIdx++; + } + var translatedText = sb.ToString().Trim(); + + var arr = TextSplit.SplitMulti(translatedText, numberOfParagraphs, target.TwoLetterIsoLanguageName); + for (var i = 0; i < arr.Count && paragraphIdx < newSub.Paragraphs.Count; i++) + { + newSub.Paragraphs[paragraphIdx].Text = Utilities.AutoBreakLine(arr[i], Configuration.Settings.General.SubtitleLineMaximumLength * 2, 0, target.TwoLetterIsoLanguageName); + paragraphIdx++; + } + } + + if (paragraphIdx == mergeCount && HasSameEmptyLines(newSub, sourceSubtitle, index)) + { + var idx = 0; + foreach (var p in newSub.Paragraphs) + { + var reformattedText = formattings[idx].ReAddFormatting(p.Text); + targetSubtitle.Paragraphs[index].Text = reformattedText; + index++; + linesTranslate++; + idx++; + } + + return linesTranslate; + } + } } - if (mergeCount > 0) - { - var mergedTranslation = await autoTranslator.Translate(text, source.Code, target.Code); - - List result; - - if (splitAtChar != null && mergeCount == 1) - { - result = SplitResultAtSplitChar(mergedTranslation, splitAtChar.Value, target.Code); - } - else - { - result = SplitResult(mergedTranslation.SplitToLines(), mergeCount, source.Code); - } - - if (allItalic) - { - for (var k = 0; k < result.Count; k++) - { - result[k] = "" + result[k] + ""; - } - } - - if (allBold) - { - for (var k = 0; k < result.Count; k++) - { - result[k] = "" + result[k] + ""; - } - } - - if (result.Count == mergeCount + 1 && result.All(t => !string.IsNullOrEmpty(t))) - { - foreach (var line in result) - { - targetSubtitle.Paragraphs[index].Text = line; - index++; - linesTranslate++; - } - - return linesTranslate; - } - } + MergeSplitProblems = true; return linesTranslate; } + private static bool HasSameEmptyLines(Subtitle newSub, Subtitle sourceSubtitle, int index) + { + for (var i = 0; i < newSub.Paragraphs.Count; i++) + { + var inputBlank = string.IsNullOrWhiteSpace(sourceSubtitle.Paragraphs[i + index].Text); + var outputBlank = string.IsNullOrWhiteSpace(newSub.Paragraphs[i].Text); + if (inputBlank || outputBlank && (inputBlank != outputBlank)) + { + return false; + } + } + + return true; + } + + private static bool HasSameEmptyLines(List splitResult, Subtitle tempSubtitle, int index) + { + for (var i = 0; i < splitResult.Count; i++) + { + var inputBlank = string.IsNullOrWhiteSpace(tempSubtitle.Paragraphs[i + index].Text); + var outputBlank = string.IsNullOrWhiteSpace(splitResult[i]); + if (inputBlank || outputBlank && (inputBlank != outputBlank)) + { + return false; + } + } + + return true; + } + private static List HandleFormatting(Subtitle sourceSubtitle, int index, string sourceLanguage) { var formattings = new List(); @@ -164,31 +184,6 @@ namespace Nikse.SubtitleEdit.Forms.Translate return formattings; } - public class MergeResultItem - { - public string Text { get; set; } - public int StartIndex { get; set; } - public int EndIndex { get; set; } - public bool AllItalic { get; set; } - public bool AllBold { get; set; } - public bool Continious { get; set; } - public char EndChar { get; set; } - public int EndCharOccurences { get; set; } - public bool IsEmpty { get; set; } - public bool HasError { get; set; } - } - - - public class MergeResult - { - public string Text { get; set; } - public int ParagraphCount { get; set; } - public List MergeResultItems { get; set; } - public bool HasError { get; set; } - public bool NoSentenceEndingSource { get; set; } - public bool NoSentenceEndingTarget { get; set; } - } - public static MergeResult MergeMultipleLines(Subtitle sourceSubtitle, int index, int maxTextSize, bool noSentenceEndingSource, bool noSentenceEndingTarget) { var result = new MergeResult @@ -201,11 +196,14 @@ namespace Nikse.SubtitleEdit.Forms.Translate var item = new MergeResultItem(); item.StartIndex = index; item.EndIndex = index; + item.Text = string.Empty; result.Text = sourceSubtitle.Paragraphs[index].Text; + item.Text = sourceSubtitle.Paragraphs[index].Text; if (string.IsNullOrWhiteSpace(result.Text)) { item.IsEmpty = true; + item.Text = string.Empty; result.MergeResultItems.Add(item); item = null; result.Text = string.Empty; @@ -225,15 +223,24 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (noSentenceEndingSource) { - result.Text += Environment.NewLine + "." + Environment.NewLine + p.Text; + if (item != null) { + item.TextIndexEnd = result.Text.Length; + } + + result.Text += Environment.NewLine + "." + Environment.NewLine + p.Text; + item.Text += Environment.NewLine + "." + Environment.NewLine + p.Text; + + if (item != null) + { + item.TextIndexStart = result.Text.Length; item.StartIndex = i - 1; item.EndIndex = i - 1; result.MergeResultItems.Add(item); textBuild = new StringBuilder(); - item = new MergeResultItem { StartIndex = i }; + item = new MergeResultItem { StartIndex = i, Text = string.Empty }; } } else if (string.IsNullOrWhiteSpace(p.Text)) @@ -241,6 +248,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate var endChar = result.Text[result.Text.Length - 1]; if (item != null) { + item.TextIndexStart = result.Text.Length; + item.TextIndexEnd = result.Text.Length; item.EndChar = endChar; var endCharOccurences = Utilities.CountTagInText(textBuild.ToString(), endChar); item.EndCharOccurences = endCharOccurences; @@ -252,7 +261,10 @@ namespace Nikse.SubtitleEdit.Forms.Translate { StartIndex = index, EndIndex = index, - IsEmpty = true + IsEmpty = true, + TextIndexStart = result.Text.Length, + TextIndexEnd = result.Text.Length, + Text = string.Empty, }); item = null; @@ -266,6 +278,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate { if (item != null) { + item.TextIndexEnd = result.Text.Length; result.MergeResultItems.Add(item); textBuild = new StringBuilder(); } @@ -279,6 +292,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate item.EndChar = endChar; var endCharOccurences = Utilities.CountTagInText(textBuild.ToString(), endChar); item.EndCharOccurences = endCharOccurences; + item.TextIndexEnd = result.Text.Length; result.MergeResultItems.Add(item); textBuild = new StringBuilder(); } @@ -288,13 +302,14 @@ namespace Nikse.SubtitleEdit.Forms.Translate result.Text += Environment.NewLine + p.Text; - item = new MergeResultItem { StartIndex = i }; + item = new MergeResultItem { StartIndex = i, TextIndexStart = result.Text.Length, Text = p.Text }; } else if (item != null && (item.Continious || item.StartIndex == item.EndIndex) && p.StartTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds < 1000) { textBuild.Append(" "); textBuild.Append(p.Text); result.Text += " " + p.Text; + item.Text += " " + p.Text; item.Continious = true; } else @@ -306,6 +321,7 @@ namespace Nikse.SubtitleEdit.Forms.Translate if (item != null) { item.EndIndex = i; + item.TextIndexEnd = result.Text.Length; } prev = p; @@ -328,13 +344,18 @@ namespace Nikse.SubtitleEdit.Forms.Translate result.Text = result.Text.Trim(); result.ParagraphCount = result.MergeResultItems.Sum(p => p.EndIndex - p.StartIndex + 1); + foreach (var i in result.MergeResultItems) + { + i.Text = i.Text.Trim(); + } + return result; } - public static List SplitMultipleLines(MergeResult mergeResult, string input, string language) + public static List SplitMultipleLines(MergeResult mergeResult, string translatedText, string language) { var lines = new List(); - var text = input; + var text = translatedText; if (mergeResult.NoSentenceEndingSource) { @@ -371,8 +392,8 @@ namespace Nikse.SubtitleEdit.Forms.Translate { var part = GetPartFromItem(text, item); text = text.Remove(0, part.Length).Trim(); - var lineRAnge = SplitContontinous(part, item, language); - lines.AddRange(lineRAnge); + var lineRange = SplitContontinous(part, item, language); + lines.AddRange(lineRange); } else { @@ -429,294 +450,18 @@ namespace Nikse.SubtitleEdit.Forms.Translate return TextSplit.SplitMulti(text, count, language); } - private static bool HasAllLinesTag(Subtitle subtitle, int i, int mergeCount, string tag) + private static bool IsNonMergeLanguage(TranslationPair language) { - for (var j = i; j < subtitle.Paragraphs.Count && j <= i + mergeCount; j++) - { - var text = subtitle.Paragraphs[j].Text.Trim(); - if (!text.StartsWith("<" + tag + ">") && !text.EndsWith("")) - { - return false; - } - } + var code = language.TwoLetterIsoLanguageName ?? language.Code; - return true; + return code.ToLowerInvariant() == "zh" || + code.ToLowerInvariant() == "zh-CN" || + code.ToLowerInvariant() == "zh-TW" || + code.ToLowerInvariant() == "yue_Hant" || + code.ToLowerInvariant() == "zho_Hans" || + code.ToLowerInvariant() == "zho_Hant" || + code.ToLowerInvariant() == "jpn_Jpan" || + code.ToLowerInvariant() == "ja"; } - - private static bool MergeWithTwoNext(Subtitle subtitle, int i, string source) - { - if (i + 2 >= subtitle.Paragraphs.Count || IsNonMergeLanguage(source)) - { - return false; - } - - return MergeWithNext(subtitle, i, source) && MergeWithNext(subtitle, i + 1, source); - } - - private static bool MergeWithThreeNext(Subtitle subtitle, int i, string source) - { - if (i + 3 >= subtitle.Paragraphs.Count || IsNonMergeLanguage(source)) - { - return false; - } - - return MergeWithNext(subtitle, i, source) && MergeWithNext(subtitle, i + 1, source) && MergeWithNext(subtitle, i + 2, source); - } - - private static string MergeLines(Subtitle subtitle, int i, int mergeCount, bool italic, bool bold) - { - var sb = new StringBuilder(); - for (var j = i; j < subtitle.Paragraphs.Count && j <= i + mergeCount; j++) - { - var text = subtitle.Paragraphs[j].Text.Trim(); - sb.AppendLine(RemoveAllLinesTag(text, italic, bold)); - } - - return Utilities.RemoveLineBreaks(sb.ToString()); - } - - private static List SplitResultAtSplitChar(string translation, char splitAtChar, string languageCode) - { - var idx = translation.IndexOf(splitAtChar); - if (idx < 0 && idx < translation.Length - 1) - { - return new List(); - } - - var line1 = Utilities.AutoBreakLine(translation.Substring(0, idx + 1).Trim(), - Configuration.Settings.General.SubtitleLineMaximumLength, - Configuration.Settings.General.MergeLinesShorterThan, - languageCode); - var line2 = Utilities.AutoBreakLine(translation.Remove(0, idx + 1).Trim(), - Configuration.Settings.General.SubtitleLineMaximumLength, - Configuration.Settings.General.MergeLinesShorterThan, - languageCode); - return new List { line1, line2 }; - } - - private static bool MergeWithNextOneLineEnding(Subtitle subtitle, int index, string sourceCode, out char c) - { - c = '-'; - - if (index + 1 >= subtitle.Paragraphs.Count || IsNonMergeLanguage(sourceCode)) - { - return false; - } - - if (MergeWithNext(subtitle, index, sourceCode)) - { - return false; - } - - var next = subtitle.GetParagraphOrDefault(index + 1); - if (next == null || !next.Text.HasSentenceEnding("en")) - { - return false; - } - - if (subtitle.Paragraphs[index].Text.EndsWith(".") && Utilities.CountTagInText(subtitle.Paragraphs[index].Text, '.') == 1) - { - c = '.'; - return true; - } - - if (subtitle.Paragraphs[index].Text.EndsWith("?") && Utilities.CountTagInText(subtitle.Paragraphs[index].Text, '?') == 1) - { - c = '?'; - return true; - } - - if (subtitle.Paragraphs[index].Text.EndsWith("!") && Utilities.CountTagInText(subtitle.Paragraphs[index].Text, '!') == 1) - { - c = '!'; - return true; - } - - return false; - } - - private static bool MergeWithNext(Subtitle subtitle, int i, string source) - { - if (i + 1 >= subtitle.Paragraphs.Count || IsNonMergeLanguage(source)) - { - return false; - } - - var p = subtitle.Paragraphs[i]; - var text = HtmlUtil.RemoveHtmlTags(p.Text, true).TrimEnd('"'); - if (text.EndsWith(".", StringComparison.Ordinal) || - text.EndsWith("!", StringComparison.Ordinal) || - text.EndsWith("?", StringComparison.Ordinal)) - { - return false; - } - - var next = subtitle.Paragraphs[i + 1]; - return next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds < 500; - } - - private static bool IsNonMergeLanguage(string source) - { - return source.ToLowerInvariant() == "zh" || - source.ToLowerInvariant() == "zh-CN" || - source.ToLowerInvariant() == "zh-TW" || - source.ToLowerInvariant() == "yue_Hant" || - source.ToLowerInvariant() == "zho_Hans" || - source.ToLowerInvariant() == "zho_Hant" || - source.ToLowerInvariant() == "jpn_Jpan" || - source.ToLowerInvariant() == "ja"; - } - - - - private static string RemoveAllLinesTag(string text, bool allItalic, bool allBold) - { - if (allItalic) - { - text = text.Replace("", string.Empty); - text = text.Replace("", string.Empty); - } - - if (allBold) - { - text = text.Replace("", string.Empty); - text = text.Replace("", string.Empty); - } - - return text; - } - - private static List SplitResult(List result, int mergeCount, string language) - { - if (result.Count != 1) - { - return result; - } - - if (mergeCount == 1) - { - var arr = Utilities.AutoBreakLine(result[0], 84, 1, language).SplitToLines(); - if (arr.Count == 1) - { - arr = Utilities.AutoBreakLine(result[0], 42, 1, language).SplitToLines(); - } - - if (arr.Count == 1) - { - arr = Utilities.AutoBreakLine(result[0], 22, 1, language).SplitToLines(); - } - - if (arr.Count == 2) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - }; - } - - if (arr.Count == 1) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - string.Empty, - }; - } - - return result; - } - - if (mergeCount == 2) - { - var arr = SplitHelper.SplitToXLines(3, result[0], 84).ToArray(); - - if (arr.Length == 3) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[2], 42, language == "zh" ? 0 : 25, language), - }; - } - - if (arr.Length == 2) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - string.Empty, - }; - } - - if (arr.Length == 1) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - string.Empty, - string.Empty, - }; - } - - return result; - } - - if (mergeCount == 3) - { - var arr = SplitHelper.SplitToXLines(4, result[0], 84).ToArray(); - - if (arr.Length == 4) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[2], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[3], 42, language == "zh" ? 0 : 25, language), - }; - } - - if (arr.Length == 3) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[2], 42, language == "zh" ? 0 : 25, language), - string.Empty, - }; - } - - if (arr.Length == 2) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - Utilities.AutoBreakLine(arr[1], 42, language == "zh" ? 0 : 25, language), - string.Empty, - string.Empty, - }; - } - - if (arr.Length == 1) - { - return new List - { - Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language), - string.Empty, - string.Empty, - string.Empty, - }; - } - - return result; - } - - return result; - } - } } diff --git a/src/ui/Forms/Translate/MergeResult.cs b/src/ui/Forms/Translate/MergeResult.cs new file mode 100644 index 000000000..d76c14cb0 --- /dev/null +++ b/src/ui/Forms/Translate/MergeResult.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Nikse.SubtitleEdit.Forms.Translate +{ + public static partial class MergeAndSplitHelper + { + public class MergeResult + { + public string Text { get; set; } + public int ParagraphCount { get; set; } + public List MergeResultItems { get; set; } + public bool HasError { get; set; } + public bool NoSentenceEndingSource { get; set; } + public bool NoSentenceEndingTarget { get; set; } + } + } +} diff --git a/src/ui/Forms/Translate/MergeResultItem.cs b/src/ui/Forms/Translate/MergeResultItem.cs new file mode 100644 index 000000000..5fdd22b46 --- /dev/null +++ b/src/ui/Forms/Translate/MergeResultItem.cs @@ -0,0 +1,21 @@ +namespace Nikse.SubtitleEdit.Forms.Translate +{ + public static partial class MergeAndSplitHelper + { + public class MergeResultItem + { + public string Text { get; set; } + public int StartIndex { get; set; } + public int EndIndex { get; set; } + public bool AllItalic { get; set; } + public bool AllBold { get; set; } + public bool Continious { get; set; } + public char EndChar { get; set; } + public int EndCharOccurences { get; set; } + public bool IsEmpty { get; set; } + public bool HasError { get; set; } + public int TextIndexStart { get; set; } + public int TextIndexEnd { get; set; } + } + } +} diff --git a/src/ui/Logic/MainShortcuts.cs b/src/ui/Logic/MainShortcuts.cs index ef08c51cc..32370e4c7 100644 --- a/src/ui/Logic/MainShortcuts.cs +++ b/src/ui/Logic/MainShortcuts.cs @@ -153,6 +153,7 @@ namespace Nikse.SubtitleEdit.Logic public Keys MainAdjustInsertViaEndAutoStart { get; set; } public Keys MainAdjustInsertViaEndAutoStartAndGoToNext { get; set; } public Keys MainAdjustSetEndMinusGapAndStartNextHere { get; set; } + public Keys MainAdjustSetEndAndStartOfNextPlusGap { get; set; } public Keys MainAdjustSetStartAutoDurationAndGoToNext { get; set; } public Keys MainAdjustSetEndNextStartAndGoToNext { get; set; } public Keys MainAdjustStartDownEndUpAndGoToNext { get; set; } @@ -469,6 +470,7 @@ namespace Nikse.SubtitleEdit.Logic MainAdjustInsertViaEndAutoStart = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStart); MainAdjustInsertViaEndAutoStartAndGoToNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustViaEndAutoStartAndGoToNext); MainAdjustSetEndMinusGapAndStartNextHere = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetEndMinusGapAndStartNextHere); + MainAdjustSetEndAndStartOfNextPlusGap = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetEndAndStartOfNextPlusGap); MainAdjustSetStartAutoDurationAndGoToNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetStartAutoDurationAndGoToNext); MainAdjustSetEndNextStartAndGoToNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustSetEndNextStartAndGoToNext); MainAdjustStartDownEndUpAndGoToNext = UiUtil.GetKeys(Configuration.Settings.Shortcuts.MainAdjustStartDownEndUpAndGoToNext); diff --git a/src/ui/SubtitleEdit.csproj b/src/ui/SubtitleEdit.csproj index 4525d7be9..e4acffad0 100644 --- a/src/ui/SubtitleEdit.csproj +++ b/src/ui/SubtitleEdit.csproj @@ -1338,6 +1338,8 @@ TimedTextStyles.cs + + Form