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