Work on translate

This commit is contained in:
Nikolaj Olsson 2023-12-07 19:33:43 +01:00
parent 0ecef2a641
commit f98c0a1eda
14 changed files with 380 additions and 480 deletions

View File

@ -30,6 +30,7 @@
* Fix for unwanted "<br />" 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)

View File

@ -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);

View File

@ -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);

View File

@ -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 "...";

View File

@ -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;
}

View File

@ -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);

View File

@ -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));

View File

@ -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
//

View File

@ -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))
@ -234,10 +236,11 @@ namespace Nikse.SubtitleEdit.Forms.Translate
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);
}
}
}

View File

@ -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<int> 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<Formatting> 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<Formatting> 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);
var maxChars = autoTranslator.MaxCharacters;
if (MergeSplitProblems)
{
MergeSplitProblems = false;
if (maxChars > 500)
{
maxChars = maxChars / 2;
}
}
MergeResult mergeResult = MergeMultipleLines(tempSubtitle, index, maxChars, noSentenceEndingSource, noSentenceEndingTarget);
var mergeCount = mergeResult.ParagraphCount;
var text = mergeResult.Text;
if (mergeResult.HasError)
{
MergeSplitProblems = true;
if (!noSentenceEndingSource)
{
noSentenceEndingSource = true;
mergeResult = MergeMultipleLines(tempSubtitle, index, maxChars, noSentenceEndingSource, noSentenceEndingTarget);
mergeCount = mergeResult.ParagraphCount;
text = mergeResult.Text;
//TODO: handle mergeResult.Error !!!
if (mergeCount == 0)
{
if (MergeWithThreeNext(sourceSubtitle, index, source.Code))
{
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))
if (mergeResult.HasError)
{
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);
return 0;
}
}
// just take next sentence too
var next = sourceSubtitle.GetParagraphOrDefault(index + 1);
if (mergeCount == 0 && MergeWithNextOneLineEnding(sourceSubtitle, index, source.Code, out char splitChar))
{
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);
}
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());
}
if (mergeCount > 0)
var translatedLinesIdx = 0;
var paragraphIdx = 0;
foreach (var mergeItem in mergeResult.MergeResultItems)
{
var mergedTranslation = await autoTranslator.Translate(text, source.Code, target.Code);
var numberOfParagraphs = mergeItem.EndIndex - mergeItem.StartIndex + 1;
var numberOfLines = mergeItem.Text.SplitToLines().Count;
List<string> result;
if (splitAtChar != null && mergeCount == 1)
var sb = new StringBuilder();
for (var j = 0; j < numberOfLines && translatedLinesIdx < translatedLines.Count; j++)
{
result = SplitResultAtSplitChar(mergedTranslation, splitAtChar.Value, target.Code);
}
else
{
result = SplitResult(mergedTranslation.SplitToLines(), mergeCount, source.Code);
sb.AppendLine(translatedLines[translatedLinesIdx]);
translatedLinesIdx++;
}
var translatedText = sb.ToString().Trim();
if (allItalic)
var arr = TextSplit.SplitMulti(translatedText, numberOfParagraphs, target.TwoLetterIsoLanguageName);
for (var i = 0; i < arr.Count && paragraphIdx < newSub.Paragraphs.Count; i++)
{
for (var k = 0; k < result.Count; k++)
{
result[k] = "<i>" + result[k] + "</i>";
newSub.Paragraphs[paragraphIdx].Text = Utilities.AutoBreakLine(arr[i], Configuration.Settings.General.SubtitleLineMaximumLength * 2, 0, target.TwoLetterIsoLanguageName);
paragraphIdx++;
}
}
if (allBold)
if (paragraphIdx == mergeCount && HasSameEmptyLines(newSub, sourceSubtitle, index))
{
for (var k = 0; k < result.Count; k++)
var idx = 0;
foreach (var p in newSub.Paragraphs)
{
result[k] = "<b>" + result[k] + "</b>";
}
}
if (result.Count == mergeCount + 1 && result.All(t => !string.IsNullOrEmpty(t)))
{
foreach (var line in result)
{
targetSubtitle.Paragraphs[index].Text = line;
var reformattedText = formattings[idx].ReAddFormatting(p.Text);
targetSubtitle.Paragraphs[index].Text = reformattedText;
index++;
linesTranslate++;
idx++;
}
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<string> 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<Formatting> HandleFormatting(Subtitle sourceSubtitle, int index, string sourceLanguage)
{
var formattings = new List<Formatting>();
@ -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<MergeResultItem> 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<string> SplitMultipleLines(MergeResult mergeResult, string input, string language)
public static List<string> SplitMultipleLines(MergeResult mergeResult, string translatedText, string language)
{
var lines = new List<string>();
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("</" + tag + ">"))
{
return false;
var code = language.TwoLetterIsoLanguageName ?? language.Code;
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";
}
}
return true;
}
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<string> SplitResultAtSplitChar(string translation, char splitAtChar, string languageCode)
{
var idx = translation.IndexOf(splitAtChar);
if (idx < 0 && idx < translation.Length - 1)
{
return new List<string>();
}
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<string> { 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("<i>", string.Empty);
text = text.Replace("</i>", string.Empty);
}
if (allBold)
{
text = text.Replace("<b>", string.Empty);
text = text.Replace("</b>", string.Empty);
}
return text;
}
private static List<string> SplitResult(List<string> 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<string>
{
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<string>
{
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<string>
{
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<string>
{
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<string>
{
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<string>
{
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<string>
{
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<string>
{
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<string>
{
Utilities.AutoBreakLine(arr[0], 42, language == "zh" ? 0 : 25, language),
string.Empty,
string.Empty,
string.Empty,
};
}
return result;
}
return result;
}
}
}

View File

@ -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<MergeResultItem> MergeResultItems { get; set; }
public bool HasError { get; set; }
public bool NoSentenceEndingSource { get; set; }
public bool NoSentenceEndingTarget { get; set; }
}
}
}

View File

@ -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; }
}
}
}

View File

@ -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);

View File

@ -1338,6 +1338,8 @@
<DependentUpon>TimedTextStyles.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Translate\MergeAndSplitHelper.cs" />
<Compile Include="Forms\Translate\MergeResult.cs" />
<Compile Include="Forms\Translate\MergeResultItem.cs" />
<Compile Include="Forms\Translate\SplitHelper.cs" />
<Compile Include="Forms\Translate\TranslateBlock.cs">
<SubType>Form</SubType>