| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- 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
- {
- /// <summary>
- /// 多语言翻译模板生成器 - 自动扫描插件并生成翻译模板
- /// </summary>
- public class LocalizationTemplateGenerator
- {
- /// <summary>
- /// 扫描程序集中的所有插件模型并生成翻译模板
- /// </summary>
- /// <param name="assemblies">要扫描的程序集列表</param>
- /// <param name="outputPath">输出模板文件路径</param>
- /// <param name="languageCode">目标语言代码(如 "en-US")</param>
- 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}");
- }
- /// <summary>
- /// 扫描单个程序集
- /// </summary>
- 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}");
- }
- }
- /// <summary>
- /// 扫描插件模型类型
- /// </summary>
- private static void ScanPluginModel(Type type, LanguageResourcePack pack)
- {
- var typeName = type.Name;
- var properties = new Dictionary<string, PropertyTranslation>();
- foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
- {
- // 跳过标记为 Browsable(false) 的属性
- var browsable = prop.GetCustomAttribute<BrowsableAttribute>();
- if (browsable != null && !browsable.Browsable)
- continue;
- var displayNameAttr = prop.GetCustomAttribute<DisplayNameAttribute>();
- var descriptionAttr = prop.GetCustomAttribute<DescriptionAttribute>();
- var categoryAttr = prop.GetCustomAttribute<CategoryAttribute>();
- 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;
- }
- }
- /// <summary>
- /// 扫描插件类
- /// </summary>
- 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"
- };
- }
- }
- }
- /// <summary>
- /// 扫描枚举类型
- /// </summary>
- private static void ScanEnum(Type type, LanguageResourcePack pack)
- {
- var enumValues = new Dictionary<string, string>();
- foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
- {
- var displayNameAttr = field.GetCustomAttribute<DisplayNameAttribute>();
- var displayName = displayNameAttr?.DisplayName ?? field.Name;
- enumValues[field.Name] = $"[TODO: {displayName}]";
- }
- if (enumValues.Count > 0)
- {
- pack.Enums[type.Name] = enumValues;
- }
- }
- /// <summary>
- /// 判断是否为插件模型类型
- /// </summary>
- 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;
- }
- /// <summary>
- /// 判断是否为插件类
- /// </summary>
- private static bool IsPlugin(Type type)
- {
- return type.GetCustomAttributes(false)
- .Any(a => a.GetType().Name == "PluginAttribute");
- }
- /// <summary>
- /// 获取语言显示名称
- /// </summary>
- 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
- };
- }
- /// <summary>
- /// 批量生成多个语言的模板
- /// </summary>
- 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);
- }
- }
- /// <summary>
- /// 使用示例
- /// </summary>
- 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: ...] 标记替换为实际翻译。");
- }
- }
- }
|