From 58794579138f3055c0377f3c5bf6ccead0f60fdf Mon Sep 17 00:00:00 2001 From: Phantomical Date: Thu, 9 Jul 2026 02:58:47 -0700 Subject: [PATCH] Properly localize the text in the ReflectionTypeLoadException popup The exception can happen before GameDatabase has actually been localized. If it does, then you get the english strings in the warning. We fix this by deferring localization until later, when the message is actually rendered. --- .../ReflectionTypeLoadExceptionHandler.cs | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/KSPCommunityFixes/Modding/ReflectionTypeLoadExceptionHandler.cs b/KSPCommunityFixes/Modding/ReflectionTypeLoadExceptionHandler.cs index dfedacba..0a86a394 100644 --- a/KSPCommunityFixes/Modding/ReflectionTypeLoadExceptionHandler.cs +++ b/KSPCommunityFixes/Modding/ReflectionTypeLoadExceptionHandler.cs @@ -25,14 +25,13 @@ class ReflectionTypeLoadExceptionHandler : MonoBehaviour private class FailedAssembly { public string errorMessage; - public string guiMessage; + + private readonly string assemblyName; + private readonly string assemblyLocation; + private readonly List missingDependencies = new List(); public FailedAssembly(Assembly assembly) { - string assemblyName; - string assemblyLocation; - List missingDependencies = new List(); - try { assemblyName = assembly.GetName().Name; @@ -70,24 +69,40 @@ public FailedAssembly(Assembly assembly) errorMessage = $"[KSPCF] A ReflectionTypeLoadException thrown by Assembly.GetTypes() has been handled by KSP Community Fixes." + $"\nThis is usually harmless, but indicates that the \"{assemblyName}\" plugin failed to load (location: \"{assemblyLocation}\")"; - guiMessage = Localizer.Format(LOC_F_PluginLoadFailed_name_in_location, $"{assemblyName}", $"\"{assemblyLocation}\""); - if (missingDependencies.Count > 0) { errorMessage += $"\nIt happened because \"{assemblyName}\" is missing the following dependencies : "; - guiMessage += $"\n{LOC_PluginLoadFailed_missingDep} : "; for (int i = 0; i < missingDependencies.Count; i++) { if (i > 0) - { errorMessage += ", "; - guiMessage += ", "; - } errorMessage += "\"" + missingDependencies[i] + "\""; + } + } + } + + // Build the GUI message lazily at render time. The LOC_ fields are only populated by + // LocalizationUtils.ParseLocalization() once KSPCommunityFixes.Start() runs, which can happen + // after a FailedAssembly is constructed during early assembly loading. Formatting here (rather + // than in the constructor) ensures the localized strings are used. See issue #403. + public string GetGuiMessage() + { + string guiMessage = Localizer.Format(LOC_F_PluginLoadFailed_name_in_location, $"{assemblyName}", $"\"{assemblyLocation}\""); + + if (missingDependencies.Count > 0) + { + guiMessage += $"\n{LOC_PluginLoadFailed_missingDep} : "; + for (int i = 0; i < missingDependencies.Count; i++) + { + if (i > 0) + guiMessage += ", "; + guiMessage += "" + missingDependencies[i] + ""; } } + + return guiMessage; } } @@ -139,7 +154,7 @@ private void OnGUI() GUILayout.Label(LOC_PluginsLoadFailed, labelStyle); foreach (FailedAssembly assembly in failedAssemblies.Values) - GUILayout.Label(assembly.guiMessage, labelStyle); + GUILayout.Label(assembly.GetGuiMessage(), labelStyle); GUILayout.EndVertical(); GUILayout.EndArea();