Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public partial class BatchConvertSettingsViewModel : ObservableObject
public BatchConvertSettingsViewModel(IFolderHelper folderHelper, IWindowService windowService)
{
var encodings = EncodingHelper.GetEncodings().Select(p => p.DisplayName).ToList();
encodings.Insert(0, EncodingHelper.TryToUseSourceEncoding);
TargetEncodings = new ObservableCollection<string>(encodings);

OcrEngines = new ObservableCollection<string> { "nOcr", "BinaryOcr", "Tesseract", "Ollama" };
Expand Down Expand Up @@ -159,16 +160,18 @@ private void LoadSettings()
UseOutputFolder = !UseSourceFolder;
OutputFolder = Se.Settings.Tools.BatchConvert.OutputFolder;
Overwrite = Se.Settings.Tools.BatchConvert.Overwrite;
SelectedTargetEncoding = Se.Settings.Tools.BatchConvert.TargetEncoding;
SelectedOcrEngine = OcrEngines.FirstOrDefault(p => p == Se.Settings.Tools.BatchConvert.OcrEngine) ?? OcrEngines.First();
SelectedTargetEncoding = TargetEncodings.FirstOrDefault(p => p == Se.Settings.Tools.BatchConvert.TargetEncoding)
?? TargetEncodings.FirstOrDefault(p => p == TextEncoding.Utf8WithBom)
?? TargetEncodings.First();
SelectedOcrEngine = OcrEngines.FirstOrDefault(p => p == Se.Settings.Tools.BatchConvert.OcrEngine) ?? OcrEngines.First();
}

private void SaveSettings()
{
Se.Settings.Tools.BatchConvert.SaveInSourceFolder = !UseOutputFolder;
Se.Settings.Tools.BatchConvert.OutputFolder = OutputFolder;
Se.Settings.Tools.BatchConvert.Overwrite = Overwrite;
Se.Settings.Tools.BatchConvert.TargetEncoding = SelectedTargetEncoding ?? TargetEncodings.First();
Se.Settings.Tools.BatchConvert.TargetEncoding = SelectedTargetEncoding ?? TextEncoding.Utf8WithBom;
Se.Settings.Tools.BatchConvert.LanguagePostFix = SelectedLanguagePostFix ?? Se.Language.General.TwoLetterLanguageCode;
Se.Settings.Tools.BatchConvert.OcrEngine = SelectedOcrEngine ?? "nOcr";

Expand Down
4 changes: 3 additions & 1 deletion src/ui/Features/Tools/BatchConvert/BatchConvertViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ public BatchConvertViewModel(
_cancellationToken = _cancellationTokenSource.Token;

_encodings = EncodingHelper.GetEncodings().Select(p => p.DisplayName).ToList();
_encodings.Insert(0, EncodingHelper.TryToUseSourceEncoding);

AutoTranslateModel = string.Empty;
AutoTranslateUrl = string.Empty;
Expand Down Expand Up @@ -773,7 +774,8 @@ private void UpdateOutputProperties()
_encodings.FirstOrDefault(p => p == Se.Settings.Tools.BatchConvert.TargetEncoding);
if (targetEncoding == null)
{
targetEncoding = _encodings.First();
targetEncoding = _encodings.FirstOrDefault(p => p == TextEncoding.Utf8WithBom)
?? _encodings.First();
Se.Settings.Tools.BatchConvert.TargetEncoding = targetEncoding;
}

Expand Down
5 changes: 3 additions & 2 deletions src/ui/Features/Tools/BatchConvert/BatchConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1406,9 +1406,10 @@ private async Task SaveSubtitleFormat(BatchConvertItem item, SubtitleFormat targ
}
}

var converted = targetFormat.ToText(s, _config.TargetEncoding);
var converted = targetFormat.ToText(s, Path.GetFileNameWithoutExtension(item.FileName));
var path = MakeOutputFileName(item, targetFormat.Extension);
await File.WriteAllTextAsync(path, converted, cancellationToken);
var encoding = EncodingHelper.ResolveEncoding(_config.TargetEncoding, item.FileName);
await File.WriteAllTextAsync(path, converted, encoding, cancellationToken);
item.Status = Se.Language.General.Converted;
}
catch (Exception exception)
Expand Down
38 changes: 38 additions & 0 deletions src/ui/Logic/EncodingHelper.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using Nikse.SubtitleEdit.Core.Common;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Nikse.SubtitleEdit.Logic;

public static class EncodingHelper
{
// Stable sentinel for the batch-convert "use the source file's encoding" option.
// Stored verbatim in settings, so kept English (matches "UTF-8 with BOM" et al.).
public const string TryToUseSourceEncoding = "Try to use source encoding";

public static List<TextEncoding> GetEncodings()
{
var encodingList = new List<TextEncoding>();
Expand Down Expand Up @@ -38,4 +44,36 @@ public static List<Encoding> GetRawEncodings()

return encodingList;
}

/// <summary>
/// Resolves a target-encoding <see cref="TextEncoding.DisplayName"/> (as stored in
/// settings) to a concrete <see cref="Encoding"/>. Honors the <see cref="TryToUseSourceEncoding"/>
/// sentinel by detecting the source file's encoding. Falls back to UTF-8 with BOM
/// when the name is empty, unknown, or detection fails.
Comment on lines +51 to +52
/// </summary>
public static Encoding ResolveEncoding(string? displayName, string? sourceFile)
{
if (string.Equals(displayName, TryToUseSourceEncoding, System.StringComparison.Ordinal))
{
if (!string.IsNullOrEmpty(sourceFile) && File.Exists(sourceFile))
{
return LanguageAutoDetect.GetEncodingFromFile(sourceFile);
}
return new UTF8Encoding(true);
}

if (string.IsNullOrEmpty(displayName) ||
string.Equals(displayName, TextEncoding.Utf8WithBom, System.StringComparison.Ordinal))
{
return new UTF8Encoding(true);
}

if (string.Equals(displayName, TextEncoding.Utf8WithoutBom, System.StringComparison.Ordinal))
{
return new UTF8Encoding(false);
}

var match = GetEncodings().FirstOrDefault(e => e.DisplayName == displayName);
return match?.Encoding ?? new UTF8Encoding(true);
Comment on lines +76 to +77
}
}