Net.Like.Xue.Tokyo/Assets/BITKit/Core/Localization/ILocalizationService.cs

112 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}
}