112 lines
3.7 KiB
C#
112 lines
3.7 KiB
C#
|
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
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 本地化
|
|||
|
/// </summary>
|
|||
|
public interface ILocalizationService
|
|||
|
{
|
|||
|
public string Prefix { get; }
|
|||
|
/// <summary>
|
|||
|
/// 当前语言
|
|||
|
/// </summary>
|
|||
|
public string CurrentLanguage { get; }
|
|||
|
/// <summary>
|
|||
|
/// 更改回调,通常在此检查并下载语言包
|
|||
|
/// </summary>
|
|||
|
public event Func<string,string,UniTask> OnLanguageChangeAsync;
|
|||
|
/// <summary>
|
|||
|
/// 语言更改完成回调,UI和World执行更新
|
|||
|
/// </summary>
|
|||
|
public event Action<string,string> OnLanguageChanged;
|
|||
|
/// <summary>
|
|||
|
/// 获取翻译文本,返回无复制的引用
|
|||
|
/// </summary>
|
|||
|
/// <param name="key"></param>
|
|||
|
/// <param name="language">语言,默认为当前CultureInfo.Name</param>
|
|||
|
/// <returns></returns>
|
|||
|
public string GetLocalizedString(string key,string language=null);
|
|||
|
public UniTask ChangeLanguageAsync(string newLanguage);
|
|||
|
public IDictionary<string, IDictionary<string, string>> 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<string, string, UniTask> OnLanguageChangeAsync;
|
|||
|
public event Action<string, string> OnLanguageChanged;
|
|||
|
|
|||
|
private readonly ILogger<LocalizationService> _logger;
|
|||
|
|
|||
|
public IDictionary<string, IDictionary<string, string>> LocalizedStrings { get; } =
|
|||
|
new Dictionary<string, IDictionary<string, string>>();
|
|||
|
|
|||
|
private readonly ValidHandle _isBusy = new();
|
|||
|
|
|||
|
private readonly HashSet<string> _untranslatedKeys = new();
|
|||
|
|
|||
|
public LocalizationService(ILogger<LocalizationService> 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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|