Localization mod for Gamecraft.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

193 行
7.8KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using GamecraftModdingAPI;
  7. using GamecraftModdingAPI.App;
  8. using GamecraftModdingAPI.Commands;
  9. using GamecraftModdingAPI.Utility;
  10. using HarmonyLib;
  11. using IllusionPlugin;
  12. using Newtonsoft.Json;
  13. using Newtonsoft.Json.Linq;
  14. using ServiceLayer;
  15. namespace Localization
  16. {
  17. public class LocalizationMod : IEnhancedPlugin
  18. {
  19. private readonly DirectoryInfo _pluginFolder = new DirectoryInfo(Path.Combine("Plugins", "Localization"));
  20. private Dictionary<string, string> _origStrings;
  21. private readonly string[] _embeddedLanguages = Assembly.GetExecutingAssembly().GetManifestResourceNames();
  22. public override void OnApplicationStart()
  23. {
  24. Main.Init();
  25. if (!_pluginFolder.Exists)
  26. _pluginFolder.Create();
  27. string settingsPath = Path.Combine(_pluginFolder.FullName, "settings.json");
  28. JObject settings;
  29. if (File.Exists(settingsPath))
  30. {
  31. try
  32. {
  33. using (var stream = new JsonTextReader(File.OpenText(settingsPath)))
  34. settings = JObject.Load(stream);
  35. string lang = (string) (settings["lang"] ?? (settings["lang"] = "en"));
  36. lang = lang.ToLower();
  37. if (lang != "en")
  38. LoadTranslation(lang);
  39. }
  40. catch (Exception e)
  41. {
  42. Logging.LogError(e);
  43. settings = new JObject();
  44. }
  45. }
  46. else
  47. settings = new JObject();
  48. CommandBuilder.Builder("SetLanguage", "Sets the game's language")
  49. .Action<string>(lang =>
  50. {
  51. lang = lang.ToLower();
  52. settings["lang"] = lang;
  53. using (var stream = new JsonTextWriter(new StreamWriter(File.OpenWrite(settingsPath))))
  54. settings.WriteTo(stream);
  55. LoadTranslation(lang);
  56. }).Build();
  57. CommandBuilder.Builder("ListLanguages", "Lists available languages")
  58. .Action(() =>
  59. {
  60. Logging.CommandLog(new[] {"en"}.Concat(_pluginFolder.EnumerateFiles()
  61. .Where(file => file.Extension == ".json"
  62. && (file.Name.Length < 8 || file.Name.Contains("-")))
  63. .Select(file => file.Name.Replace(file.Extension, "")))
  64. .Concat(_embeddedLanguages)
  65. .Select(lang => lang.Replace("Localization.", "").Replace(".json", ""))
  66. .Distinct().Aggregate((a, b) => a + ", " + b));
  67. }).Build();
  68. CommandBuilder.Builder("DumpLangStrings", "Dumps the current strings. Set language to en first.")
  69. .Action(() =>
  70. {
  71. File.WriteAllText(Path.Combine(_pluginFolder.FullName, "dumped.json"),
  72. JsonConvert.SerializeObject(_origStrings, Formatting.Indented));
  73. }).Build();
  74. if (!settings.ContainsKey("autoload"))
  75. {
  76. settings["autoload"] = true;
  77. using (var stream = new JsonTextWriter(new StreamWriter(File.OpenWrite(settingsPath))))
  78. settings.WriteTo(stream);
  79. }
  80. if ((bool) settings["autoload"])
  81. Client.EnterMenu += TryLoadSteamLanguageMenuEnterEvent;
  82. }
  83. public override void OnApplicationQuit()
  84. {
  85. Main.Shutdown();
  86. }
  87. private void LoadTranslation(string lang)
  88. {
  89. Logging.CommandLog("Loading translation for " + lang + "...");
  90. LoadOriginalStrings();
  91. string langPath = Path.Combine(_pluginFolder.FullName, lang + ".json");
  92. if (!File.Exists(langPath))
  93. {
  94. if (_embeddedLanguages.Contains("Localization." + lang + ".json"))
  95. langPath = null;
  96. else
  97. {
  98. if (lang == "en")
  99. {
  100. AccessTools.Method(typeof(LocalizationService), "Init").Invoke(null, new object[0]);
  101. _origStrings = null; //Reset as the object changed
  102. LoadOriginalStrings();
  103. Logging.CommandLog("Strings reset to default. (" + _origStrings.Count + " strings in total)");
  104. return;
  105. }
  106. Logging.CommandLogError("Could not find json file!");
  107. return;
  108. }
  109. }
  110. string jsonText = langPath != null ? File.ReadAllText(langPath) : null;
  111. if (jsonText == null)
  112. {
  113. var stream = Assembly.GetExecutingAssembly()
  114. .GetManifestResourceStream("Localization." + lang + ".json");
  115. if (stream != null)
  116. using (var st = new StreamReader(stream))
  117. jsonText = st.ReadToEnd();
  118. else
  119. {
  120. Logging.CommandLogError("Failed to load embedded translation for " + lang);
  121. return;
  122. }
  123. }
  124. var strings = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonText);
  125. foreach (var kv in strings)
  126. {
  127. if (!_origStrings.Remove(kv.Key))
  128. Logging.CommandLogWarning(kv.Key + " wasn't in the original file.");
  129. _origStrings.Add(kv.Key, kv.Value);
  130. }
  131. Logging.CommandLog("Updated " + strings.Count + " strings (" + _origStrings.Count + " strings in total)");
  132. }
  133. private void LoadOriginalStrings()
  134. {
  135. if (_origStrings != null) return;
  136. _origStrings =
  137. (Dictionary<string, string>) AccessTools.Field(typeof(LocalizationService), "LocalizedStrings")
  138. .GetValue(null);
  139. }
  140. private void TryLoadSteamLanguageMenuEnterEvent(object sender, MenuEventArgs args)
  141. {
  142. TryLoadSteamLanguage();
  143. Client.EnterMenu -= TryLoadSteamLanguageMenuEnterEvent;
  144. }
  145. private void TryLoadSteamLanguage()
  146. {
  147. string lang = Steamworks.SteamUtils.SteamUILanguage;
  148. string first2 = lang.Substring(0, 2);
  149. // try some possibly valid language codes
  150. if (File.Exists(Path.Combine(_pluginFolder.FullName, lang + ".json")))
  151. {
  152. Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
  153. LoadTranslation(lang);
  154. }
  155. else if (File.Exists(Path.Combine(_pluginFolder.FullName, first2 + ".json")))
  156. {
  157. lang = first2;
  158. Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
  159. LoadTranslation(lang);
  160. }
  161. else if (File.Exists(Path.Combine(_pluginFolder.FullName, first2 + "-" + first2 + ".json")))
  162. {
  163. // 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)
  164. lang = first2 + "-" + first2;
  165. Logging.MetaLog($"Automatically detected Steam UI language {lang}, loading translations...");
  166. LoadTranslation(lang);
  167. }
  168. else
  169. {
  170. Logging.MetaLog($"Translations for Steam UI language {lang} are not available, skipping...");
  171. }
  172. }
  173. public override string Name { get; } = "LocalizationMod";
  174. public override string Version { get; } = "1.0.0";
  175. }
  176. }