using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; using System.Text.Json; using TeamAAS.Localization; namespace TeamAAS.Tools { /// /// 多语言翻译模板生成器 - 自动扫描插件并生成翻译模板 /// public class LocalizationTemplateGenerator { /// /// 扫描程序集中的所有插件模型并生成翻译模板 /// /// 要扫描的程序集列表 /// 输出模板文件路径 /// 目标语言代码(如 "en-US") public static void GenerateTemplate(Assembly[] assemblies, string outputPath, string languageCode = "en-US") { var pack = new LanguageResourcePack { LanguageCode = languageCode, LanguageName = GetLanguageName(languageCode), Version = "1.0.0", Author = "Auto Generated" }; // 扫描所有插件模型 foreach (var assembly in assemblies) { ScanAssembly(assembly, pack); } // 序列化为 JSON var options = new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; var json = JsonSerializer.Serialize(pack, options); File.WriteAllText(outputPath, json); Console.WriteLine($"翻译模板已生成: {outputPath}"); Console.WriteLine($" - 类型数: {pack.Properties.Count}"); Console.WriteLine($" - 属性数: {pack.Properties.Sum(p => p.Value.Count)}"); Console.WriteLine($" - 插件数: {pack.Plugins.Count}"); } /// /// 扫描单个程序集 /// private static void ScanAssembly(Assembly assembly, LanguageResourcePack pack) { try { var types = assembly.GetTypes(); foreach (var type in types) { // 扫描插件模型(继承自 BasePluginModel) if (IsPluginModel(type)) { ScanPluginModel(type, pack); } // 扫描插件类(带 PluginAttribute) if (IsPlugin(type)) { ScanPlugin(type, pack); } // 扫描枚举类型 if (type.IsEnum) { ScanEnum(type, pack); } } } catch (Exception ex) { Console.WriteLine($"警告: 扫描程序集 {assembly.FullName} 时出错: {ex.Message}"); } } /// /// 扫描插件模型类型 /// private static void ScanPluginModel(Type type, LanguageResourcePack pack) { var typeName = type.Name; var properties = new Dictionary(); foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { // 跳过标记为 Browsable(false) 的属性 var browsable = prop.GetCustomAttribute(); if (browsable != null && !browsable.Browsable) continue; var displayNameAttr = prop.GetCustomAttribute(); var descriptionAttr = prop.GetCustomAttribute(); var categoryAttr = prop.GetCustomAttribute(); properties[prop.Name] = new PropertyTranslation { DisplayName = displayNameAttr?.DisplayName ?? $"[TODO: {prop.Name}]", Description = descriptionAttr?.Description ?? $"[TODO: Description for {prop.Name}]", Category = categoryAttr?.Category ?? "Miscellaneous" }; } if (properties.Count > 0) { pack.Properties[typeName] = properties; } } /// /// 扫描插件类 /// private static void ScanPlugin(Type type, LanguageResourcePack pack) { var pluginAttr = type.GetCustomAttributes(false) .FirstOrDefault(a => a.GetType().Name == "PluginAttribute"); if (pluginAttr != null) { var displayNameProp = pluginAttr.GetType().GetProperty("DisplayName"); var descriptionProp = pluginAttr.GetType().GetProperty("Description"); var categoryProp = pluginAttr.GetType().GetProperty("Category"); var displayName = displayNameProp?.GetValue(pluginAttr)?.ToString(); var description = descriptionProp?.GetValue(pluginAttr)?.ToString(); var category = categoryProp?.GetValue(pluginAttr)?.ToString(); if (!string.IsNullOrWhiteSpace(displayName)) { pack.Plugins[type.Name] = new PluginTranslation { DisplayName = displayName, Description = description ?? $"[TODO: Description for {type.Name}]", Category = category?.ToString() ?? "Others" }; } } } /// /// 扫描枚举类型 /// private static void ScanEnum(Type type, LanguageResourcePack pack) { var enumValues = new Dictionary(); foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { var displayNameAttr = field.GetCustomAttribute(); var displayName = displayNameAttr?.DisplayName ?? field.Name; enumValues[field.Name] = $"[TODO: {displayName}]"; } if (enumValues.Count > 0) { pack.Enums[type.Name] = enumValues; } } /// /// 判断是否为插件模型类型 /// private static bool IsPluginModel(Type type) { if (type.IsAbstract || type.IsInterface) return false; var baseType = type.BaseType; while (baseType != null) { if (baseType.Name == "BasePluginModel") return true; baseType = baseType.BaseType; } return false; } /// /// 判断是否为插件类 /// private static bool IsPlugin(Type type) { return type.GetCustomAttributes(false) .Any(a => a.GetType().Name == "PluginAttribute"); } /// /// 获取语言显示名称 /// private static string GetLanguageName(string languageCode) { return languageCode switch { "zh-CN" => "简体中文", "zh-TW" => "繁体中文", "en-US" => "English", "en-GB" => "English (UK)", "ja-JP" => "日本語", "ko-KR" => "한국어", "de-DE" => "Deutsch", "fr-FR" => "Français", "es-ES" => "Español", "ru-RU" => "Русский", "it-IT" => "Italiano", "pt-BR" => "Português (Brasil)", "ar-SA" => "العربية", "th-TH" => "ไทย", "vi-VN" => "Tiếng Việt", _ => languageCode }; } /// /// 批量生成多个语言的模板 /// public static void GenerateMultipleTemplates(Assembly[] assemblies, string outputDirectory, params string[] languageCodes) { if (!Directory.Exists(outputDirectory)) Directory.CreateDirectory(outputDirectory); foreach (var langCode in languageCodes) { var outputPath = Path.Combine(outputDirectory, $"{langCode}.json"); GenerateTemplate(assemblies, outputPath, langCode); } } /// /// 使用示例 /// public static void Example() { // 示例 1: 生成单个语言模板 var assemblies = new[] { Assembly.Load("TeamAAS.Plugins.Standard"), Assembly.Load("TeamAAS.Plugins.Vpp"), Assembly.Load("TeamAAS.Plugins.Feeder") }; GenerateTemplate( assemblies, @"D:\Program\TeamAAS\Localization\template-en-US.json", "en-US" ); // 示例 2: 批量生成多个语言模板 GenerateMultipleTemplates( assemblies, @"D:\Program\TeamAAS\Localization\templates", "en-US", "ja-JP", "ko-KR", "de-DE", "fr-FR" ); Console.WriteLine("模板生成完成!"); Console.WriteLine("请编辑生成的模板文件,将 [TODO: ...] 标记替换为实际翻译。"); } } }