I have my game set up so it saves my custom scene name labels as well as the time and date, but I want these to be translatable too. I have my custom handler set like this:
using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;
using SceneM = UnityEngine.SceneManagement.SceneManager;
namespace AC
{
public class CustomSaveFileHandler_Timestamped : SaveFileHandler_SystemFile
{
private const string LogPrefix = "[CustomSaveFileHandler_Timestamped]";
public override void Save(SaveFile saveFile, string dataString, Action<bool> callback)
{
if (saveFile == null)
{
ACDebug.LogWarning($"{LogPrefix} Save called with null SaveFile.");
base.Save(saveFile, dataString, callback);
return;
}
string rawScene = SceneM.GetActiveScene().name;
int lang = GetCurrentLanguageIndex_Robust();
ACDebug.Log($"{LogPrefix} Language index at save-time = {lang}");
string friendlyScene = GetFriendlySceneName(rawScene, lang);
string timeStamp = DateTime.Now.ToString("dd/MM/yyyy HH:mm");
saveFile.label = $"{friendlyScene}\n[{timeStamp}]";
ACDebug.Log($"{LogPrefix} Saving saveID {saveFile.saveID} with label:\n\"{saveFile.label}\"");
base.Save(saveFile, dataString, success =>
{
ACDebug.Log($"{LogPrefix} Save finished for ID {saveFile.saveID} (success={success})");
callback?.Invoke(success);
});
}
// --------------------------------------------------------------------
// LANGUAGE DETECTION (AC 1.85.5 safe + robust fallbacks)
// Your setup (per screenshot):
// 0 = English (Original)
// 1 = German
// 2 = Spanish
// --------------------------------------------------------------------
private int GetCurrentLanguageIndex_Robust()
{
// 1) Preferred: static Options.GetLanguage()
try
{
return Options.GetLanguage();
}
catch { /* ignore */ }
// 2) Fallback: try instance KickStarter.options.GetLanguage() (some setups)
try
{
if (KickStarter.options != null)
{
MethodInfo mi = KickStarter.options.GetType().GetMethod("GetLanguage", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (mi != null && mi.ReturnType == typeof(int))
{
return (int)mi.Invoke(KickStarter.options, null);
}
}
}
catch { /* ignore */ }
// 3) Fallback: look for optionsData.language (common in AC)
try
{
if (KickStarter.options != null)
{
object optionsData = GetMemberValue(KickStarter.options, "optionsData");
if (optionsData != null)
{
object langObj = GetMemberValue(optionsData, "language");
if (langObj is int i) return i;
}
}
}
catch { /* ignore */ }
// 4) Fallback: look for language-ish fields on SpeechManager (names vary by version)
try
{
if (KickStarter.speechManager != null)
{
// Try a few likely member names without hardcoding AC version-specific APIs
string[] candidates = { "language", "currentLanguage", "selectedLanguage", "gameLanguage", "speechLanguage" };
foreach (string name in candidates)
{
object val = GetMemberValue(KickStarter.speechManager, name);
if (val is int i) return i;
}
}
}
catch { /* ignore */ }
// Default to original language
return 0;
}
private object GetMemberValue(object obj, string memberName)
{
if (obj == null) return null;
Type t = obj.GetType();
// Property
PropertyInfo pi = t.GetProperty(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (pi != null) return pi.GetValue(obj, null);
// Field
FieldInfo fi = t.GetField(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (fi != null) return fi.GetValue(obj);
return null;
}
// --------------------------------------------------------------------
// TRANSLATION
// German first, then Spanish, else English (fallback)
// --------------------------------------------------------------------
private string GetFriendlySceneName(string raw, int lang)
{
if (lang == 1) return GetGermanSceneName(raw); // German
if (lang == 2) return GetSpanishSceneName(raw); // Spanish
return GetEnglishSceneName(raw); // English / fallback
}
private string GetEnglishSceneName(string raw)
{
switch (raw)
{
case "MeMeBedroom": return "The Bedroom";
case "MeMeUpstairs": return "The Balcony";
case "MeMeBasement": return "The Basement";
default: return raw;
}
}
private string GetSpanishSceneName(string raw)
{
switch (raw)
{
case "MeMeBedroom": return "El Dormitorio";
case "MeMeUpstairs": return "El Balcón";
case "MeMeBasement": return "El Sótano";
default: return raw;
}
}
private string GetGermanSceneName(string raw)
{
switch (raw)
{
case "MeMeBedroom": return "Das Schlafzimmer";
case "MeMeUpstairs": return "Der Balkon";
case "MeMeBasement": return "Der Keller";
default: return raw;
}
}
}
}
Which works, BUT doesn't work if I change the langauge in game, any ideas how to fix this? THANKS
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
Save-game labels support variable tokens. Rather than setting the label to the scene's name directly, instead set it to a token that references a Global String variable that stores that scene's name.
And just to confirm, scene names are not gathered in speech manager?
They are not.
Sorted it thanks Chris.