diff --git a/src/Filee.App/Services/ConversionService.cs b/src/Filee.App/Services/ConversionService.cs
index 44b0c0fd9..7b8a99e7c 100644
--- a/src/Filee.App/Services/ConversionService.cs
+++ b/src/Filee.App/Services/ConversionService.cs
@@ -213,6 +213,8 @@ private void OnJobUpdated(object? sender, ConversionJob job)
private void OnJobFinished(object? sender, ConversionJob job)
{
var entry = HistoryEntry.From(job);
+ if (string.IsNullOrWhiteSpace(job.Preset.Name) && job.Preset.NameKey is { } key && _loc[key] == job.PresetDisplayName)
+ entry.PresetNameKey = key;
entry.WatchRuleId = _watchJobs.GetValueOrDefault(job.Id);
_store.AddHistory(entry);
if (_waiting.TryGetValue(job.Id, out var waiting))
diff --git a/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs b/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
index 663c6bfd5..e6487327d 100644
--- a/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
+++ b/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
@@ -34,7 +34,7 @@ public HistoryItemViewModel(HistoryEntry entry, ILocalizer loc, IPlatformService
_platform = platform;
_conversions = conversions;
_store = store;
- Title = entry.PresetName;
+ Title = NameOf(entry, loc);
Subtitle = entry.Sources.Count == 1 ? Path.GetFileName(entry.Sources[0]) : loc.Format("home.files", entry.Sources.Count);
Time = entry.FinishedAt.Date == DateTime.Today ? entry.FinishedAt.ToString("t") : entry.FinishedAt.ToString("d");
Failures = entry.Failures.Count > 0
@@ -61,6 +61,10 @@ public HistoryItemViewModel(HistoryEntry entry, ILocalizer loc, IPlatformService
UndoneText = entry.Undone ? loc[entry.OriginalsInTrash ? "home.undone_original" : "home.undone"] : "";
}
+ /// The preset's name in the language Filee is in now when it is a built-in one, else as it was saved.
+ internal static string NameOf(HistoryEntry entry, ILocalizer loc) =>
+ entry.PresetNameKey is { } key && loc[key] is var name && name != key ? name : entry.PresetName;
+
///
/// Undo (#553) is offered while the results not moved yet are all as the job left them, so a file changed since is
/// never moved; after an Undo that stopped half-way, for the ones it didn't get to.
@@ -288,7 +292,7 @@ private void Reload()
var query = Search.Trim();
// The entries are picked first, then built: building one looks for its outputs on disk.
var entries = _store.History
- .Where(entry => query.Length == 0 || Matches(entry, query))
+ .Where(entry => query.Length == 0 || Matches(entry, query, _loc))
.Take(Shown)
.ToList();
History.Clear();
@@ -338,9 +342,9 @@ private void LoadThumbnails()
}, token);
}
- private static bool Matches(HistoryEntry entry, string query)
+ private static bool Matches(HistoryEntry entry, string query, ILocalizer loc)
{
- return Contains(entry.PresetName) || entry.Sources.Any(source => Contains(Path.GetFileName(source)));
+ return Contains(HistoryItemViewModel.NameOf(entry, loc)) || Contains(entry.PresetName) || entry.Sources.Any(source => Contains(Path.GetFileName(source)));
bool Contains(string? text) => text?.Contains(query, StringComparison.CurrentCultureIgnoreCase) == true;
}
diff --git a/src/Filee.Core/History/HistoryEntry.cs b/src/Filee.Core/History/HistoryEntry.cs
index 9efa654ac..3fa418fa7 100644
--- a/src/Filee.Core/History/HistoryEntry.cs
+++ b/src/Filee.Core/History/HistoryEntry.cs
@@ -12,6 +12,12 @@ public sealed class HistoryEntry
public DateTime FinishedAt { get; set; }
public string PresetId { get; set; } = "";
public string PresetName { get; set; } = "";
+
+ ///
+ /// The built-in preset's name key when the job showed its translated name, so the entry follows the language Filee
+ /// is in now (#744); null for the user's own names and in entries from before.
+ ///
+ public string? PresetNameKey { get; set; }
public JobState State { get; set; }
public List Sources { get; set; } = [];
public List Outputs { get; set; } = [];
diff --git a/tests/Filee.App.Tests/RecentConversionTests.cs b/tests/Filee.App.Tests/RecentConversionTests.cs
index 5b5f7292b..4d5433820 100644
--- a/tests/Filee.App.Tests/RecentConversionTests.cs
+++ b/tests/Filee.App.Tests/RecentConversionTests.cs
@@ -399,6 +399,25 @@ public void Recent_conversions_show_their_results(string language, bool dark)
}
}
+ [AvaloniaFact]
+ public void A_built_in_preset_name_follows_the_language_filee_is_in_now()
+ {
+ // #744: converted while Filee was in Chinese, looked at in English.
+ TestServices.EnsureInitialized("en");
+ var loc = AppHost.Get();
+ var platform = new OpeningPlatform(false);
+ var builtIn = Entry([], "长图");
+ builtIn.PresetNameKey = "preset.long_image";
+ Assert.Equal(loc["preset.long_image"], new HistoryItemViewModel(builtIn, loc, platform).Title);
+ Assert.NotEqual("长图", loc["preset.long_image"]);
+
+ // The user's own name, an older entry and a key Filee no longer has keep the saved name.
+ Assert.Equal("My PNG", new HistoryItemViewModel(Entry([], "My PNG"), loc, platform).Title);
+ var gone = Entry([], "旧名");
+ gone.PresetNameKey = "preset.no_such_preset";
+ Assert.Equal("旧名", new HistoryItemViewModel(gone, loc, platform).Title);
+ }
+
private static HistoryEntry Entry(List outputs, string preset = "PNG", List? sources = null) => new()
{
FinishedAt = DateTime.Now,