using System.Globalization;
using System.IO;
using System.Text.Json;
using GFramework.Core.Abstractions.Localization;
using GFramework.Core.Systems;
namespace GFramework.Core.Localization;
///
/// 本地化管理器实现
///
public class LocalizationManager : AbstractSystem, ILocalizationManager
{
private readonly LocalizationConfig _config;
private readonly Dictionary _formatters;
private readonly List> _languageChangeCallbacks;
private readonly Dictionary> _tables;
private List _availableLanguages;
private CultureInfo _currentCulture;
private string _currentLanguage;
///
/// 初始化本地化管理器
///
/// 配置
public LocalizationManager(LocalizationConfig? config = null)
{
_config = config ?? new LocalizationConfig();
_tables = new Dictionary>();
_formatters = new Dictionary();
_languageChangeCallbacks = new List>();
_currentLanguage = _config.DefaultLanguage;
_currentCulture = GetCultureInfo(_currentLanguage);
_availableLanguages = new List();
}
///
public string CurrentLanguage => _currentLanguage;
///
public CultureInfo CurrentCulture => _currentCulture;
///
public IReadOnlyList AvailableLanguages => _availableLanguages;
///
public void SetLanguage(string languageCode)
{
if (string.IsNullOrEmpty(languageCode))
{
throw new ArgumentNullException(nameof(languageCode));
}
if (_currentLanguage == languageCode)
{
return;
}
LoadLanguage(languageCode);
_currentLanguage = languageCode;
_currentCulture = GetCultureInfo(languageCode);
// 触发语言变化回调
TriggerLanguageChange();
}
///
public ILocalizationTable GetTable(string tableName)
{
if (string.IsNullOrEmpty(tableName))
{
throw new ArgumentNullException(nameof(tableName));
}
if (!_tables.TryGetValue(_currentLanguage, out var languageTables))
{
throw new LocalizationTableNotFoundException(tableName);
}
if (!languageTables.TryGetValue(tableName, out var table))
{
throw new LocalizationTableNotFoundException(tableName);
}
return table;
}
///
public string GetText(string table, string key)
{
return GetTable(table).GetRawText(key);
}
///
public ILocalizationString GetString(string table, string key)
{
return new LocalizationString(this, table, key);
}
///
public bool TryGetText(string table, string key, out string text)
{
try
{
text = GetText(table, key);
return true;
}
catch (LocalizationException)
{
// 只捕获本地化相关的异常(键不存在、表不存在等)
text = string.Empty;
return false;
}
}
///
public void RegisterFormatter(string name, ILocalizationFormatter formatter)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
_formatters[name] = formatter ?? throw new ArgumentNullException(nameof(formatter));
}
///
public ILocalizationFormatter? GetFormatter(string name)
{
if (string.IsNullOrEmpty(name))
{
return null;
}
return _formatters.TryGetValue(name, out var formatter) ? formatter : null;
}
///
public void SubscribeToLanguageChange(Action callback)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
if (!_languageChangeCallbacks.Contains(callback))
{
_languageChangeCallbacks.Add(callback);
}
}
///
public void UnsubscribeFromLanguageChange(Action callback)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
_languageChangeCallbacks.Remove(callback);
}
///
protected override void OnInit()
{
// 扫描可用语言
ScanAvailableLanguages();
// 加载默认语言
LoadLanguage(_config.DefaultLanguage);
}
///
protected override void OnDestroy()
{
_tables.Clear();
_formatters.Clear();
_languageChangeCallbacks.Clear();
}
///
/// 扫描可用语言
///
private void ScanAvailableLanguages()
{
_availableLanguages.Clear();
var localizationPath = _config.LocalizationPath;
if (!Directory.Exists(localizationPath))
{
_availableLanguages.Add(_config.DefaultLanguage);
return;
}
var directories = Directory.GetDirectories(localizationPath);
foreach (var dir in directories)
{
var languageCode = Path.GetFileName(dir);
if (!string.IsNullOrEmpty(languageCode))
{
_availableLanguages.Add(languageCode);
}
}
if (_availableLanguages.Count == 0)
{
_availableLanguages.Add(_config.DefaultLanguage);
}
}
///
/// 加载语言
///
private void LoadLanguage(string languageCode)
{
if (_tables.ContainsKey(languageCode))
{
return; // 已加载
}
var languageTables = new Dictionary();
// 加载回退语言(如果不是默认语言)
Dictionary? fallbackTables = null;
if (languageCode != _config.FallbackLanguage)
{
LoadLanguage(_config.FallbackLanguage);
_tables.TryGetValue(_config.FallbackLanguage, out fallbackTables);
}
// 加载目标语言
var languagePath = Path.Combine(_config.LocalizationPath, languageCode);
if (Directory.Exists(languagePath))
{
var jsonFiles = Directory.GetFiles(languagePath, "*.json");
foreach (var file in jsonFiles)
{
var tableName = Path.GetFileNameWithoutExtension(file);
var data = LoadJsonFile(file);
ILocalizationTable? fallback = null;
fallbackTables?.TryGetValue(tableName, out fallback);
languageTables[tableName] = new LocalizationTable(tableName, languageCode, data, fallback);
}
}
_tables[languageCode] = languageTables;
}
///
/// 加载 JSON 文件
///
private static Dictionary LoadJsonFile(string filePath)
{
var json = File.ReadAllText(filePath);
var data = JsonSerializer.Deserialize>(json);
return data ?? new Dictionary();
}
///
/// 获取文化信息
///
private static CultureInfo GetCultureInfo(string languageCode)
{
try
{
// 尝试映射常见的语言代码
var cultureCode = languageCode switch
{
"eng" => "en-US",
"zhs" => "zh-CN",
"zht" => "zh-TW",
"jpn" => "ja-JP",
"kor" => "ko-KR",
"fra" => "fr-FR",
"deu" => "de-DE",
"spa" => "es-ES",
"rus" => "ru-RU",
_ => languageCode
};
return new CultureInfo(cultureCode);
}
catch
{
return CultureInfo.InvariantCulture;
}
}
///
/// 触发语言变化事件
///
private void TriggerLanguageChange()
{
foreach (var callback in _languageChangeCallbacks.ToList())
{
try
{
callback(_currentLanguage);
}
catch
{
// 忽略回调异常
}
}
}
}