From 02e9579fb57f5fb2fa8633b2af1b87ca91e0a115 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 22 Jul 2026 00:00:57 -0400 Subject: [PATCH] game: ensure overwritten subtitle lines have the `merge` flag disabled (#4352) Fixes another long-standing subtitle translation bug. There is a `merge` flag on each subtitle line, the idea being that we would merge in the text from the base game if this was set. However in jak 2 and beyond: - The subtitles for english (base) are not predefined for the cutscenes, only the hints. The rest are in the game files and we do not simultaneously load both languages when the game is running so there is no trivial fallback path. - However, every subtitle language by default inherits the base games metadata, where all `merge` flags are set to `true` This means that all custom cutscene translations were being ignored unless this flag was set to false in the metadata file for each line. This is what finnish does since it changes the number of lines and their timings, and is why it works fine. This flag can probably be completely removed, as per the above, it serves no actual purpose. All it does in our code is if it's set, we skip the line when writing out the subtitle file. But for now i simply just iterate through and flip these flags automatically if the language overrode the cutscene. Tested on english/finnish/pt-BR image --- .../serialization/subtitles/subtitles_v2.cpp | 18 ++++++++++++++++++ common/serialization/subtitles/subtitles_v2.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/common/serialization/subtitles/subtitles_v2.cpp b/common/serialization/subtitles/subtitles_v2.cpp index 84dbde76d6..5bb2be0adc 100644 --- a/common/serialization/subtitles/subtitles_v2.cpp +++ b/common/serialization/subtitles/subtitles_v2.cpp @@ -186,6 +186,24 @@ GameSubtitlePackage read_json_files_v2(const GameSubtitleDefinitionFile& file_in "subtitle_line_path"); lang_lines = package.combined_lines; } + // Update any line metadata to `merge = false` if they've been defined + // otherwise, the lines get skipped + for (const auto [scene_name, scene_lines] : lang_lines.cutscenes) { + if (package.combined_meta.cutscenes.find(scene_name) != + package.combined_meta.cutscenes.end()) { + for (int i = 0; i < package.combined_meta.cutscenes[scene_name].lines.size(); i++) { + package.combined_meta.cutscenes[scene_name].lines[i].merge = false; + } + } + } + for (const auto [scene_name, scene_lines] : lang_lines.other) { + if (package.combined_meta.other.find(scene_name) != package.combined_meta.other.end()) { + for (int i = 0; i < package.combined_meta.other[scene_name].lines.size(); i++) { + package.combined_meta.other[scene_name].lines[i].merge = false; + } + } + } + for (const auto& [scene_name, scene_info] : lang_lines.cutscenes) { package.scenes_defined_in_lang.insert(scene_name); } diff --git a/common/serialization/subtitles/subtitles_v2.h b/common/serialization/subtitles/subtitles_v2.h index f5c22e4bb5..35ec9a37eb 100644 --- a/common/serialization/subtitles/subtitles_v2.h +++ b/common/serialization/subtitles/subtitles_v2.h @@ -10,6 +10,9 @@ struct SubtitleLineMetadata { int frame_end; bool offscreen; std::string speaker; + // NOTE: merge is a bad name, as we don't actually merge anything (the game doesn't load the + // english subtitles as well) and all this does if set is it's ignored when being written out to + // the file bool merge; bool operator==(const SubtitleLineMetadata& other) const {