|
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using GamecraftModdingAPI;
- using GamecraftModdingAPI.App;
- using GamecraftModdingAPI.Commands;
- using GamecraftModdingAPI.Utility;
- using HarmonyLib;
- using IllusionPlugin;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using ServiceLayer;
-
- namespace Localization
- {
- public class LocalizationMod : IEnhancedPlugin
- {
- private readonly DirectoryInfo _pluginFolder = new DirectoryInfo(Path.Combine("Plugins", "Localization"));
- private Dictionary<string, string> _origStrings;
- private readonly string[] _embeddedLanguages = Assembly.GetExecutingAssembly().GetManifestResourceNames();
-
- public override void OnApplicationStart()
- {
- Main.Init();
- if (!_pluginFolder.Exists)
- _pluginFolder.Create();
- string settingsPath = Path.Combine(_pluginFolder.FullName, "settings.json");
- JObject settings;
- if (File.Exists(settingsPath))
- {
- try
- {
- using (var stream = new JsonTextReader(File.OpenText(settingsPath)))
- settings = JObject.Load(stream);
- string lang = (string) (settings["lang"] ?? (settings["lang"] = "en"));
- lang = lang.ToLower();
- if (lang != "en")
- LoadTranslation(lang);
- }
- catch (Exception e)
- {
- Logging.LogError(e);
- settings = new JObject();
- }
- }
- else
- settings = new JObject();
-
- CommandBuilder.Builder("SetLanguage", "Sets the game's language")
- .Action<string>(lang =>
- {
- lang = lang.ToLower();
- settings["lang"] = lang;
- using (var stream = new JsonTextWriter(new StreamWriter(File.OpenWrite(settingsPath))))
- settings.WriteTo(stream);
- LoadTranslation(lang);
-
- }).Build();
- CommandBuilder.Builder("ListLanguages", "Lists available languages")
- .Action(() =>
- {
- Logging.CommandLog(new[] {"en"}.Concat(_pluginFolder.EnumerateFiles()
- .Where(file => file.Extension == ".json"
- && (file.Name.Length < 8 || file.Name.Contains("-")))
- .Select(file => file.Name.Replace(file.Extension, "")))
- .Concat(_embeddedLanguages)
- .Select(lang => lang.Replace("Localization.", "").Replace(".json", ""))
- .Distinct().Aggregate((a, b) => a + ", " + b));
- }).Build();
- CommandBuilder.Builder("DumpLangStrings", "Dumps the current strings. Set language to en first.")
- .Action(() =>
- {
- File.WriteAllText(Path.Combine(_pluginFolder.FullName, "dumped.json"),
- JsonConvert.SerializeObject(_origStrings, Formatting.Indented));
- }).Build();
-
- if (!settings.ContainsKey("autoload"))
- {
- settings["autoload"] = true;
- using (var stream = new JsonTextWriter(new StreamWriter(File.OpenWrite(settingsPath))))
- settings.WriteTo(stream);
- }
-
- if ((bool) settings["autoload"])
- Client.EnterMenu += TryLoadSteamLanguageMenuEnterEvent;
- }
-
- public override void OnApplicationQuit()
- {
- Main.Shutdown();
- }
-
- private void LoadTranslation(string lang)
- {
- Logging.CommandLog("Loading translation for " + lang + "...");
- LoadOriginalStrings();
- string langPath = Path.Combine(_pluginFolder.FullName, lang + ".json");
- if (!File.Exists(langPath))
- {
- if (_embeddedLanguages.Contains("Localization." + lang + ".json"))
- langPath = null;
- else
- {
- if (lang == "en")
- {
- AccessTools.Method(typeof(LocalizationService), "Init").Invoke(null, new object[0]);
- _origStrings = null; //Reset as the object changed
- LoadOriginalStrings();
- Logging.CommandLog("Strings reset to default. (" + _origStrings.Count + " strings in total)");
- return;
- }
-
- Logging.CommandLogError("Could not find json file!");
- return;
- }
- }
-
- string jsonText = langPath != null ? File.ReadAllText(langPath) : null;
- if (jsonText == null)
- {
- var stream = Assembly.GetExecutingAssembly()
- .GetManifestResourceStream("Localization." + lang + ".json");
- if (stream != null)
- using (var st = new StreamReader(stream))
- jsonText = st.ReadToEnd();
- else
- {
- Logging.CommandLogError("Failed to load embedded translation for " + lang);
- return;
- }
- }
-
- var strings = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonText);
- foreach (var kv in strings)
- {
- if (!_origStrings.Remove(kv.Key))
- Logging.CommandLogWarning(kv.Key + " wasn't in the original file.");
- _origStrings.Add(kv.Key, kv.Value);
- }
-
- Logging.CommandLog("Updated " + strings.Count + " strings (" + _origStrings.Count + " strings in total)");
- }
-
- private void LoadOriginalStrings()
- {
- if (_origStrings != null) return;
- _origStrings =
- (Dictionary<string, string>) AccessTools.Field(typeof(LocalizationService), "LocalizedStrings")
- .GetValue(null);
- }
-
- private void TryLoadSteamLanguageMenuEnterEvent(object sender, MenuEventArgs args)
- {
- TryLoadSteamLanguage();
- Client.EnterMenu -= TryLoadSteamLanguageMenuEnterEvent;
- }
-
- private void TryLoadSteamLanguage()
- {
- string lang = Steamworks.SteamUtils.SteamUILanguage;
- string first2 = lang.Substring(0, 2);
- // try some possibly valid language codes
- if (File.Exists(Path.Combine(_pluginFolder.FullName, lang + ".json")))
- {
- Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
- LoadTranslation(lang);
- }
- else if (File.Exists(Path.Combine(_pluginFolder.FullName, first2 + ".json")))
- {
- lang = first2;
- Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
- LoadTranslation(lang);
- }
- else if (File.Exists(Path.Combine(_pluginFolder.FullName, first2 + "-" + first2 + ".json")))
- {
- // a lot of standard languages codes are like fr-fr (French from France), but this won't work for English (nor fr-CA French from Canada)
- lang = first2 + "-" + first2;
- Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
- LoadTranslation(lang);
- }
- else
- {
- Logging.MetaLog($"Translations for Steam UI language {lang} are not available, skipping...");
- }
-
- }
-
- public override string Name { get; } = "LocalizationMod";
- public override string Version { get; } = "1.0.0";
- }
- }
|