diff --git a/Changelog.txt b/Changelog.txt
index 74ed324a7..8e78bfc80 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -14,7 +14,10 @@
* Update Finnish translation - thx Teijo S
* Update Chinese translation - thx nkh0472
* Update French translation - thx Pierre
+ * Update Italian language - thx bovirus
* Update Russian translation - thx elfriob
+ * Update Polish translation - thx admas
+ * Update Dutch translation - thx Flitskikker
* Improve auto-translate re-split (two lines only)
* Some "Beautify time codes" improvements - thx Flitskikker
* Set file name after .MKS file import - thx RedSoxFan04
@@ -25,6 +28,8 @@
* Update Danish OCR dictionaries - thx Claus
* Add default icon for layout - thx PaulVeld
* Improve Macedonian language auto detect - thx Aco
+ * Auto load video when switching to layout w video - thx Dave
+ * Update Libre translate languages - thx thehijacker
* FIXED:
* Fix Papago translate - thx banziseo
* Fix for "outputfilename" in cmd line with SUP source - thx sapphire-bt
@@ -37,7 +42,9 @@
* Fix for MyMemory translate to Russian/Hebrew - thx darnn
* Fix json text decode bug - thx darnn
* Fix for LRC time code bug - thx fineless71
- * Fix possible crash in mkv/ts reading - thx Maknol
+ * Fix possible crash in MKV/TS reading - thx Maknol
+ * Fix for "Add missing periods" and ASSA tags - thx Firegloom
+ * Fix Whisper CPP Hebrew language code - thx Udo
4.0.3 (23rd December 2023)
diff --git a/src/Test/FixCommonErrors/FixCommonErrorsTest.cs b/src/Test/FixCommonErrors/FixCommonErrorsTest.cs
index 234afef17..85d4a6578 100644
--- a/src/Test/FixCommonErrors/FixCommonErrorsTest.cs
+++ b/src/Test/FixCommonErrors/FixCommonErrorsTest.cs
@@ -8,6 +8,7 @@ using Nikse.SubtitleEdit.Logic;
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
namespace Test.FixCommonErrors
{
@@ -3532,5 +3533,55 @@ namespace Test.FixCommonErrors
Assert.AreEqual("It is I this illustrious illiteration. It's this...", _subtitle.Paragraphs[0].Text);
}
}
+
+ [TestMethod]
+ public void FixMissingOpenBracketOneTest()
+ {
+ var engine = new FixMissingOpenBracket();
+ var sub = GetGenericSub();
+ sub.Paragraphs.First().Text = "Hey, FOO).";
+ engine.Fix(sub, new EmptyFixCallback());
+ Assert.AreEqual("(Hey, FOO).", sub.Paragraphs.First().Text);
+ }
+
+ [TestMethod]
+ public void FixMissingOpenBracketTwoTest()
+ {
+ var engine = new FixMissingOpenBracket();
+ var sub = GetGenericSub();
+ sub.Paragraphs.First().Text = "Reaper, hostiles, 100 meters\neast. Two hundred meters south).";
+ engine.Fix(sub, new EmptyFixCallback());
+ Assert.AreEqual("(Reaper, hostiles, 100 meters\neast. Two hundred meters south).", sub.Paragraphs.First().Text);
+ }
+
+ [TestMethod]
+ public void FixMissingOpenBracketThreeTest()
+ {
+ var engine = new FixMissingOpenBracket();
+ var sub = GetGenericSub();
+ sub.Paragraphs.First().Text = "- Foobar bar zzz).\n- Foo bar Zz";
+ engine.Fix(sub, new EmptyFixCallback());
+ Assert.AreEqual( "- (Foobar bar zzz).\n- Foo bar Zz", sub.Paragraphs.First().Text);
+ }
+ [TestMethod]
+ public void FixMissingOpenBracketFourTest()
+ {
+ var engine = new FixMissingOpenBracket();
+ var sub = GetGenericSub();
+ sub.Paragraphs.First().Text = "Foobar THIS IS A NOISE)";
+ engine.Fix(sub, new EmptyFixCallback());
+ Assert.AreEqual( "Foobar (THIS IS A NOISE)", sub.Paragraphs.First().Text);
+ }
+
+ private static Subtitle GetGenericSub()
+ {
+ return new Subtitle()
+ {
+ Paragraphs =
+ {
+ new Paragraph("Hello World!", 1000, 2000)
+ }
+ };
+ }
}
}
diff --git a/src/libse/AudioToText/WhisperLanguage.cs b/src/libse/AudioToText/WhisperLanguage.cs
index 59c889b75..7d01608aa 100644
--- a/src/libse/AudioToText/WhisperLanguage.cs
+++ b/src/libse/AudioToText/WhisperLanguage.cs
@@ -64,8 +64,7 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
new WhisperLanguage("vi", "vietnamese"),
};
- if (Configuration.Settings.Tools.WhisperChoice == WhisperChoice.Cpp ||
- Configuration.Settings.Tools.WhisperChoice == WhisperChoice.ConstMe)
+ if (Configuration.Settings.Tools.WhisperChoice == WhisperChoice.ConstMe)
{
languages.Add(new WhisperLanguage("iw", "hebrew"));
}
diff --git a/src/libse/AutoTranslate/LibreTranslate.cs b/src/libse/AutoTranslate/LibreTranslate.cs
index 994d23942..faea6395f 100644
--- a/src/libse/AutoTranslate/LibreTranslate.cs
+++ b/src/libse/AutoTranslate/LibreTranslate.cs
@@ -81,36 +81,52 @@ namespace Nikse.SubtitleEdit.Core.AutoTranslate
{
var languageCodes = new List
{
+ "sq",
"ar",
"az",
+ "bn",
+ "bg",
+ "ca",
+ "zh",
+ "zt",
"cs",
"da",
- "de",
- "el",
+ "nl",
"en",
"eo",
- "es",
- "fa",
+ "et",
"fi",
"fr",
- "ga",
+ "de",
+ "el",
"he",
"hi",
"hu",
"id",
+ "ga",
"it",
"ja",
"ko",
- "nl",
+ "lv",
+ "lt",
+ "ms",
+ "nb",
+ "fa",
"pl",
"pt",
+ "ro",
"ru",
- "ru",
+ "sr",
"sk",
+ "sl",
+ "es",
"sv",
+ "tl",
+ "th",
"tr",
+ "ur",
"uk",
- "zh",
+ "vi",
};
var result = new List();
diff --git a/src/libse/Common/Settings.cs b/src/libse/Common/Settings.cs
index 494a61d36..01255521e 100644
--- a/src/libse/Common/Settings.cs
+++ b/src/libse/Common/Settings.cs
@@ -177,6 +177,7 @@ namespace Nikse.SubtitleEdit.Core.Common
public string ChatGptApiKey { get; set; }
public int ChatGptDelaySeconds { get; set; }
public string GeminiProApiKey { get; set; }
+ public bool DisableVidoInfoViaLabel { get; set; }
public bool ListViewSyntaxColorDurationSmall { get; set; }
public bool ListViewSyntaxColorDurationBig { get; set; }
public bool ListViewSyntaxColorOverlap { get; set; }
@@ -5343,6 +5344,12 @@ $HorzAlign = Center
settings.Tools.TranslateViaCopyPasteAutoCopyToClipboard = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
}
+ subNode = node.SelectSingleNode("DisableVidoInfoViaLabel");
+ if (subNode != null)
+ {
+ settings.Tools.DisableVidoInfoViaLabel = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
+ }
+
subNode = node.SelectSingleNode("ListViewSyntaxColorDurationSmall");
if (subNode != null)
{
@@ -11789,6 +11796,7 @@ $HorzAlign = Center
textWriter.WriteElementString("ChatGptApiKey", settings.Tools.ChatGptApiKey);
textWriter.WriteElementString("ChatGptDelaySeconds", settings.Tools.ChatGptDelaySeconds.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("GeminiProApiKey", settings.Tools.GeminiProApiKey);
+ textWriter.WriteElementString("DisableVidoInfoViaLabel", settings.Tools.DisableVidoInfoViaLabel.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ListViewSyntaxColorDurationSmall", settings.Tools.ListViewSyntaxColorDurationSmall.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ListViewSyntaxColorDurationBig", settings.Tools.ListViewSyntaxColorDurationBig.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("ListViewSyntaxColorLongLines", settings.Tools.ListViewSyntaxColorLongLines.ToString(CultureInfo.InvariantCulture));
diff --git a/src/libse/Forms/FixCommonErrors/AddMissingQuotes.cs b/src/libse/Forms/FixCommonErrors/AddMissingQuotes.cs
index 1c513fa6c..102980530 100644
--- a/src/libse/Forms/FixCommonErrors/AddMissingQuotes.cs
+++ b/src/libse/Forms/FixCommonErrors/AddMissingQuotes.cs
@@ -243,14 +243,20 @@ namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
return text;
}
- if (Utilities.CountTagInText(text, "\"") == 1 && Utilities.CountTagInText(text, "”") == 1)
+ const string doubleQuote = "\"";
+ if (Utilities.CountTagInText(text, doubleQuote) == 1)
{
- return text.Replace("”", "\"");
- }
- if (Utilities.CountTagInText(text, "\"") == 1 && Utilities.CountTagInText(text, "“") == 1)
- {
- return text.Replace("“", "\"");
+ if (Utilities.CountTagInText(text, "”") == 1)
+ {
+ return text.Replace("”", doubleQuote);
+ }
+
+ if (Utilities.CountTagInText(text, "“") == 1)
+ {
+ return text.Replace("“", doubleQuote);
+ }
}
+
return text;
}
}
diff --git a/src/libse/Forms/FixCommonErrors/FixDoubleDash.cs b/src/libse/Forms/FixCommonErrors/FixDoubleDash.cs
index 461680dc3..8a6884361 100644
--- a/src/libse/Forms/FixCommonErrors/FixDoubleDash.cs
+++ b/src/libse/Forms/FixCommonErrors/FixDoubleDash.cs
@@ -35,8 +35,12 @@ namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
text = text.TrimEnd();
text = text.Replace("... " + Environment.NewLine, "..." + Environment.NewLine);
text = text.Replace("... ", "..."); // , ...
- text = text.Replace("... ?", "...?");
- text = text.Replace("... !", "...!");
+
+ if (callbacks.Language != "fr")
+ {
+ text = text.Replace("... ?", "...?");
+ text = text.Replace("... !", "...!");
+ }
if (text.IndexOf(Environment.NewLine, StringComparison.Ordinal) > 1)
{
diff --git a/src/libse/Forms/FixCommonErrors/FixMissingOpenBracket.cs b/src/libse/Forms/FixCommonErrors/FixMissingOpenBracket.cs
index fd80939ab..4603be7b3 100644
--- a/src/libse/Forms/FixCommonErrors/FixMissingOpenBracket.cs
+++ b/src/libse/Forms/FixCommonErrors/FixMissingOpenBracket.cs
@@ -1,6 +1,7 @@
using Nikse.SubtitleEdit.Core.Common;
using Nikse.SubtitleEdit.Core.Interfaces;
using System;
+using System.Linq;
namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
{
@@ -11,96 +12,131 @@ namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
public static string FixMissingOpenBracket { get; set; } = "Fix missing [ or ( in line";
}
- private static string Fix(string text, string openB)
- {
- string pre = string.Empty;
- string closeB = openB == "(" ? ")" : "]";
+ private static bool IsIgnorable(char ch) => char.IsWhiteSpace(ch) || ch == '-';
- if (text.Contains(" " + closeB))
+ private static char GetOpeningPair(char tag) => tag == ')' ? '(' : '[';
+
+ private static int CalcInsertPositionFromBeginning(string input)
+ {
+ var len = input.Length;
+ var i = 0;
+
+ // skip asa tag
+ while (i < len && input[i] == '{')
{
- openB = openB + " ";
+ i = input.IndexOf('}', i + 1) + 1;
+ if (i == 0) break;
}
- do
- {
- if (text.Length > 1 && text.StartsWith('-'))
- {
- pre += "- ";
- if (text[1] == ' ')
- {
- text = text.Substring(2);
- }
- else
- {
- text = text.Substring(1);
- }
- }
- if (text.Length > 3 && text.StartsWith("", StringComparison.OrdinalIgnoreCase))
- {
- pre += "";
- if (text[3] == ' ')
- {
- text = text.Substring(4);
- }
- else
- {
- text = text.Substring(3);
- }
- }
- if (text.Length > 1 && (text[0] == ' ' || text[0] == '.'))
- {
- pre += text[0] == '.' ? '.' : ' ';
- text = text.Substring(1);
- while (text.Length > 0 && text[0] == '.')
- {
- pre += ".";
- text = text.Substring(1);
- }
- text = text.TrimStart(' ');
- }
- } while (text.StartsWith("", StringComparison.Ordinal) || text.StartsWith('-'));
+ while (i < len && IsIgnorable(input[i])) i++;
- text = pre + openB + text;
- return text;
+ // skip html tags
+ while (i < len && input[i] == '<')
+ {
+ i = input.IndexOf('>', i + 1) + 1;
+ if (i == 0) break;
+ }
+
+ // skip anything that is not a letter or digit
+ while (i < len && !char.IsLetterOrDigit(input[i])) i++;
+
+ return i;
}
+ private static string RestoreMissingOpenParenthesis(string input)
+ {
+ var len = input.Length;
+
+ // empty string
+ if (len == 0) return input;
+
+ var closeTags = new[] { ']', ')' };
+ // ignore line if contains opening
+ if (input.Any(ch => ch == '(' || ch == '[')) return input;
+
+ var ci = input.IndexOfAny(closeTags);
+ // invalid position
+ if (ci < 1) return input;
+
+ var k = ci - 1;
+ // jump backward if uppercase or any one of the ignorable chars
+ while (k > 0 && char.IsUpper(input[k]) || IsIgnorable(input[k])) k--;
+
+ // note if we have case like: "Hey, FOO)." then we want to insert the open before the "Hey"
+ if (k > 0 && input[k] == ',')
+ {
+ k--;
+ while (k > 0 && char.IsLetterOrDigit(input[k])) k--;
+ }
+
+ // try landing on white-space char
+ if (k >= 0 && k + 1 < len && input[k] != ' ' && input[k + 1] == ' ') k++;
+ // try finding first valid char (this is used to not insert '(' or '[') in to left of a white-space
+ while (k < ci && char.IsWhiteSpace(input[k])) k++;
+
+ // FO) => (FO)
+ if (ci - k > 1)
+ {
+ input = input.Insert(k, GetOpeningPair(input[ci]).ToString());
+ }
+ else
+ {
+ // recalculate value of k from beginning
+ k = CalcInsertPositionFromBeginning(input);
+ if (k < ci)
+ {
+ input = input.Insert(k, GetOpeningPair(input[ci]).ToString());
+ }
+ }
+
+ return input;
+ }
+
+ private static bool IsPerLineRestoration(string[] lines) => lines.Length == 1 || lines.All(l => l.HasSentenceEnding());
+
public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
{
- string fixAction = Language.FixMissingOpenBracket;
- int fixCount = 0;
- for (int i = 0; i < subtitle.Paragraphs.Count; i++)
+ var fixAction = Language.FixMissingOpenBracket;
+ var fixCount = 0;
+ for (var i = 0; i < subtitle.Paragraphs.Count; i++)
{
var p = subtitle.Paragraphs[i];
if (callbacks.AllowFix(p, fixAction))
{
- var hit = false;
- string oldText = p.Text;
- var openIdx = p.Text.IndexOf('(');
- var closeIdx = p.Text.IndexOf(')');
- if (closeIdx >= 0 && (closeIdx < openIdx || openIdx < 0))
+ var oldText = p.Text;
+ var text = p.Text;
+
+ // split only if both lines are closed
+ var lines = p.Text.SplitToLines().ToArray();
+ // logic to perform for when line is/are closed.
+ if (IsPerLineRestoration(lines))
{
- p.Text = Fix(p.Text, "(");
- hit = true;
+ var count = lines.Length;
+ for (var j = 0; j < count; j++)
+ {
+ lines[j] = RestoreMissingOpenParenthesis(lines[j]);
+ }
+
+ // rebuild the text
+ text = count > 1 ? string.Join(Environment.NewLine, lines) : lines[0];
+ }
+ else
+ {
+ // handles 2+ lines even if the their adjacent is not closed
+ text = RestoreMissingOpenParenthesis(text);
}
- openIdx = p.Text.IndexOf('[');
- closeIdx = p.Text.IndexOf(']');
- if (closeIdx >= 0 && (closeIdx < openIdx || openIdx < 0))
- {
- p.Text = Fix(p.Text, "[");
- hit = true;
- }
-
- if (hit)
+ if (oldText.Length != text.Length)
{
fixCount++;
+ p.Text = text;
callbacks.AddFixToListView(p, fixAction, oldText, p.Text);
}
}
}
+
callbacks.UpdateFixStatus(fixCount, Language.FixMissingOpenBracket);
}
-
}
-}
+}
\ No newline at end of file
diff --git a/src/libse/Forms/FixCommonErrors/FixStartWithUppercaseLetterAfterColon.cs b/src/libse/Forms/FixCommonErrors/FixStartWithUppercaseLetterAfterColon.cs
index 0def9fe23..8628eee21 100644
--- a/src/libse/Forms/FixCommonErrors/FixStartWithUppercaseLetterAfterColon.cs
+++ b/src/libse/Forms/FixCommonErrors/FixStartWithUppercaseLetterAfterColon.cs
@@ -1,7 +1,7 @@
-using Nikse.SubtitleEdit.Core.Common;
-using Nikse.SubtitleEdit.Core.Interfaces;
-using System;
+using System;
using System.Globalization;
+using Nikse.SubtitleEdit.Core.Common;
+using Nikse.SubtitleEdit.Core.Interfaces;
namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
{
@@ -12,105 +12,120 @@ namespace Nikse.SubtitleEdit.Core.Forms.FixCommonErrors
public static string StartWithUppercaseLetterAfterColon { get; set; } = "Start with uppercase letter after colon/semicolon";
}
- private static readonly char[] ExpectedChars = { ':', ';' };
public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
{
- string fixAction = Language.StartWithUppercaseLetterAfterColon;
- int noOfFixes = 0;
- for (int i = 0; i < subtitle.Paragraphs.Count; i++)
+ var fixAction = Language.StartWithUppercaseLetterAfterColon;
+ var noOfFixes = 0;
+
+ var count = subtitle.Paragraphs.Count;
+ var isTurkish = IsTurkish(callbacks.Language);
+ // paragraph
+ for (var i = 0; i < count; i++)
{
- var p = new Paragraph(subtitle.Paragraphs[i]);
- Paragraph last = subtitle.GetParagraphOrDefault(i - 1);
- string oldText = p.Text;
- int skipCount = 0;
-
- if (last != null)
+ var p = subtitle.Paragraphs[i];
+ if (!callbacks.AllowFix(p, fixAction))
{
- string lastText = HtmlUtil.RemoveHtmlTags(last.Text);
- if (lastText.EndsWith(':') || lastText.EndsWith(';'))
- {
- var st = new StrippableText(p.Text);
- if (st.StrippedText.Length > 0 && st.StrippedText[0] != char.ToUpper(st.StrippedText[0]))
- {
- p.Text = st.Pre + char.ToUpper(st.StrippedText[0]) + st.StrippedText.Substring(1) + st.Post;
- }
- }
+ continue;
}
-
- if (oldText.Contains(ExpectedChars))
+
+ var text = p.Text;
+ var len = text.Length;
+
+ // text
+ for (var j = 0; j < len; j++)
{
- bool lastWasColon = false;
- for (int j = 0; j < p.Text.Length; j++)
+ var ch = text[j];
+ if (ch == ':' || ch == ';')
{
- var s = p.Text[j];
- if (s == ':' || s == ';')
+ var k = j + 1;
+
+ // skip white space before formatting
+ while (k < len && text[k] == ' ') k++;
+ // skip formatting e.g: , ,...
+ while (k < len && text[k] == '<' || text[k] == '{')
{
- lastWasColon = true;
+ var closingPair = GetClosingPair(text[k]);
+ var closeIdx = text.IndexOf(closingPair, k + 1);
+ if (closeIdx < 0)
+ {
+ k++;
+ break;
+ }
+ k = closeIdx + 1;
}
- else if (lastWasColon)
+ // skip whitespace after formatting
+ while (k < len && text[k] == ' ') k++;
+
+ if (k < len)
{
- // skip whitespace index
- if (j + 2 < p.Text.Length && p.Text[j] == ' ')
+ // slice from k index
+ var textFromK = text.Substring(k);
+
+ if (CanCapitalize(textFromK, callbacks) && !isTurkish)
{
- s = p.Text[++j];
+ text = text.Substring(0, k) + textFromK.CapitalizeFirstLetter();
}
-
- var startFromJ = p.Text.Substring(j);
- if (startFromJ.Length > 3 && startFromJ[0] == '<' && startFromJ[2] == '>' && (startFromJ[1] == 'i' || startFromJ[1] == 'b' || startFromJ[1] == 'u'))
+ else if (Helper.IsTurkishLittleI(text[k], callbacks.Encoding, callbacks.Language))
{
- skipCount = 2;
- }
- else if (startFromJ.StartsWith("'))
- {
- skipCount = (j + startFromJ.IndexOf('>', 6)) - j;
- }
- else if (Helper.IsTurkishLittleI(s, callbacks.Encoding, callbacks.Language))
- {
- p.Text = p.Text.Remove(j, 1).Insert(j, Helper.GetTurkishUppercaseLetter(s, callbacks.Encoding).ToString(CultureInfo.InvariantCulture));
- lastWasColon = false;
- }
- else if (char.IsLower(s))
- {
- // iPhone
- bool change = true;
- if (s == 'i' && p.Text.Length > j + 1)
- {
- if (p.Text[j + 1] == char.ToUpper(p.Text[j + 1]))
- {
- change = false;
- }
- }
- if (change)
- {
- p.Text = p.Text.Remove(j, 1).Insert(j, char.ToUpper(s).ToString(CultureInfo.InvariantCulture));
- }
-
- lastWasColon = false;
- }
- else if (!(" " + Environment.NewLine).Contains(s))
- {
- lastWasColon = false;
- }
-
- // move the: 'j' pointer and reset skipCount to 0
- if (skipCount > 0)
- {
- j += skipCount;
- skipCount = 0;
+ text = text.Remove(j, 1).Insert(j, Helper.GetTurkishUppercaseLetter(text[k], callbacks.Encoding).ToString(CultureInfo.InvariantCulture));
}
}
}
}
- if (oldText != p.Text && callbacks.AllowFix(p, fixAction))
+ if (text != p.Text)
{
noOfFixes++;
- subtitle.Paragraphs[i].Text = p.Text;
+ var oldText = subtitle.Paragraphs[i].Text;
+ subtitle.Paragraphs[i].Text = text;
callbacks.AddFixToListView(subtitle.Paragraphs[i], fixAction, oldText, p.Text);
}
}
+
callbacks.UpdateFixStatus(noOfFixes, Language.StartWithUppercaseLetterAfterColon);
+
+ char GetClosingPair(char ch) => ch == '<' ? '>' : '}';
}
+ private static bool IsTurkish(string lang) => lang.Equals("tr", StringComparison.OrdinalIgnoreCase);
+
+ private static bool CanCapitalize(string input, IFixCallbacks callbacks)
+ {
+ return !IsAppleNaming(input) && BeginsWithLetter(input);
+ }
+
+ ///
+ /// Returns true if first character is convertible to uppercase otherwise false
+ ///
+ private static bool BeginsWithLetter(string input)
+ {
+ if (input.Length == 0)
+ {
+ return false;
+ }
+
+ var ch = input[0];
+
+ return char.IsLetter(ch) && char.IsLower(ch);
+ }
+
+ ///
+ /// Check if word is one of the apple product name e.g; iPhone, iPad, iMac...
+ ///
+ private static bool IsAppleNaming(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ {
+ return false;
+ }
+
+ var len = input.Length;
+ if (len < 3)
+ {
+ return false;
+ }
+
+ return input[0] == 'i' && char.IsUpper(input[1]) && char.IsLower(input[2]);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ui/Controls/NikseUpDown.cs b/src/ui/Controls/NikseUpDown.cs
index ac81f7592..91626c995 100644
--- a/src/ui/Controls/NikseUpDown.cs
+++ b/src/ui/Controls/NikseUpDown.cs
@@ -267,6 +267,21 @@ namespace Nikse.SubtitleEdit.Controls
KeyDown?.Invoke(sender, e);
Invalidate();
}
+ else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
+ {
+ _textBox.SelectAll();
+ e.SuppressKeyPress = true;
+ }
+ if (e.Modifiers == Keys.Control && e.KeyCode == Keys.C)
+ {
+ _textBox.Copy();
+ e.SuppressKeyPress = true;
+ }
+ if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V)
+ {
+ _textBox.Paste();
+ e.SuppressKeyPress = true;
+ }
else
{
KeyDown?.Invoke(sender, e);
diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs
index 7a17798b3..5fa7bee02 100644
--- a/src/ui/Forms/Main.cs
+++ b/src/ui/Forms/Main.cs
@@ -36487,7 +36487,7 @@ namespace Nikse.SubtitleEdit.Forms
private void labelVideoInfo_Click(object sender, EventArgs e)
{
- if (string.IsNullOrEmpty(_videoFileName) || _videoInfo == null)
+ if (string.IsNullOrEmpty(_videoFileName) || _videoInfo == null || Configuration.Settings.Tools.DisableVidoInfoViaLabel)
{
return;
}
diff --git a/src/ui/Languages/it-IT.xml b/src/ui/Languages/it-IT.xml
index c53ce9fd4..28c847255 100644
--- a/src/ui/Languages/it-IT.xml
+++ b/src/ui/Languages/it-IT.xml
@@ -3,7 +3,7 @@
Subtitle Edit
4.0.3
- Tradotto da NAMP e bovirus - Data traduzione: 20.02.2024
+ Tradotto da NAMP e bovirus - Data traduzione: 22.02.2024
it-IT
OK
@@ -965,7 +965,7 @@ Si sfrutta così il ritmo intrinseco dell'immagine.Correggi '--' -> '...'
Elimina >>
Elimina puntini iniziali '...'
- Correggi [ mancante nella riga
+ Correggi [ o ( mancante nella riga
Sostituisci simboli musicali (esempio âTª) con simboli preferiti
'Oh sì!' -> 'Wow... oh sì!'
'>> Roberto: La zuppa è pronta!' -> 'Roberto: La zuppa è pronta!'
diff --git a/src/ui/Languages/pl-PL.xml b/src/ui/Languages/pl-PL.xml
index 4d5b1c0d6..fd2d655d1 100644
--- a/src/ui/Languages/pl-PL.xml
+++ b/src/ui/Languages/pl-PL.xml
@@ -10,10 +10,11 @@
&Anuluj
Tak
Nie
+ Zamknij
Zastosuj
Zastosuj do
Brak
- Wszystko
+ Wszystkie
Podgląd
Pokaż podgląd
Ukryj podgląd
@@ -404,6 +405,11 @@ Kliknij "{0}", aby najpierw wyodrębnić lub zaimportować zmiany ujęć, albo w
Dopasuj kody czasowe do kodów czasowych klatki
Użyj dokładnych kodów czasowych (jeśli są dostępne)
Przyciągaj wskaźniki do zmian ujęcia (jeśli są dostępne)
+ Przegląd nie w pełni połączonych napisów
+ Niektóre napisy nie zostały w pełni połączone zgodnie z profilem użytkownika, najprawdopodobniej z powodu zbyt ciasno zgrupowanych zmian ujęć (możliwe fałszywe alarmy). Możesz przejrzeć te przypadki ręcznie, aby upewnić się, że wskazówki są przyciągane do prawidłowych (rzeczywistych) zmian ujęcia.
+ Linie
+ #{0} – #{1}
+ Odstęp (klatki)
Edycja profilu
@@ -427,6 +433,7 @@ Kliknij "{0}", aby najpierw wyodrębnić lub zaimportować zmiany ujęć, albo w
Łączenie
Wskaźnik wejściowy zmiany ujęcia
Wskaźnik wyjściowy zmiany ujęcia
+ Nadal egzekwuj zasady ogólne, jeśli nie ma to na nie wpływu
Maksymalny odstęp:
Jeśli w międzyczasie nastąpi zmiana ujęcia:
Nie łącz
@@ -956,7 +963,7 @@ Wykorzystujemy naturalny rytm obrazu.
Popraw '--' na wielokropek '...'
Usuń '>>'
Usuń wiodący wielokropek '...'
- Popraw brakujący '[' w linii
+ Popraw brakujący '[' lub '(' w linii
Zastąp symbole muzyczne (np. âTª) preferowanym symbolem
'Ach-- tak!' -> 'Ach... tak!'
'>> Robert: Siema, stary!' -> 'Robert: Siema, stary!'
@@ -1051,9 +1058,9 @@ Wykorzystujemy naturalny rytm obrazu.
Obsługiwane przez {0}
Przepraszamy, potrzebujesz klucza do usług poznawczych "Translator Text" firmy Microsoft, aby móc korzystać z najnowszego programu Microsoft Translator.
-Przejdź do "Opcje -> Ustawienia -> Narzędzia", aby wpisać swój klucz.
+Przejdź do "Opcje -> Ustawienia -> Tłumaczenie automatyczne", aby wpisać swój klucz.
Spróbuję przetłumaczyć bez klucza API... (powolne i z ograniczonymi danymi).
-Aby użyć klucza API przejdź do "Opcje -> Ustawienia -> Narzędzia", aby wprowadzić swój klucz API tłumacza Google.
+Aby użyć klucza API przejdź do "Opcje -> Ustawienia -> Tłumaczenie automatyczne", aby wprowadzić swój klucz API tłumacza Google.
Usługa:
Połącz linie:
Połącz maksymalnie dwie linie
@@ -1319,6 +1326,7 @@ Aby użyć klucza API przejdź do "Opcje -> Ustawienia -> Narzędzia", aby
Zamknij przetłumaczone napisy
Otwórz folder zawierający wideo
&Porównaj...
+ Zweryfikuj kompletność...
S&tatystyki...
&Wtyczki...
Napisy z pliku wideo...
@@ -1565,6 +1573,7 @@ Aby użyć klucza API przejdź do "Opcje -> Ustawienia -> Narzędzia", aby
Indeks dolny
Wyrównanie...
Automatycznie zrównoważ wybrane linie...
+ Równomierne rozmieszczenie wybranych linii (ZNS)
Usuń łamanie linii z zaznaczonych linii...
Efekt maszyny do pisania...
Efekt karaoke...
@@ -1836,6 +1845,8 @@ Kontynuować?
Wykonano sortowanie wg: {0}
Przed automatycznym zrównoważeniem wybranych linii
Liczba automatycznie zrównoważonych linii: {0}
+ Przed równomiernym rozmieszczeniem wybranych linii
+ Liczba równomiernie rozmieszczonych linii: {0}
Przed usunięciem łamania linii z wybranych linii
Liczba linii z usuniętym łamaniem linii: {0}
Przed wielokrotnymi zastąpieniami
@@ -2609,6 +2620,7 @@ może edytować ten sam plik napisów (współpraca)
Połącz dialog z następnym (wstaw myślniki)
Połącz dialog z poprzednim (wstaw myślniki)
Automatyczne równoważenie wybranych linii
+ Równomierne rozmieszczenie wybranych linii (ZNS)
Przejdź do następnej linii
Przejdź do następnej linii (i odtwarzaj w "Trybie tłumacza")
Przejdź do następnej linii i ustaw kursor na końcu
@@ -2708,6 +2720,7 @@ może edytować ten sam plik napisów (współpraca)
Wyodrębnij audio (wybrane linie)
Audio na tekst wybranych linii ({0})
Przełącz jasność (tylko mpv)
+ Tłumaczenie automatyczne wybranych linii
Tłumaczenie, wyszukiwanie niestandardowe 1
Tłumaczenie, wyszukiwanie niestandardowe 2
Tłumaczenie, wyszukiwanie niestandardowe 3
@@ -2837,6 +2850,8 @@ Kontynuować?
Eksportuj jako HTML...
Ustaw nowego aktora/głos
Ustaw aktora/głos {0}
+ Używane
+ Nieużywane
Pobierz bibliotekę mpv
@@ -3150,6 +3165,21 @@ Kontynuować?
Jeśli chcesz to naprawić, wyślij e-mail na adres mailto: niksedk@gmail.com i dołącz kopię napisów.
Importuj jako zwykły tekst...
+
+ Weryfikacja kompletności na podstawie innych napisów
+ Otwórz napisy kontrolne
+ Napisy kontrolne są puste lub nie można ich wczytać.
+ Napisy kontrolne: {0}
+ Pokrywanie się
+ {0:0.##}%
+ Sortuj wg stopnia pokrywania się
+ Sortuj wg czasu
+ Zweryfikuj ponownie
+ Wstaw
+ Wstaw i idź do następnego
+ Odrzuć
+ Odrzuć i idź do następnego
+
Synchronizacja wizualna
Scena początkowa
diff --git a/src/ui/Languages/ru-RU.xml b/src/ui/Languages/ru-RU.xml
index bd4c0108d..6d2e0e377 100644
--- a/src/ui/Languages/ru-RU.xml
+++ b/src/ui/Languages/ru-RU.xml
@@ -3,14 +3,14 @@
Subtitle Edit
4.0.3
- Перевод на русский: Leserg (mailto:leserg@ua.fm)
-Последующие правки и дополнения перевода: Elheym https://discord.gg/Z7a5qtDc || (mailto:Subs.for.everybody@gmail.com)
+ Перевод на русский: Leserg | Elheym | elfriob
ru-RU
ОК
Отмена
Да
Нет
+ Закрыть
Применить
Применить к
Нет
@@ -109,8 +109,8 @@
О программе
- Subtitle Edit - это свободное программное обеспечение,
-распространяемое на основании общественной лицензии GNU.
+ Subtitle Edit - это бесплатное программное обеспечение,
+распространяемое на условиях GNU Public License.
Вы можете свободно распространять, модифицировать и
использовать программу по своему усмотрению.
@@ -154,7 +154,7 @@ https://github.com/SubtitleEdit/subtitleedit
Командная строка: {1} {2}
{0} не удалось извлечь форму сигнала из аудио-файла!
-Командная строка: {1} {2} Примечание: Проверьте свободное место на диске
+Командная строка: {1} {2} Примечание: проверьте свободное место на диске
Недостаточно свободного места на диске!
{0} свободно
Звуковые дорожки не найдены! Создать пустую форму сигнала?
@@ -177,7 +177,7 @@ https://github.com/SubtitleEdit/subtitleedit
Перерасчёта
Добавить секунды
«%» от продолжительности
- Примечание: Временные границы субтитра будут установлены
+ Примечание: временные границы субтитра будут установлены
без наложения на следующий текст
Фиксировано
Миллисекунд(-ы)
@@ -313,7 +313,7 @@ https://github.com/SubtitleEdit/subtitleedit
Удалить переносы из выбранных строк
Найдено строк: {0}
Разделять только строки длиннее, чем
- Только для строк длиннее чем
+ Только для строк длиннее, чем
Пакетная конвертация
@@ -407,6 +407,13 @@ https://github.com/SubtitleEdit/subtitleedit
Согласование тайм-кодов с тайм-кодами кадров
Использовать точные тайм-коды (если доступно)
Привязка метки к смене плана (если доступно)
+ Просмотреть не полностью связанные субтитры
+ Некоторые субтитры не полностью связаны в соответствии с вашим профилем из-за скорости изменения кадров (ложных срабатываний).
+
+Такие случаи вы можете просмотреть вручную, чтобы убедиться, что реплики привязаны к правильным (реальным) изменениям кадра.
+ Строки
+ #{0} – #{1}
+ Разрыв (кадры)
Редактировать профиль
@@ -430,6 +437,7 @@ https://github.com/SubtitleEdit/subtitleedit
Связывание
Нач. метка изм-ния плана
Кон. метка изм-ния плана
+ Применять общие правила, если они не затрагиваются
Макс. интервал:
Если происходит изменение плана:
Не связывать
@@ -439,8 +447,8 @@ https://github.com/SubtitleEdit/subtitleedit
Хотите продолжить?
Создание упрощённого режима
- Введите основные правила и текущий профиль будут обновлен.
- Минимальный интервал между субтитрами.
+ Введите основные правила и текущий профиль будет обновлен
+ Минимальный интервал между субтитрами
Начальные метки:
При смене кадра
1 кадр после смены плана
@@ -454,11 +462,11 @@ https://github.com/SubtitleEdit/subtitleedit
Минимальный интервал перед сменой плана
Для связанных субтитров выровняйте начальную или конечную метку по смене плана, в зависимости от того, какая из них ближе
Макс. сдвиг:
- Сигналы на этом расстоянии от смены кадров будут привязаны к смене кадров.
+ Сигналы на этом расстоянии от смены кадров будут привязаны к смене кадров
Безопасная зона:
- Метки, расположенные на этом расстоянии от изменения плана, будут привязаны к изменению плана.
+ Метки, расположенные на этом расстоянии от изменения плана, будут привязаны к изменению плана
Макс. интервал связывания:
- Если интервал между двумя субтитрами меньше этого значения, субтитры будут объединены.
+ Если интервал между двумя субтитрами меньше этого значения, субтитры будут объединены
После конечной метки при смене плана, интервал может быть короче
Рекомендуется связывать субтитры, чтобы согласовать «ритм» с «миганием» субтитров.
Это обеспечивает более комфортные условия просмотра.
@@ -466,7 +474,7 @@ https://github.com/SubtitleEdit/subtitleedit
После связывания субтитры либо подключаются (т.е. субтитры исчезают, а новые субтитры появляются сразу после небольшой паузы), либо нет.
Это даёт зрителям некоторое представление о том, когда они могут снова переключить своё внимание на экран.
-После того, как субтитры исчезнут при смене плана, интервал связывания может быть немного короче, поскольку смены плана «сбрасывают» изображение.
+После того как субтитры исчезнут при смене плана, интервал связывания может быть немного короче, поскольку смены плана «сбрасывают» изображение.
Мы используем естественный ритм изображения.
Загрузить правила Netflix
кадры(-ов)
@@ -960,7 +968,7 @@ https://github.com/SubtitleEdit/subtitleedit
Исправить символы тире «--» на многоточие «...»
Удалить символы «>>» в начале строки
Удалить многоточие «...» в начале строки
- Добавить недостающие «[» в строке
+ Добавить недостающие [ или ( в строке
Заменить музыкальные символы (напр. âTª) выбранным
'Хм-- да!' -> 'Хм... да!'
'>> Иван: Спасибо!' -> 'Иван: Спасибо!'
@@ -1053,9 +1061,9 @@ https://github.com/SubtitleEdit/subtitleedit
Переводчик Google
Переводчик Microsoft
Переводчик {0}
- Извините, вам нужен секретный ключ клиента Bing от Microsoft, чтобы использовать последнюю версию Bing Translate.
+ К сожалению, для использования последней версии Microsoft Translator вам понадобится ключ «Translator Text» Cognitive Services от Microsoft.
-Перейдите в «Параметры -> Настройки -> Инструменты», чтобы ввести свой секретный ключ клиенту Bing
+Чтобы ввести ключ, перейдите в «Параметры -> Настройки -> Автоматический перевод», чтобы ввести ключ.
Попытка перевести без ключа API… (медленно и с ограничением данных)
Сервис:
Слияние строк:
@@ -1325,6 +1333,7 @@ https://github.com/SubtitleEdit/subtitleedit
Закрыть переведённые субтитры
Открыть папку с субтитрами
Сравнить…
+ Проверка полноты…
Статистика…
Плагины…
Видеофайла…
@@ -1571,6 +1580,7 @@ https://github.com/SubtitleEdit/subtitleedit
Нижний индекс
Выравнивание…
Автовыравнивание выбранных строк…
+ Равномерно распределить выбранные строки (CPS)
Удалить все переносы из выбранных строк…
Эффект машинописи…
Эффект караоке…
@@ -1843,6 +1853,8 @@ https://github.com/SubtitleEdit/subtitleedit
Выполнена сортировка по: {0}
Перед автовыравниванием выделенных строк
Число строк с автовыравниванием: {0}
+ Перед равномерным распределением выделенных строк
+ Равномерно распределённых строк:
Перед удалением разделителей из выбранных строк
Число строк с удалёнными разделителями: {0}
Перед множественной заменой
@@ -2334,7 +2346,7 @@ https://github.com/SubtitleEdit/subtitleedit
Справка
Шрифт пользовательского интерфейса
Интерфейс
- Показывать частоту кадров в панели инструментов
+ Показывать частоту кадров на панели инструментов
Частота кадров по умолчанию
Кодировка файла по умолчанию
Определение ANSI кодировки
@@ -2519,16 +2531,16 @@ https://github.com/SubtitleEdit/subtitleedit
Тире
Тире, но точки для пауз
Настройка
- cps/Длина строки
+ CPS/Длина строки
Все символы
- Исключить пробелы, только cps
+ Исключить пробелы, только CPS
Исключить пробелы
CJK 1, латиница 0.5
CJK 1, латиница 0.5, пробел 0
Игнор. арабскую диакритику
Игнор. арабскую диакритику/пробел
Без пробелов и знак. преп. ()[]-:;,.!?
- Без пробелов и знак. преп., только cps
+ Без пробелов и знак. преп., только CPS
Музыкальный символ
Символы на замену (через запятую)
Исправить ошибки OCR - применить жёсткие правила
@@ -2541,7 +2553,7 @@ https://github.com/SubtitleEdit/subtitleedit
- Авто -
Избранное
Избранные форматы
- Примечание: Избранные форматы будут отображаться первыми при выборе формата, формат по умолчанию будет всегда отображаться первым
+ Примечание: избранные форматы будут отображаться первыми при выборе формата, формат по умолчанию будет всегда отображаться первым
Горячие клавиши
Команда:
Ctrl
@@ -2621,6 +2633,7 @@ https://github.com/SubtitleEdit/subtitleedit
Объединить диалог с предыдущим (вставить тире)
Автоматическая балансировка выбранных линий
+ Равномерно распределить выбранные строки (CPS)
Перейти к следующей строке
Перейти к следующей строке (и играть в «Режиме перевода»)
Перейти к следующей строке и установить курсор в конце
@@ -2795,7 +2808,7 @@ https://github.com/SubtitleEdit/subtitleedit
Удалить тег ASSA у курсора
Сохранить всё
Разное
- Символов/сек (cps), включая пробелы
+ Символов/сек (CPS), включая пробелы
Не переносить после
Переносить после конца предложения (.!?)
Переносить, где большое расстояние между символами
@@ -2808,7 +2821,7 @@ https://github.com/SubtitleEdit/subtitleedit
Как зарегистрироваться
Ключ
Конечная точка токена
- Примечание: Настройки шрифта применяются только к пользовательскому интерфейсу Subtitle Edit.
+ Примечание: настройки шрифта применяются только к пользовательскому интерфейсу Subtitle Edit.
Настройка шрифта субтитров обычно выполняется в видеоплеере, но также может быть выполнена при использовании формата субтитров
со встроенной информацией о шрифтах, например «Advanced SubStation Alpha», или через экспорт в форматы на основе изображений.
Сбросить
@@ -2852,6 +2865,8 @@ https://github.com/SubtitleEdit/subtitleedit
Экспортировать как HTML…
Установить нового актёра/голос
Установить актёра/голос {0}
+ Используемый
+ Неиспользуемый
Загрузить mpv
@@ -3020,8 +3035,8 @@ https://github.com/SubtitleEdit/subtitleedit
Символов/сек. - минимум: {0:0.000}
Символов/сек. - максимум: {0:0.000}
Символов/сек. - в среднем: {0:0.000}
- Символов/сек. - выше оптимальной ({0:0.##} cps): {1} ({2:0.00}%)
- Символов/сек. - выше максимума ({0:0.##} cps): {1} ({2:0.00}%)
+ Символов/сек. - выше оптимальной ({0:0.##} CPS): {1} ({2:0.00}%)
+ Символов/сек. - выше максимума ({0:0.##} CPS): {1} ({2:0.00}%)
Слов/мин. - минимум: {0:0.000}
Слов/мин. - максимум: {0:0.000}
Слов/мин. - среднее: {0:0.000}
@@ -3150,7 +3165,7 @@ https://github.com/SubtitleEdit/subtitleedit
Синхронизация SMPTE
Использовать синхронизацию времени SMPTE для текущих субтитров?
- Примечание: Синхронизацию SMPTE можно изменить в меню «Видео»
+ Примечание: синхронизацию SMPTE можно изменить в меню «Видео»
Да, всегда с частотой кадров, отличной от целого числа
Нет, никогда
@@ -3166,6 +3181,21 @@ https://github.com/SubtitleEdit/subtitleedit
файла субтитров по адресу: niksedk@gmail.com
Импортировать как обычный текст…
+
+ Проверка полноты по другим субтитрам
+ Открыть контрольные субтитры
+ Контрольные субтитры пусты или не могут быть загружены
+ Контрольные субтитры: {0}
+ Покрытие
+ {0:0.##}%
+ Сортировать по покрытию
+ Сортировать по времени
+ Перепроверить
+ Вставить
+ Вставить и к следующему
+ Игнорировать
+ Игнор. и к следующему
+
Визуальная синхронизация
Начало сцены
diff --git a/src/ui/Languages/zh-Hans.xml b/src/ui/Languages/zh-Hans.xml
index 6c4f69ac6..a5964dc81 100644
--- a/src/ui/Languages/zh-Hans.xml
+++ b/src/ui/Languages/zh-Hans.xml
@@ -962,7 +962,7 @@ Command line: {1} {2}
修复 '-- '为 '...'
删除 '>>'
删除开头的 '...'
- 修复行内丢失的 '['
+ 修复行内丢失的 '[' 及 '('
用自己喜欢的符号替换音符 (如 âTª)
'Whoa-- um yeah!' -> 'Whoa... um yeah!'
'>> Robert: Sup dude!' -> 'Robert: Sup dude!'
diff --git a/src/ui/Logic/Ocr/OcrFixEngine.cs b/src/ui/Logic/Ocr/OcrFixEngine.cs
index ef885fe38..b75d931b0 100644
--- a/src/ui/Logic/Ocr/OcrFixEngine.cs
+++ b/src/ui/Logic/Ocr/OcrFixEngine.cs
@@ -1626,9 +1626,9 @@ namespace Nikse.SubtitleEdit.Logic.Ocr
}
}
- string wordWithCasingChanged = GetWordWithDominatedCasing(word);
if (DoSpell(word.ToLowerInvariant()))
{
+ var wordWithCasingChanged = GetWordWithDominatedCasing(word);
guesses.Insert(0, wordWithCasingChanged);
}
}