diff --git a/v2rayN/AmazTool/LocalizationHelper.cs b/v2rayN/AmazTool/LocalizationHelper.cs index 69411faa..3804564c 100644 --- a/v2rayN/AmazTool/LocalizationHelper.cs +++ b/v2rayN/AmazTool/LocalizationHelper.cs @@ -1,71 +1,63 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; +using System.Globalization; using System.Text.Json; -using System.Threading; -public class Localization +namespace AmazTool { - // 使用 Lazy 实现单例模式,确保 Localization 实例在需要时才会创建 - private static readonly Lazy _instance = new(() => new Localization()); - private Dictionary translations; - - // 私有构造函数,防止外部实例化 - private Localization() + public class LocalizationHelper { - // 获取当前系统的完整文化名称,例如:zh-CN, en-US - string currentLanguage = CultureInfo.CurrentCulture.Name; + private static Dictionary languageResources = new(); - // 如果当前语言不是 "zh-CN" 或 "en-US",默认使用英语 - if (currentLanguage != "zh-CN" && currentLanguage != "en-US") + static LocalizationHelper() { - currentLanguage = "en-US"; + // 加载语言资源 + LoadLanguageResources(); } - // 加载相应语言的 JSON 文件 - string jsonFilePath = $"{currentLanguage}.json"; - if (!LoadTranslations(jsonFilePath)) + /// + /// 加载外部 JSON 文件中的语言资源 + /// + private static void LoadLanguageResources() { - // 如果加载失败,则使用默认语言的 JSON 文件 - jsonFilePath = "en-US.json"; - LoadTranslations(jsonFilePath); - } - } + try + { + string currentLanguage = CultureInfo.CurrentCulture.Name; + if (currentLanguage != "zh-CN" && currentLanguage != "en-US") + { + currentLanguage = "en-US"; + } - // 公有静态属性用于获取单例实例 - public static Localization Instance - { - get - { - return _instance.Value; - } - } + string jsonFilePath = $"{currentLanguage}.json"; + if (!File.Exists(jsonFilePath)) + { + jsonFilePath = "en-US.json"; + } - // 加载翻译文件,并将内容解析为字典 - private bool LoadTranslations(string jsonFilePath) - { - try - { - // 读取 JSON 文件内容 - var json = File.ReadAllText(jsonFilePath); - // 解析 JSON 内容并转换为字典 - translations = JsonSerializer.Deserialize>(json); - return true; // 成功读取并解析 JSON 文件 + var json = File.ReadAllText(jsonFilePath); + if (!string.IsNullOrEmpty(json)) + { + languageResources = JsonSerializer.Deserialize>(json) ?? new Dictionary(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Failed to load language resources: {ex.Message}"); + languageResources = []; // 初始化为空字典 + } } - catch (Exception ex) - { - // 处理读取或解析 JSON 文件时的异常 - Console.WriteLine($"Failed to load JSON file: {ex.Message}"); - Thread.Sleep(5000); - Environment.Exit(1); - return false; // 读取或解析 JSON 文件失败 - } - } - // 根据键值返回相应的翻译,如果不存在则返回键值本身 - public string Translate(string key) - { - return translations != null && translations.TryGetValue(key, out string value) ? value : key; + /// + /// 获取系统当前语言的本地化字符串 + /// + /// 要翻译的关键字 + /// 对应语言的本地化字符串,如果没有找到则返回关键字 + public static string GetLocalizedValue(string key) + { + if (languageResources != null && languageResources.TryGetValue(key, out var translation)) + { + return translation; + } + + return key; + } } } diff --git a/v2rayN/AmazTool/Program.cs b/v2rayN/AmazTool/Program.cs index 236a84ef..11e6aefc 100644 --- a/v2rayN/AmazTool/Program.cs +++ b/v2rayN/AmazTool/Program.cs @@ -1,110 +1,22 @@ -/** - * 使用JSON文件对C#应用程序进行本地化。 - * 根据系统当前的语言加载相应的语言文件。 - * 如果当前语言不被支持,则默认使用英语。 - * - * 用法: - * - 为每种支持的语言创建JSON文件(例如,en-US.json,zh-CN.json)。 - * - 将JSON文件放置程序同目录中。 - * - 运行程序,它将根据系统当前的语言加载翻译。 - * - 调用方式: localization.Translate("Try_Terminate_Process") //返回一个 string 字符串 - * 示例JSON文件(en-US.json): - * { - * "Restart_v2rayN": "Start v2rayN, please wait...", - * "Guidelines": "Please run it from the main application." - * } - * - * 示例JSON文件(zh-CN.json): - * { - * "Restart_v2rayN": "正在重启,请等待...", - * "Guidelines": "请从主应用运行!" - * } - */ - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text.Json; -using System.Threading; - -namespace AmazTool +namespace AmazTool { - public class Localization - { - private static readonly Lazy _instance = new Lazy(() => new Localization()); - private Dictionary translations; - - // 私有构造函数,防止外部实例化 - private Localization() - { - string currentLanguage = CultureInfo.CurrentCulture.Name; - - if (currentLanguage != "zh-CN" && currentLanguage != "en-US") - { - currentLanguage = "en-US"; - } - - string jsonFilePath = $"{currentLanguage}.json"; - if (!LoadTranslations(jsonFilePath)) - { - jsonFilePath = "en-US.json"; - LoadTranslations(jsonFilePath); - } - } - - // 公有静态属性用于获取单例实例 - public static Localization Instance - { - get - { - return _instance.Value; - } - } - - private bool LoadTranslations(string jsonFilePath) - { - try - { - var json = File.ReadAllText(jsonFilePath); - translations = JsonSerializer.Deserialize>(json); - return true; - } - catch (Exception ex) - { - Console.WriteLine($"Failed to load JSON file: {ex.Message}"); - Thread.Sleep(5000); - Environment.Exit(1); - return false; - } - } - - public string Translate(string key) - { - return translations != null && translations.TryGetValue(key, out string value) ? value : key; - } - } - internal static class Program { - + /// + /// 应用程序的主入口点。 + /// [STAThread] - public static void Main(string[] args) + private static void Main(string[] args) { - Localization localization = Localization.Instance; - if (args.Length == 0) { - // 不能直接打开更新程序 - Console.WriteLine(localization.Translate("Guidelines")); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Guidelines")); Thread.Sleep(5000); return; } - // 解析并拼接命令行参数以获取文件名 var fileName = Uri.UnescapeDataString(string.Join(" ", args)); - // 调用升级方法进行文件处理 UpgradeApp.Upgrade(fileName); } } -} +} \ No newline at end of file diff --git a/v2rayN/AmazTool/UpgradeApp.cs b/v2rayN/AmazTool/UpgradeApp.cs index a8db3516..98239961 100644 --- a/v2rayN/AmazTool/UpgradeApp.cs +++ b/v2rayN/AmazTool/UpgradeApp.cs @@ -1,72 +1,46 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.Diagnostics; using System.IO.Compression; using System.Text; -using System.Threading; namespace AmazTool { internal class UpgradeApp { - // 定义常量 - private static readonly string V2rayN = "v2rayN"; - private static readonly string SplitKey = "/"; - public static void Upgrade(string fileName) { - var localization = new Localization(); - - Console.WriteLine(fileName); + Console.WriteLine($"{LocalizationHelper.GetLocalizedValue("Start_Unzipping")}\n{fileName}"); + Thread.Sleep(9000); if (!File.Exists(fileName)) { - // 如果文件不存在,输出相应的本地化信息 - Console.WriteLine(localization.Translate("Upgrade_File_Not_Found")); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Upgrade_File_Not_Found")); return; } - // 尝试终止进程 - TerminateProcess(localization); - - // 解压缩更新包 - ExtractUpdatePackage(fileName, localization); - - // 重启进程 - Console.WriteLine(localization.Translate("Restart_v2rayN")); - Thread.Sleep(9000); - RestartProcess(); - } - - private static void TerminateProcess(Localization localization) - { - Console.WriteLine(localization.Translate("Try_Terminate_Process")); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Try_Terminate_Process")); try { - var processes = Process.GetProcessesByName(V2rayN); - foreach (var process in processes) + var existing = Process.GetProcessesByName(V2rayN); + foreach (var pp in existing) { - process?.Kill(); - process?.WaitForExit(1000); + pp?.Kill(); + pp?.WaitForExit(1000); } } catch (Exception ex) { - // 如果无法终止进程,输出相应的本地化信息和错误堆栈 - Console.WriteLine(localization.Translate("Failed_Terminate_Process") + ex.StackTrace); + // Access may be denied without admin right. The user may not be an administrator. + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Terminate_Process") + ex.StackTrace); } - } - - private static void ExtractUpdatePackage(string fileName, Localization localization) - { - Console.WriteLine(localization.Translate("Start_Unzipping")); - StringBuilder errorLog = new(); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Start_Unzipping")); + StringBuilder sb = new(); try { - string backupFilePath = $"{GetExePath()}.tmp"; - File.Delete(backupFilePath); + string thisAppOldFile = $"{GetExePath()}.tmp"; + File.Delete(thisAppOldFile); + string splitKey = "/"; using ZipArchive archive = ZipFile.OpenRead(fileName); foreach (ZipArchiveEntry entry in archive.Entries) @@ -74,14 +48,22 @@ namespace AmazTool try { if (entry.Length == 0) + { continue; + } Console.WriteLine(entry.FullName); - string fullPath = GetEntryFullPath(entry.FullName); - BackupExistingFile(fullPath, backupFilePath); + var lst = entry.FullName.Split(splitKey); + if (lst.Length == 1) continue; + string fullName = string.Join(splitKey, lst[1..lst.Length]); - string entryOutputPath = GetPath(fullPath); + if (string.Equals(GetExePath(), GetPath(fullName), StringComparison.OrdinalIgnoreCase)) + { + File.Move(GetExePath(), thisAppOldFile); + } + + string entryOutputPath = GetPath(fullName); Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!); entry.ExtractToFile(entryOutputPath, true); @@ -89,39 +71,23 @@ namespace AmazTool } catch (Exception ex) { - errorLog.Append(ex.StackTrace); + sb.Append(ex.StackTrace); } } } catch (Exception ex) { - // 如果解压失败,输出相应的本地化信息和错误堆栈 - Console.WriteLine(localization.Translate("Failed_Upgrade") + ex.StackTrace); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + ex.StackTrace); + //return; } - - if (errorLog.Length > 0) + if (sb.Length > 0) { - // 如果有任何错误记录,输出相应的本地化信息和错误日志 - Console.WriteLine(localization.Translate("Failed_Upgrade") + errorLog.ToString()); + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + sb.ToString()); + //return; } - } - private static void BackupExistingFile(string fullPath, string backupFilePath) - { - if (string.Equals(GetExePath(), fullPath, StringComparison.OrdinalIgnoreCase)) - { - File.Move(GetExePath(), backupFilePath); - } - } - - private static string GetEntryFullPath(string entryName) - { - var parts = entryName.Split(SplitKey); - return parts.Length > 1 ? string.Join(SplitKey, parts[1..]) : entryName; - } - - private static void RestartProcess() - { + Console.WriteLine(LocalizationHelper.GetLocalizedValue("Restart_v2rayN")); + Thread.Sleep(9000); Process process = new() { StartInfo = new() @@ -146,7 +112,14 @@ namespace AmazTool private static string GetPath(string fileName) { - return string.IsNullOrEmpty(fileName) ? StartupPath() : Path.Combine(StartupPath(), fileName); + string startupPath = StartupPath(); + if (string.IsNullOrEmpty(fileName)) + { + return startupPath; + } + return Path.Combine(startupPath, fileName); } + + private static string V2rayN => "v2rayN"; } -} +} \ No newline at end of file