using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using BITKit;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Net.BITKit.Localization
{
///
/// 本地化
///
public interface ILocalizationService
{
public string Prefix { get; }
///
/// 当前语言
///
public string CurrentLanguage { get; }
///
/// 更改回调,通常在此检查并下载语言包
///
public event Func OnLanguageChangeAsync;
///
/// 语言更改完成回调,UI和World执行更新
///
public event Action OnLanguageChanged;
///
/// 获取翻译文本,返回无复制的引用
///
///
/// 语言,默认为当前CultureInfo.Name
///
public string GetLocalizedString(string key,string language=null);
public UniTask ChangeLanguageAsync(string newLanguage);
public IDictionary> LocalizedStrings { get; }
}
public class LocalizationService : ILocalizationService,IDisposable
{
private static LocalizationService _singleton;
public string Prefix => "#";
private char _prefix = '#';
public string CurrentLanguage { get; private set; }
public event Func OnLanguageChangeAsync;
public event Action OnLanguageChanged;
private readonly ILogger _logger;
public IDictionary> LocalizedStrings { get; } =
new Dictionary>();
private readonly ValidHandle _isBusy = new();
private readonly HashSet _untranslatedKeys = new();
public LocalizationService(ILogger logger)
{
if (_singleton is not null)
{
logger.LogError("LocalizationService can only be one singleton");
return;
}
_logger = logger;
}
public string GetLocalizedString(string key, string language = null)
{
language ??= CurrentLanguage; // 默认使用当前语言
if (key[0] != _prefix)
{
key = _prefix + key;
}
if (LocalizedStrings.TryGetValue(language, out var langDict) && langDict.TryGetValue(key, out var value))
{
return value;
}
_untranslatedKeys.Add(key);
return key.Replace(Prefix,string.Empty).Replace("_"," "); // 如果找不到翻译,就返回 key 本身(常见策略)
}
public async UniTask ChangeLanguageAsync(string newLanguage)
{
if (CurrentLanguage == newLanguage) return;
var oldLanguage = CurrentLanguage;
CurrentLanguage = newLanguage;
await _isBusy;
using var _ = _isBusy.GetHandle();
await UniTask.SwitchToMainThread();
await OnLanguageChangeAsync.UniTaskFunc(oldLanguage, newLanguage);
// 触发同步事件(例如更新 UI)
OnLanguageChanged?.Invoke(oldLanguage, newLanguage);
}
public void Dispose()
{
_isBusy?.Dispose();
_singleton = null;
_logger.LogInformation("Untranslated keys:\n"+string.Join("\n", _untranslatedKeys));
_untranslatedKeys.Clear();
}
}
}