Decompiled source of Autolocalization v1.5.4

Autolocalization.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Autolocalization.Localization;
using Autolocalization.Services;
using Autolocalization.Utils;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Autolocalization")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.5.3.0")]
[assembly: AssemblyInformationalVersion("1.5.3+bb6808fdaad04e590f02d08a83c95397ff7c8f12")]
[assembly: AssemblyProduct("Autolocalization")]
[assembly: AssemblyTitle("Autolocalization")]
[assembly: AssemblyVersion("1.5.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Autolocalization
{
	[BepInPlugin(".com.HsgtLgt.autolocalization", "智能本地化引擎", "1.5.3")]
	public class Autolocalization : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ConfigDescription))]
		public static class ConfigDescriptionPatch
		{
			private static readonly ConcurrentDictionary<string, string> _descriptionCache = new ConcurrentDictionary<string, string>();

			private static readonly ConcurrentDictionary<string, bool> _processedKeys = new ConcurrentDictionary<string, bool>();

			private static readonly object _exportLock = new object();

			private static readonly List<string> _exportBuffer = new List<string>(1000);

			private static long _processedCount = 0L;

			private static long _cacheHits = 0L;

			public static long _translatedCount = 0L;

			public static long _unchangedCount = 0L;

			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPrefix]
			public static void Prefix(ref string description)
			{
				if (string.IsNullOrWhiteSpace(description))
				{
					return;
				}
				if (_descriptionCache.TryGetValue(description, out string value))
				{
					Interlocked.Increment(ref _cacheHits);
					description = value;
					PerformanceMonitor.RecordProcessing(0L, 1L);
					return;
				}
				string text = ProcessDescription(description);
				if (text != description)
				{
					Interlocked.Increment(ref _translatedCount);
				}
				else
				{
					Interlocked.Increment(ref _unchangedCount);
				}
				if (_descriptionCache.Count < 50000)
				{
					_descriptionCache.TryAdd(description, text);
				}
				description = text;
				Interlocked.Increment(ref _processedCount);
				PerformanceMonitor.RecordProcessing(1L, 0L);
				AddToExportBuffer(description);
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			private static string ProcessDescription(string original)
			{
				string text = _smartLocalizationManager?.GetTranslation(original);
				if (!string.IsNullOrEmpty(text) && text != original && text != null)
				{
					return text;
				}
				return original;
			}

			private static void AddToExportBuffer(string description)
			{
				lock (_exportLock)
				{
					_exportBuffer.Add(description);
					if (_exportBuffer.Count >= 1000)
					{
						ExportBatch();
					}
				}
			}

			private static void ExportBatch()
			{
				if (_exportBuffer.Count != 0)
				{
					string[] array = _exportBuffer.ToArray();
					_exportBuffer.Clear();
					ManualLogSource? slog = Slog;
					if (slog != null)
					{
						slog.LogInfo((object)$"批量导出 {array.Length} 条描述数据");
					}
				}
			}

			public static void FlushExportBuffer()
			{
				lock (_exportLock)
				{
					ExportBatch();
				}
			}
		}

		[HarmonyPatch(typeof(ConfigDefinition))]
		public static class ConfigDefinitionPatch
		{
			private static readonly ConcurrentDictionary<string, string> _keyCache = new ConcurrentDictionary<string, string>();

			private static readonly ConcurrentDictionary<string, string> _sectionCache = new ConcurrentDictionary<string, string>();

			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPrefix]
			public static void Prefix(ref string section, ref string key)
			{
				if (!string.IsNullOrWhiteSpace(section))
				{
					if (_sectionCache.TryGetValue(section, out string value))
					{
						section = value;
					}
					else
					{
						string text = ProcessSection(section);
						if (_sectionCache.Count < 10000)
						{
							_sectionCache.TryAdd(section, text);
						}
						section = text;
					}
				}
				if (string.IsNullOrWhiteSpace(key))
				{
					return;
				}
				if (_keyCache.TryGetValue(key, out string value2))
				{
					key = value2;
					return;
				}
				string text2 = ProcessKey(key);
				if (_keyCache.Count < 10000)
				{
					_keyCache.TryAdd(key, text2);
				}
				key = text2;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			private static string ProcessSection(string original)
			{
				string text = _smartLocalizationManager?.GetTranslation(original);
				if (!string.IsNullOrEmpty(text) && text != original && text != null)
				{
					return text;
				}
				return original;
			}

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			private static string ProcessKey(string original)
			{
				string text = _smartLocalizationManager?.GetTranslation(original);
				if (!string.IsNullOrEmpty(text) && text != original && text != null)
				{
					return text;
				}
				return original;
			}
		}

		public const string PluginGuid = ".com.HsgtLgt.autolocalization";

		public const string PluginName = "智能本地化引擎";

		public const string PluginVersion = "1.5.3";

		private static readonly Harmony Harmony = new Harmony(".com.HsgtLgt.autolocalization");

		public static ManualLogSource? Slog;

		private static SmartLocalizationManager? _smartLocalizationManager;

		private static LocalizationFileManager? _fileManager;

		public static Autolocalization? Instance { get; private set; }

		public static string LogLevel { get; private set; } = "Basic";


		private void Awake()
		{
			Slog = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			LoadConfigurations();
			PerformanceMonitor.SetLogSource(Slog);
			PerformanceMonitor.StartMonitoring();
			PerformanceMonitor.StartPeriodicReporting(30, LogLevel);
			InitializeTranslationServicesSync();
			Slog.LogDebug((object)FormatLog("INFO", "Main", "版本1.5.3启动成功"));
			Harmony.PatchAll();
			Task.Delay(5000).ContinueWith(delegate
			{
				if (ConfigDescriptionPatch._translatedCount > 0 || ConfigDescriptionPatch._unchangedCount > 0)
				{
					ManualLogSource? slog = Slog;
					if (slog != null)
					{
						slog.LogInfo((object)FormatLog("INFO", "Config", $"已处理配置: {ConfigDescriptionPatch._translatedCount}项已翻译, {ConfigDescriptionPatch._unchangedCount}项未变化"));
					}
				}
			});
		}

		private void LoadConfigurations()
		{
			LogLevel = ((BaseUnityPlugin)this).Config.Bind<string>("General", "LogLevel", "None", "日志详细程度。可选: None(仅错误)/Basic(基本进度)/Detailed(详细统计)/Debug(调试信息)").Value;
		}

		private void InitializeTranslationServicesSync()
		{
			try
			{
				_fileManager = new LocalizationFileManager();
				_smartLocalizationManager = new SmartLocalizationManager(_fileManager);
				_smartLocalizationManager.SetLogSource(Slog);
				Slog.LogDebug((object)"智能本地化管理器初始化完成");
				Task<bool> task = _smartLocalizationManager.InitializeAsync();
				task.Wait();
				if (task.Result)
				{
					Slog.LogDebug((object)"✅ 智能本地化系统同步初始化成功");
					Slog.LogDebug((object)$"当前阶段: {_smartLocalizationManager.CurrentPhase}");
				}
				else
				{
					Slog.LogError((object)"❌ 智能本地化系统同步初始化失败");
				}
				Slog.LogDebug((object)"翻译服务同步初始化完成");
			}
			catch (Exception ex)
			{
				Slog.LogError((object)("同步初始化翻译服务失败: " + ex.Message));
			}
		}

		public static string FormatLog(string level, string module, string message)
		{
			return LogFormatter.FormatLog(level, module, message);
		}

		public void OnDestroy()
		{
			_smartLocalizationManager?.Dispose();
			PerformanceMonitor.StopMonitoring();
		}
	}
	public static class PerformanceMonitor
	{
		private static readonly Stopwatch _stopwatch = new Stopwatch();

		private static long _totalProcessed = 0L;

		private static long _totalCacheHits = 0L;

		private static readonly object _lock = new object();

		private static ManualLogSource? _logSource;

		public static void SetLogSource(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		public static void StartMonitoring()
		{
			_stopwatch.Start();
		}

		public static void StopMonitoring()
		{
			_stopwatch.Stop();
		}

		public static void RecordProcessing(long processed, long cacheHits)
		{
			lock (_lock)
			{
				_totalProcessed += processed;
				_totalCacheHits += cacheHits;
			}
		}

		public static PerformanceStats GetCurrentStats()
		{
			lock (_lock)
			{
				long elapsedMilliseconds = _stopwatch.ElapsedMilliseconds;
				long totalProcessed = _totalProcessed;
				long totalCacheHits = _totalCacheHits;
				double cacheHitRate = ((totalProcessed > 0) ? ((double)totalCacheHits / (double)totalProcessed * 100.0) : 0.0);
				double processingRate = ((elapsedMilliseconds > 0) ? ((double)totalProcessed / (double)elapsedMilliseconds * 1000.0) : 0.0);
				PerformanceStats result = default(PerformanceStats);
				result.TotalProcessed = totalProcessed;
				result.TotalCacheHits = totalCacheHits;
				result.CacheHitRate = cacheHitRate;
				result.ProcessingRate = processingRate;
				result.ElapsedMilliseconds = elapsedMilliseconds;
				result.MemoryUsage = GC.GetTotalMemory(forceFullCollection: false);
				return result;
			}
		}

		private static void LogPerformanceReport()
		{
			PerformanceStats currentStats = GetCurrentStats();
			ManualLogSource? logSource = _logSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)"=== 性能监控报告 ===");
			}
			ManualLogSource? logSource2 = _logSource;
			if (logSource2 != null)
			{
				logSource2.LogInfo((object)$"总处理数量: {currentStats.TotalProcessed:N0}");
			}
			ManualLogSource? logSource3 = _logSource;
			if (logSource3 != null)
			{
				logSource3.LogInfo((object)$"缓存命中数: {currentStats.TotalCacheHits:N0}");
			}
			ManualLogSource? logSource4 = _logSource;
			if (logSource4 != null)
			{
				logSource4.LogInfo((object)$"缓存命中率: {currentStats.CacheHitRate:F2}%");
			}
			ManualLogSource? logSource5 = _logSource;
			if (logSource5 != null)
			{
				logSource5.LogInfo((object)$"处理速率: {currentStats.ProcessingRate:F0} 条/秒");
			}
			ManualLogSource? logSource6 = _logSource;
			if (logSource6 != null)
			{
				logSource6.LogInfo((object)$"总耗时: {currentStats.ElapsedMilliseconds:N0} 毫秒");
			}
			ManualLogSource? logSource7 = _logSource;
			if (logSource7 != null)
			{
				logSource7.LogInfo((object)$"内存使用: {currentStats.MemoryUsage / 1024 / 1024:F2} MB");
			}
			ManualLogSource? logSource8 = _logSource;
			if (logSource8 != null)
			{
				logSource8.LogInfo((object)"==================");
			}
		}

		public static void StartPeriodicReporting(int intervalSeconds = 30, string logLevel = "Basic")
		{
			if (intervalSeconds > 0 && !(logLevel == "None"))
			{
				Timer timer = new Timer(ReportPeriodicStats, logLevel, TimeSpan.FromSeconds(intervalSeconds), TimeSpan.FromSeconds(intervalSeconds));
			}
		}

		private static void ReportPeriodicStats(object state)
		{
			string text = (state as string) ?? "Basic";
			PerformanceStats currentStats = GetCurrentStats();
			if (currentStats.TotalProcessed <= 0 || !(text != "None"))
			{
				return;
			}
			if (text == "Debug" || text == "Detailed")
			{
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)$"[拦截统计] 配置拦截: {currentStats.TotalProcessed:N0}次, 拦截速率: {currentStats.ProcessingRate:F0}次/秒, 拦截缓存命中: {currentStats.CacheHitRate:F2}%");
				}
			}
			else
			{
				_ = text == "Basic";
			}
		}
	}
	public struct PerformanceStats
	{
		public long TotalProcessed { get; set; }

		public long TotalCacheHits { get; set; }

		public double CacheHitRate { get; set; }

		public double ProcessingRate { get; set; }

		public long ElapsedMilliseconds { get; set; }

		public long MemoryUsage { get; set; }
	}
}
namespace Autolocalization.Utils
{
	public static class LogFormatter
	{
		public static string FormatLog(string level, string module, string message)
		{
			string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
			string text2 = level switch
			{
				"ERROR" => "\ud83d\udd34", 
				"WARN" => "\ud83d\udfe1", 
				"INFO" => "\ud83d\udd35", 
				"DEBUG" => "⚪", 
				_ => "⚪", 
			};
			return $"{text2} [{text}] [{level,-5}] [{module,-20}] {message}";
		}

		public static string FormatSection(string title)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("\ud83d\udccb " + new string('═', 60));
			stringBuilder.AppendLine("   " + title);
			stringBuilder.AppendLine("   " + new string('═', 60));
			return stringBuilder.ToString();
		}

		public static string FormatConfigTable(string title, params (string key, string value)[] configs)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("⚙\ufe0f  " + title);
			stringBuilder.AppendLine("   " + new string('─', 50));
			for (int i = 0; i < configs.Length; i++)
			{
				var (arg, arg2) = configs[i];
				stringBuilder.AppendLine($"   {arg,-25}: {arg2}");
			}
			stringBuilder.AppendLine("   " + new string('─', 50));
			return stringBuilder.ToString();
		}

		public static string FormatProgressBar(int current, int total, string description = "")
		{
			double num = ((total > 0) ? ((double)current / (double)total) : 0.0);
			int num2 = (int)(30.0 * num);
			int count = 30 - num2;
			string text = "[" + new string('█', num2) + new string('░', count) + "]";
			string text2 = $"{num * 100.0:F1}%";
			return $"\ud83d\udcca {description} {text} {current}/{total} ({text2})";
		}

		public static string FormatPerformanceStats(string operation, TimeSpan elapsed, int itemsProcessed)
		{
			double num = ((itemsProcessed > 0) ? ((double)itemsProcessed / elapsed.TotalSeconds) : 0.0);
			double num2 = ((itemsProcessed > 0) ? (elapsed.TotalMilliseconds / (double)itemsProcessed) : 0.0);
			return $"⚡ {operation} - 耗时: {elapsed.TotalSeconds:F1}s, 处理: {itemsProcessed}项, " + $"吞吐量: {num:F1}项/s, 平均: {num2:F1}ms/项";
		}

		public static string FormatErrorDetails(string context, Exception ex)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("❌ " + context);
			stringBuilder.AppendLine("   错误类型: " + ex.GetType().Name);
			stringBuilder.AppendLine("   错误消息: " + ex.Message);
			if (!string.IsNullOrEmpty(ex.StackTrace))
			{
				stringBuilder.AppendLine("   堆栈跟踪:");
				string[] array = ex.StackTrace.Split(new char[1] { '\n' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!string.IsNullOrWhiteSpace(text))
					{
						stringBuilder.AppendLine("     " + text.Trim());
					}
				}
			}
			return stringBuilder.ToString();
		}

		public static string FormatBatchSummary(string operation, int total, int success, int failed, int cached = 0)
		{
			double num = ((total > 0) ? ((double)success / (double)total * 100.0) : 0.0);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("\ud83d\udcc8 " + operation + " 摘要");
			stringBuilder.AppendLine($"   总计: {total} 项");
			stringBuilder.AppendLine($"   成功: {success} 项 ({num:F1}%)");
			if (failed > 0)
			{
				stringBuilder.AppendLine($"   失败: {failed} 项");
			}
			if (cached > 0)
			{
				stringBuilder.AppendLine($"   缓存: {cached} 项");
			}
			return stringBuilder.ToString();
		}
	}
}
namespace Autolocalization.Services
{
	public static class PathManager
	{
		public static string GetPluginDirectory()
		{
			string location = typeof(PathManager).Assembly.Location;
			return Path.GetDirectoryName(location) ?? "";
		}

		public static string GetProjectDirectory()
		{
			return Path.Combine(Paths.ConfigPath, "Autolocalization");
		}

		public static string GetTranslationsFilePath()
		{
			return Path.Combine(GetProjectDirectory(), "translations.yaml");
		}

		public static string GetCollectedItemsFilePath()
		{
			return Path.Combine(GetProjectDirectory(), "collected_items.yaml");
		}

		public static void EnsureDirectoryExists(string directoryPath)
		{
			if (!Directory.Exists(directoryPath))
			{
				Directory.CreateDirectory(directoryPath);
			}
		}
	}
	public class SmartLocalizationManager : IDisposable
	{
		private readonly LocalizationFileManager _fileManager = fileManager ?? throw new ArgumentNullException("fileManager");

		private readonly string _translationFilePath = PathManager.GetTranslationsFilePath();

		private readonly string _collectionFilePath = PathManager.GetCollectedItemsFilePath();

		private readonly string? _configFilePath;

		private readonly string? _cacheFilePath;

		private readonly ConcurrentDictionary<string, string> _translations = new ConcurrentDictionary<string, string>();

		private readonly ConcurrentDictionary<string, string> _collectedItems = new ConcurrentDictionary<string, string>();

		private readonly ConcurrentDictionary<string, DateTime> _translationTimestamps = new ConcurrentDictionary<string, DateTime>();

		private readonly object _stateLock = new object();

		private LocalizationPhase _currentPhase;

		private bool _isInitialized;

		private bool _isDisposed;

		private readonly object _saveLock = new object();

		private bool _isSaving;

		private bool _needsSave;

		private int _totalCollected;

		private int _totalTranslated;

		private int _totalApplied;

		private int _cacheHits;

		private int _cacheMisses;

		private long _lastSavedCount;

		private long _translationQueryCount;

		private long _translationCacheHits;

		private long _translationNewCount;

		private DateTime _lastCollectTime = DateTime.MinValue;

		private Timer? _collectionEndCheckTimer;

		private bool _collectionEnded;

		private int _unsavedCount;

		private readonly ConcurrentDictionary<string, string> _reverseTranslations = new ConcurrentDictionary<string, string>();

		private ManualLogSource? _logSource;

		public LocalizationPhase CurrentPhase => _currentPhase;

		public bool IsInitialized => _isInitialized;

		public LocalizationStatistics Statistics => GetStatistics();

		public event Action<LocalizationPhase, LocalizationPhase>? OnPhaseChanged;

		public event Action<string, string>? OnTranslationAdded;

		public event Action<string, string, string>? OnTranslationUpdated;

		public event Action<LocalizationStatistics>? OnStatisticsUpdated;

		public SmartLocalizationManager(LocalizationFileManager fileManager)
		{
		}

		public void SetLogSource(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		public async Task<bool> InitializeAsync()
		{
			if (_isInitialized)
			{
				return true;
			}
			try
			{
				string projectDirectory = PathManager.GetProjectDirectory();
				PathManager.EnsureDirectoryExists(projectDirectory);
				if (File.Exists(_translationFilePath))
				{
					try
					{
						await LoadTranslationsAsync();
					}
					catch (Exception ex)
					{
						ManualLogSource? logSource = _logSource;
						if (logSource != null)
						{
							logSource.LogError((object)("❌ 从新位置加载翻译文件失败: " + ex.Message));
						}
					}
				}
				Dictionary<string, string> dictionary = null;
				if (File.Exists(_collectionFilePath))
				{
					try
					{
						dictionary = _fileManager.LoadFromYaml(_collectionFilePath);
					}
					catch (Exception ex2)
					{
						ManualLogSource? logSource2 = _logSource;
						if (logSource2 != null)
						{
							logSource2.LogError((object)("加载收集文件失败: " + ex2.Message));
						}
					}
				}
				if (dictionary != null && dictionary.Count > 0 && !File.Exists(_translationFilePath))
				{
					ManualLogSource? logSource3 = _logSource;
					if (logSource3 != null)
					{
						logSource3.LogInfo((object)"\ud83d\udcdd 发现收集文件但缺少翻译文件,创建空模板...");
					}
					Dictionary<string, string> translations = new Dictionary<string, string>();
					_fileManager.SaveToYaml(translations, _translationFilePath);
					ManualLogSource? logSource4 = _logSource;
					if (logSource4 != null)
					{
						logSource4.LogInfo((object)("✅ 已创建空的翻译文件: " + _translationFilePath));
					}
					ManualLogSource? logSource5 = _logSource;
					if (logSource5 != null)
					{
						logSource5.LogInfo((object)$"\ud83d\udca1 提示: 请参考 collected_items.yaml ({dictionary.Count} 项) 进行翻译");
					}
					ManualLogSource? logSource6 = _logSource;
					if (logSource6 != null)
					{
						logSource6.LogInfo((object)"\ud83d\udca1 将翻译添加到 translations.yaml 格式: 原文: 翻译");
					}
				}
				bool flag = false;
				if (dictionary != null && dictionary.Count > 0)
				{
					int num = dictionary.Keys.Count((string key) => !_translations.ContainsKey(key) || string.IsNullOrWhiteSpace(_translations[key]));
					if (num > 0)
					{
						flag = true;
						LogInfo($"\ud83d\udcdd 发现收集文件中有 {num} 项未翻译内容,保持在收集阶段");
					}
					else
					{
						LogInfo($"✅ 收集文件中的所有 {dictionary.Count} 项都已翻译");
					}
				}
				if (_translations.Count == 0)
				{
					ChangePhase(LocalizationPhase.Collection);
					LogInfo("未找到翻译数据,进入收集阶段");
				}
				else if (flag)
				{
					ChangePhase(LocalizationPhase.Collection);
					LogInfo("有未翻译的收集项,保持在收集阶段");
				}
				else
				{
					ChangePhase(LocalizationPhase.Application);
					LogInfo("✅ 所有翻译数据完整,进入应用阶段");
				}
				await CleanupCollectedItemsAsync(dictionary);
				await LoadCacheAsync();
				_collectionEndCheckTimer = new Timer(CheckCollectionEnd, null, 5000, 5000);
				_isInitialized = true;
				return true;
			}
			catch (Exception ex3)
			{
				ManualLogSource? logSource7 = _logSource;
				if (logSource7 != null)
				{
					logSource7.LogError((object)("❌ 初始化失败: " + ex3.Message));
				}
				return false;
			}
		}

		public string GetTranslation(string originalText, bool autoCollect = true)
		{
			if (string.IsNullOrWhiteSpace(originalText))
			{
				return originalText;
			}
			Interlocked.Increment(ref _translationQueryCount);
			if (_translations.TryGetValue(originalText, out string value))
			{
				Interlocked.Increment(ref _cacheHits);
				Interlocked.Increment(ref _translationCacheHits);
				return value;
			}
			if (_reverseTranslations.ContainsKey(originalText))
			{
				Interlocked.Increment(ref _cacheHits);
				Interlocked.Increment(ref _translationCacheHits);
				return originalText;
			}
			Interlocked.Increment(ref _cacheMisses);
			if (autoCollect)
			{
				CollectText(originalText);
				Interlocked.Increment(ref _translationNewCount);
			}
			return originalText;
		}

		public void StartCollectionPhase()
		{
			lock (_stateLock)
			{
				ChangePhase(LocalizationPhase.Collection);
			}
			LogInfo("\ud83d\udccb 开始收集阶段 - 将收集所有需要翻译的内容");
		}

		public async Task EndCollectionPhaseAsync()
		{
			lock (_stateLock)
			{
				ChangePhase(LocalizationPhase.Application);
			}
			LogInfo($"\ud83d\udccb 收集阶段结束 - 共收集 {_totalCollected} 项内容");
			await SaveCollectedItemsAsync();
			LogInfo("✅ 收集阶段完成");
		}

		public async Task<bool> StartApplicationPhaseAsync()
		{
			try
			{
				if (File.Exists(_translationFilePath))
				{
					await LoadTranslationsAsync();
					ChangePhase(LocalizationPhase.Application);
					LogInfo($"✅ 应用阶段开始 - 已加载 {_totalTranslated} 条翻译");
					return true;
				}
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)"⚠\ufe0f 未找到翻译文件,将进入收集阶段");
				}
				StartCollectionPhase();
				return false;
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource2 = _logSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("❌ 加载翻译文件失败: " + ex.Message));
				}
				StartCollectionPhase();
				return false;
			}
		}

		public void UpdateTranslation(string key, string newTranslation)
		{
			if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(newTranslation))
			{
				string orAdd = _translations.GetOrAdd(key, newTranslation);
				_translations[key] = newTranslation;
				_translationTimestamps[key] = DateTime.Now;
				_reverseTranslations[newTranslation] = key;
				this.OnTranslationUpdated?.Invoke(key, orAdd, newTranslation);
				LogInfo("\ud83d\udd04 更新翻译: " + key + " -> " + newTranslation, "Debug");
			}
		}

		public int CleanupTranslatedItems()
		{
			List<string> list = _collectedItems.Keys.Where((string key) => _translations.ContainsKey(key)).ToList();
			foreach (string item in list)
			{
				_collectedItems.TryRemove(item, out string _);
			}
			if (list.Count > 0)
			{
				LogInfo($"\ud83e\uddf9 清理了 {list.Count} 个已翻译的收集项", "Detailed");
			}
			return list.Count;
		}

		public Task<bool> ReloadTranslationsAsync()
		{
			try
			{
				LoadTranslationsAsync().Wait();
				LogInfo("\ud83d\udd04 翻译文件重新加载完成");
				return Task.FromResult(result: true);
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogError((object)("❌ 重新加载翻译文件失败: " + ex.Message));
				}
				return Task.FromResult(result: false);
			}
		}

		public Task ExportMissingTranslationsAsync()
		{
			Dictionary<string, string> dictionary = _collectedItems.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> kvp) => !_translations.ContainsKey(kvp.Key)).ToDictionary((KeyValuePair<string, string> kvp) => kvp.Key, (KeyValuePair<string, string> kvp) => kvp.Value);
			if (dictionary.Count > 0)
			{
				string text = Path.Combine(PathManager.GetProjectDirectory(), "missing_translations.yaml");
				_fileManager.SaveToYaml(dictionary, text);
				LogInfo($"\ud83d\udce4 已导出 {dictionary.Count} 条缺失翻译到: {text}", "Detailed");
			}
			return Task.CompletedTask;
		}

		public void ClearCache()
		{
			_translations.Clear();
			_translationTimestamps.Clear();
			_cacheHits = 0;
			_cacheMisses = 0;
			LogInfo("\ud83e\uddf9 翻译缓存已清理", "Debug");
		}

		public Dictionary<string, string> GetCollectedItems()
		{
			return _collectedItems.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> kvp) => kvp.Key, (KeyValuePair<string, string> kvp) => kvp.Value);
		}

		public Dictionary<string, string> GetCurrentTranslations()
		{
			return _translations.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> kvp) => kvp.Key, (KeyValuePair<string, string> kvp) => kvp.Value);
		}

		public void UpdateTranslations(Dictionary<string, string> translations)
		{
			LogInfo($"\ud83d\udd04 批量更新翻译: {translations.Count} 条", "Debug");
			foreach (KeyValuePair<string, string> translation in translations)
			{
				UpdateTranslation(translation.Key, translation.Value);
			}
			LogInfo($"✅ 翻译更新完成,当前缓存中共有 {_translations.Count} 条翻译", "Debug");
		}

		private void LogInfo(string message, string requiredLevel = "Basic")
		{
			if (_logSource != null)
			{
				string text = LogFormatter.FormatLog("INFO", "SmartLocalization", message);
				switch (requiredLevel)
				{
				case "Basic":
					_logSource.LogInfo((object)text);
					break;
				case "Detailed":
					_logSource.LogInfo((object)text);
					break;
				case "Debug":
					_logSource.LogInfo((object)text);
					break;
				}
			}
		}

		private void CheckCollectionEnd(object? state)
		{
			try
			{
				if (_collectionEnded || _collectedItems.Count == 0 || _lastCollectTime == DateTime.MinValue)
				{
					return;
				}
				double totalSeconds = (DateTime.Now - _lastCollectTime).TotalSeconds;
				if (totalSeconds >= 10.0 && _unsavedCount > 0)
				{
					_collectionEnded = true;
					LogInfo($"✅ 检测到收集阶段结束({totalSeconds:F1}秒无新增),准备保存...");
					Task task = SaveCollectedItemsAsync();
					task.Wait();
					LogInfo($"\ud83d\udcbe 收集结束自动保存完成: {_collectedItems.Count} 项");
					LogInfo($"\ud83d\udcca 收集统计: 总检测 {_totalCollected} 项, 需要翻译 {_collectedItems.Count} 项");
					if (!File.Exists(_translationFilePath))
					{
						Task task2 = GenerateTranslationTemplateAsync();
						task2.Wait();
					}
					_collectionEndCheckTimer?.Dispose();
					_collectionEndCheckTimer = null;
					LogTranslationCacheStats();
					if (_collectedItems.Count > 0)
					{
						ChangePhase(LocalizationPhase.Application);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogError((object)("❌ 检查收集结束时出错: " + ex.Message));
				}
			}
		}

		private void CollectText(string text)
		{
			if (_collectedItems.TryAdd(text, text))
			{
				Interlocked.Increment(ref _totalCollected);
				Interlocked.Increment(ref _unsavedCount);
				this.OnTranslationAdded?.Invoke(text, text);
				_lastCollectTime = DateTime.Now;
				if (_totalCollected % 100 == 0)
				{
					LogInfo($"\ud83d\udcdd 已收集 {_totalCollected} 项待翻译内容", "Detailed");
				}
			}
		}

		private void ChangePhase(LocalizationPhase newPhase)
		{
			LocalizationPhase currentPhase = _currentPhase;
			_currentPhase = newPhase;
			this.OnPhaseChanged?.Invoke(currentPhase, newPhase);
		}

		private Task LoadTranslationsAsync()
		{
			try
			{
				Dictionary<string, string> dictionary = _fileManager.LoadFromYaml(_translationFilePath);
				_translations.Clear();
				_reverseTranslations.Clear();
				int num = 0;
				int num2 = 0;
				foreach (KeyValuePair<string, string> item in dictionary)
				{
					_translations[item.Key] = item.Value;
					_translationTimestamps[item.Key] = DateTime.Now;
					if (!string.IsNullOrWhiteSpace(item.Value))
					{
						_reverseTranslations[item.Value] = item.Key;
						num++;
					}
					else
					{
						num2++;
					}
				}
				_totalTranslated = dictionary.Count;
				_totalApplied = num;
				LogInfo("\ud83d\udce5 已加载翻译文件: " + _translationFilePath);
				LogInfo($"   \ud83d\udcca 总条目: {dictionary.Count}, 有效翻译: {num}, 待翻译: {num2}", "Detailed");
				if (num2 > 0)
				{
					LogInfo($"\ud83d\udca1 提示: 有 {num2} 项待翻译,您可以编辑翻译文件进行翻译");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogError((object)("加载翻译文件失败: " + ex.Message));
				}
			}
			return Task.CompletedTask;
		}

		public Task SaveCollectedItemsAsync()
		{
			if (_collectedItems.Count == 0)
			{
				return Task.CompletedTask;
			}
			if (_collectedItems.Count == _lastSavedCount)
			{
				return Task.CompletedTask;
			}
			try
			{
				Dictionary<string, string> dictionary = _collectedItems.Where<KeyValuePair<string, string>>((KeyValuePair<string, string> kvp) => !_translations.ContainsKey(kvp.Key) || string.IsNullOrWhiteSpace(_translations[kvp.Key])).ToDictionary((KeyValuePair<string, string> kvp) => kvp.Key, (KeyValuePair<string, string> kvp) => kvp.Value);
				int num = _collectedItems.Count - dictionary.Count;
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)$"\ud83d\udcbe 保存收集项: {dictionary.Count} 项 (已过滤 {num} 项已翻译内容)");
				}
				_fileManager.SaveToYaml(dictionary, _collectionFilePath);
				_lastSavedCount = dictionary.Count;
				_unsavedCount = 0;
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource2 = _logSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("❌ 保存收集项失败: " + ex.Message));
				}
			}
			return Task.CompletedTask;
		}

		private Task GenerateTranslationTemplateAsync()
		{
			try
			{
				if (File.Exists(_translationFilePath))
				{
					ManualLogSource? logSource = _logSource;
					if (logSource != null)
					{
						logSource.LogInfo((object)"\ud83d\udcdd 翻译文件已存在,跳过模板生成");
					}
					return Task.CompletedTask;
				}
				Dictionary<string, string> translations = new Dictionary<string, string>();
				_fileManager.SaveToYaml(translations, _translationFilePath);
				ManualLogSource? logSource2 = _logSource;
				if (logSource2 != null)
				{
					logSource2.LogInfo((object)("\ud83d\udcdd 已创建空的翻译文件模板: " + _translationFilePath));
				}
				ManualLogSource? logSource3 = _logSource;
				if (logSource3 != null)
				{
					logSource3.LogInfo((object)"\ud83d\udca1 提示: 请参考 collected_items.yaml 中的内容进行翻译");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource4 = _logSource;
				if (logSource4 != null)
				{
					logSource4.LogError((object)("❌ 生成翻译模板失败: " + ex.Message));
				}
			}
			return Task.CompletedTask;
		}

		private Task CleanupCollectedItemsAsync(Dictionary<string, string>? collectedItems)
		{
			try
			{
				if (_translations.Count == 0)
				{
					return Task.CompletedTask;
				}
				if (collectedItems == null || collectedItems.Count == 0)
				{
					return Task.CompletedTask;
				}
				int count = collectedItems.Count;
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				foreach (KeyValuePair<string, string> collectedItem in collectedItems)
				{
					if (!_translations.ContainsKey(collectedItem.Key) || string.IsNullOrWhiteSpace(_translations[collectedItem.Key]))
					{
						dictionary[collectedItem.Key] = collectedItem.Value;
					}
				}
				int num = count - dictionary.Count;
				if (num > 0)
				{
					_fileManager.SaveToYaml(dictionary, _collectionFilePath);
					ManualLogSource? logSource = _logSource;
					if (logSource != null)
					{
						logSource.LogDebug((object)$"\ud83e\uddf9 已清理收集文件: 移除 {num} 项已翻译内容,剩余 {dictionary.Count} 项待翻译");
					}
				}
				else
				{
					ManualLogSource? logSource2 = _logSource;
					if (logSource2 != null)
					{
						logSource2.LogDebug((object)"✅ 收集文件无需清理 (所有项目均未翻译)");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource3 = _logSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)("❌ 清理收集文件失败: " + ex.Message));
				}
			}
			return Task.CompletedTask;
		}

		private Task CopyUserGuideAsync(string projectDir)
		{
			try
			{
				string text = Path.Combine(projectDir, "README_翻译指南.md");
				if (File.Exists(text))
				{
					ManualLogSource? logSource = _logSource;
					if (logSource != null)
					{
						logSource.LogDebug((object)"\ud83d\udcd6 用户指南文档已存在,跳过复制");
					}
					return Task.CompletedTask;
				}
				string contents = "# 智能本地化翻译指南\r\n\r\n## 快速开始\r\n1. 编辑 `translations.yaml` 文件\r\n2. 格式:`原文: 翻译`\r\n3. 保存文件并重启服务器\r\n\r\n## 文件位置\r\n- 翻译文件:`translations.yaml`\r\n- 收集文件:`collected_items.yaml`\r\n\r\n## 注意事项\r\n- 保持冒号左边的原文不变\r\n- 只修改冒号右边的翻译\r\n- 修改后需要重启服务器生效\r\n\r\n更多详细信息请查看插件日志。\r\n";
				File.WriteAllText(text, contents, Encoding.UTF8);
				ManualLogSource? logSource2 = _logSource;
				if (logSource2 != null)
				{
					logSource2.LogInfo((object)("已创建基本用户指南: " + text));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logSource3 = _logSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)("复制用户指南失败: " + ex.Message));
				}
			}
			return Task.CompletedTask;
		}

		private Task LoadCacheAsync()
		{
			if (!string.IsNullOrEmpty(_cacheFilePath) && File.Exists(_cacheFilePath))
			{
				Dictionary<string, string> dictionary = _fileManager.LoadFromYaml(_cacheFilePath);
				foreach (KeyValuePair<string, string> item in dictionary)
				{
					_translations[item.Key] = item.Value;
				}
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)$"\ud83d\udce5 已加载 {dictionary.Count} 条缓存翻译");
				}
			}
			return Task.CompletedTask;
		}

		private LocalizationStatistics GetStatistics()
		{
			return new LocalizationStatistics
			{
				TotalCollected = _totalCollected,
				TotalTranslated = _totalTranslated,
				TotalApplied = _totalApplied,
				CacheHits = _cacheHits,
				CacheMisses = _cacheMisses,
				CacheHitRate = ((_cacheHits + _cacheMisses > 0) ? ((double)_cacheHits / (double)(_cacheHits + _cacheMisses) * 100.0) : 0.0),
				CurrentPhase = _currentPhase,
				TranslationCount = _translations.Count,
				CollectedCount = _collectedItems.Count
			};
		}

		public void LogTranslationCacheStats()
		{
			if (_translationQueryCount > 0)
			{
				double num = (double)_translationCacheHits / (double)_translationQueryCount * 100.0;
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)$"[翻译统计] 查询: {_translationQueryCount}次, 缓存命中: {_translationCacheHits}次({num:F1}%), 新收集: {_translationNewCount}次");
				}
			}
		}

		public void Dispose()
		{
			if (_isDisposed)
			{
				return;
			}
			_collectionEndCheckTimer?.Dispose();
			if (_unsavedCount > 0)
			{
				ManualLogSource? logSource = _logSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)"\ud83d\udcbe 插件卸载前保存未保存的数据...");
				}
				SaveCollectedItemsAsync().Wait();
			}
			_isDisposed = true;
			ManualLogSource? logSource2 = _logSource;
			if (logSource2 != null)
			{
				logSource2.LogInfo((object)"\ud83d\udd04 智能本地化管理器已释放");
			}
		}
	}
	public enum LocalizationPhase
	{
		Initialization,
		Collection,
		Application
	}
	public class LocalizationStatistics
	{
		public int TotalCollected { get; set; }

		public int TotalTranslated { get; set; }

		public int TotalApplied { get; set; }

		public int CacheHits { get; set; }

		public int CacheMisses { get; set; }

		public double CacheHitRate { get; set; }

		public LocalizationPhase CurrentPhase { get; set; }

		public int TranslationCount { get; set; }

		public int CollectedCount { get; set; }
	}
}
namespace Autolocalization.Localization
{
	public class LocalizationFileManager
	{
		private readonly ISerializer _yamlSerializer;

		private readonly IDeserializer _yamlDeserializer;

		private readonly object _fileLock = new object();

		public LocalizationFileManager()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			_yamlSerializer = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
			_yamlDeserializer = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
		}

		public Dictionary<string, string> LoadFromXml(string filePath)
		{
			if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
			{
				Logger.CreateLogSource("Autolocalization").LogWarning((object)("XML文件不存在: " + filePath));
				return new Dictionary<string, string>();
			}
			try
			{
				lock (_fileLock)
				{
					XDocument val = XDocument.Load(filePath);
					Dictionary<string, string> dictionary = new Dictionary<string, string>();
					IEnumerable<XElement> enumerable = ((XContainer)val).Descendants(XName.op_Implicit("item")) ?? ((XContainer)val).Descendants(XName.op_Implicit("translation")) ?? ((XContainer)val).Descendants(XName.op_Implicit("entry"));
					foreach (XElement item in enumerable)
					{
						XAttribute obj = item.Attribute(XName.op_Implicit("key"));
						object obj2 = ((obj != null) ? obj.Value : null);
						if (obj2 == null)
						{
							XAttribute obj3 = item.Attribute(XName.op_Implicit("id"));
							obj2 = ((obj3 != null) ? obj3.Value : null);
						}
						string text = (string)obj2;
						string value = item.Value?.Trim();
						if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(value))
						{
							dictionary[text] = value;
						}
					}
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"从XML文件加载翻译: {filePath}, 共{dictionary.Count}条");
					return dictionary;
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("加载XML文件失败: " + filePath + ", 错误: " + ex.Message));
				return new Dictionary<string, string>();
			}
		}

		public Dictionary<string, string> LoadFromCsv(string filePath)
		{
			if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
			{
				Logger.CreateLogSource("Autolocalization").LogWarning((object)("CSV文件不存在: " + filePath));
				return new Dictionary<string, string>();
			}
			try
			{
				lock (_fileLock)
				{
					string[] array = File.ReadAllLines(filePath, Encoding.UTF8);
					Dictionary<string, string> dictionary = new Dictionary<string, string>();
					for (int i = 0; i < array.Length; i++)
					{
						string text = array[i].Trim();
						if (string.IsNullOrEmpty(text) || text.StartsWith("#"))
						{
							continue;
						}
						string[] array2 = ParseCsvLine(text);
						if (array2.Length >= 2)
						{
							string text2 = array2[0].Trim();
							string value = array2[1].Trim();
							if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(value))
							{
								dictionary[text2] = value;
							}
						}
					}
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"从CSV文件加载翻译: {filePath}, 共{dictionary.Count}条");
					return dictionary;
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("加载CSV文件失败: " + filePath + ", 错误: " + ex.Message));
				return new Dictionary<string, string>();
			}
		}

		public Dictionary<string, string> LoadFromYaml(string filePath)
		{
			if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
			{
				Logger.CreateLogSource("Autolocalization").LogWarning((object)("YAML文件不存在: " + filePath));
				return new Dictionary<string, string>();
			}
			try
			{
				lock (_fileLock)
				{
					string text = File.ReadAllText(filePath, Encoding.UTF8);
					Dictionary<string, string> dictionary = _yamlDeserializer.Deserialize<Dictionary<string, string>>(text);
					string fileName = Path.GetFileName(filePath);
					string arg = (fileName.Contains("collected") ? "收集数据" : (fileName.Contains("translation") ? "翻译数据" : "YAML数据"));
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"从YAML文件加载{arg}: {filePath}, 共{dictionary?.Count ?? 0}条");
					return dictionary ?? new Dictionary<string, string>();
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("加载YAML文件失败: " + filePath + ", 错误: " + ex.Message));
				return new Dictionary<string, string>();
			}
		}

		public void SaveToXml(Dictionary<string, string> translations, string filePath)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			if (translations == null || string.IsNullOrWhiteSpace(filePath))
			{
				return;
			}
			try
			{
				lock (_fileLock)
				{
					string directoryName = Path.GetDirectoryName(filePath);
					if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
					{
						Directory.CreateDirectory(directoryName);
					}
					XDocument val = new XDocument(new object[1] { (object)new XElement(XName.op_Implicit("translations"), new object[3]
					{
						(object)new XAttribute(XName.op_Implicit("version"), (object)"1.0"),
						(object)new XAttribute(XName.op_Implicit("generated"), (object)DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")),
						translations.Select<KeyValuePair<string, string>, XElement>((KeyValuePair<string, string> kvp) => new XElement(XName.op_Implicit("item"), new object[2]
						{
							(object)new XAttribute(XName.op_Implicit("key"), (object)kvp.Key),
							(object)new XText(kvp.Value)
						}))
					}) });
					val.Save(filePath);
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"保存翻译到XML文件: {filePath}, 共{translations.Count}条");
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("保存XML文件失败: " + filePath + ", 错误: " + ex.Message));
			}
		}

		public void SaveToCsv(Dictionary<string, string> translations, string filePath)
		{
			if (translations == null || string.IsNullOrWhiteSpace(filePath))
			{
				return;
			}
			try
			{
				lock (_fileLock)
				{
					string directoryName = Path.GetDirectoryName(filePath);
					if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
					{
						Directory.CreateDirectory(directoryName);
					}
					List<string> list = new List<string>
					{
						"# 翻译文件",
						"# 格式: 原文,译文",
						$"# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}",
						""
					};
					foreach (KeyValuePair<string, string> translation in translations)
					{
						string text = EscapeCsvValue(translation.Key);
						string text2 = EscapeCsvValue(translation.Value);
						list.Add(text + "," + text2);
					}
					File.WriteAllLines(filePath, list, Encoding.UTF8);
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"保存翻译到CSV文件: {filePath}, 共{translations.Count}条");
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("保存CSV文件失败: " + filePath + ", 错误: " + ex.Message));
			}
		}

		public void SaveToYaml(Dictionary<string, string> translations, string filePath)
		{
			if (translations == null || string.IsNullOrWhiteSpace(filePath))
			{
				return;
			}
			try
			{
				lock (_fileLock)
				{
					string directoryName = Path.GetDirectoryName(filePath);
					if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
					{
						Directory.CreateDirectory(directoryName);
					}
					string text = _yamlSerializer.Serialize((object)translations);
					string text2;
					if (!Path.GetFileName(filePath).Equals("translations.yaml", StringComparison.OrdinalIgnoreCase))
					{
						text2 = ((!Path.GetFileName(filePath).Equals("collected_items.yaml", StringComparison.OrdinalIgnoreCase)) ? $"# 翻译文件\n# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n# 条目数量: {translations.Count}\n\n" : $"# ============================================\r\n# 收集文件 (待翻译项目)\r\n# ============================================\r\n# \r\n# 说明:\r\n# - 此文件包含所有待翻译的英文原文\r\n# - 已翻译的项目会自动从此文件中移除\r\n# - 请参考此文件内容编辑 translations.yaml\r\n# \r\n# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\r\n# 待翻译数量: {translations.Count}\r\n# \r\n# ============================================\r\n\r\n");
					}
					else
					{
						int num = translations.Count<KeyValuePair<string, string>>((KeyValuePair<string, string> kvp) => !string.IsNullOrWhiteSpace(kvp.Value));
						int num2 = translations.Count - num;
						text2 = ((translations.Count != 0) ? $"# ============================================\r\n# 智能本地化翻译文件\r\n# ============================================\r\n# \r\n# 使用说明:\r\n# 1. 这是一个简单的翻译文件,格式为 \"原文: 翻译\"\r\n# 2. 请保持冒号左边的原文不变,只修改冒号右边的翻译\r\n# 3. 如果您不想翻译某个项目,可以删除该行或保持翻译部分为空\r\n# 4. 修改后请保存文件并重启服务器以使翻译生效\r\n# \r\n# 格式示例:\r\n#   Enable Shadows: 启用阴影\r\n#   Master Volume: 主音量\r\n#   Test Section: 测试区域\r\n# \r\n# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\r\n# 条目数量: {translations.Count} (已翻译: {num}, 待翻译: {num2})\r\n# \r\n# ============================================\r\n\r\n" : $"# ============================================\r\n# 智能本地化翻译文件\r\n# ============================================\r\n# \r\n# 使用说明:\r\n# 1. 这是您的翻译文件,请手动添加翻译条目\r\n# 2. 格式为 \"原文: 翻译\"\r\n# 3. 请参考 collected_items.yaml 查看需要翻译的内容\r\n# 4. 只添加您已经翻译好的条目,无需添加空值\r\n# \r\n# 示例:\r\n#   Enable Shadows: 启用阴影\r\n#   Master Volume: 主音量\r\n#   Graphics Settings: 图形设置\r\n# \r\n# 提示:\r\n# - 从 collected_items.yaml 复制需要翻译的原文\r\n# - 在冒号后面添加中文翻译\r\n# - 保存文件后重启服务器生效\r\n# \r\n# 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\r\n# \r\n# ============================================\r\n\r\n# 在下方添加您的翻译(删除此注释行)\r\n");
					}
					string contents = text2 + text;
					File.WriteAllText(filePath, contents, Encoding.UTF8);
					Logger.CreateLogSource("Autolocalization").LogInfo((object)$"保存翻译到YAML文件: {filePath}, 共{translations.Count}条");
				}
			}
			catch (Exception ex)
			{
				Logger.CreateLogSource("Autolocalization").LogError((object)("保存YAML文件失败: " + filePath + ", 错误: " + ex.Message));
			}
		}

		private string[] ParseCsvLine(string line)
		{
			List<string> list = new List<string>();
			string text = "";
			bool flag = false;
			for (int i = 0; i < line.Length; i++)
			{
				char c = line[i];
				switch (c)
				{
				case '"':
					flag = !flag;
					continue;
				case ',':
					if (!flag)
					{
						list.Add(text);
						text = "";
						continue;
					}
					break;
				}
				text += c;
			}
			list.Add(text);
			return list.ToArray();
		}

		private string EscapeCsvValue(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return "";
			}
			if (value.Contains(",") || value.Contains("\"") || value.Contains("\n") || value.Contains("\r"))
			{
				return "\"" + value.Replace("\"", "\"\"") + "\"";
			}
			return value;
		}
	}
}