Net.Like.Xue.Tokyo/Assets/BITKit/Unity/Scripts/UX/Localization/UXLocalization.cs

209 lines
7.3 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using BITKit;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using Net.BITKit.Localization;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
namespace Net.BITKit.UX
{
public class UXLocalization:IDisposable
{
public string[] Lang { get; set; } =
{
"zh-CN",
"en-US",
"ja-JP",
};
public static string USS { get; set; } = "localized";
private readonly IUXService _uxService;
private readonly ILocalizationService _localizationService;
private readonly IMainTicker _ticker;
public UXLocalization(IUXService uxService, ILocalizationService localizationService, IMainTicker ticker)
{
_uxService = uxService;
_localizationService = localizationService;
_ticker = ticker;
_localizationService.OnLanguageChanged += OnLanguageChanged;
_localizationService.OnLocalizeAsync += OnLocalizeAsync;
_ticker.Add(OnTick);
}
private void OnTick(float obj)
{
if (Mouse.current.rightButton.wasPressedThisFrame is false) return;
if (_uxService.TryPick(Mouse.current.position.ReadValue(), out var o) is false) return;
if (o is not VisualElement visualElement) return;
if (visualElement.ClassListContains(USS) is false) return;
var builder =
ContextMenuBuilder
.Create()
.BuildText(_localizationService.GetLocalizedString("Translate"));
foreach (var lang in Lang)
{
builder.BuildAction(lang, () => Localize(visualElement, lang));
}
/*
foreach (var lang in Enum.GetValues(typeof(Lang)))
{
var code = lang.GetType().GetMember(lang.ToString())[0].GetCustomAttribute<DescriptionAttribute>()
.Description;
builder.BuildAction(code, () => Localize(visualElement, code));
}
*/
builder.BuildAction("Default", () => Localize(visualElement, _localizationService.CurrentLanguage));
builder.Build();
}
private UniTask<bool> OnLocalizeAsync(string arg1, object arg2)
{
if (arg2 is not VisualElement visualElement) return UniTask.FromResult(false);
Localize((object)visualElement);
return UniTask.FromResult(true);
}
private void Localize(VisualElement visualElement, string lang = null)
{
if (string.IsNullOrEmpty(lang))
{
lang = _localizationService.CurrentLanguage;
}
var currentLang = _localizationService.GetLocalizedString('#' + visualElement.viewDataKey,
_localizationService.CurrentLanguage);
var translate = _localizationService.GetLocalizedString('#' + visualElement.viewDataKey, lang);
if (string.Equals(visualElement.tooltip, currentLang))
{
visualElement.tooltip = translate;
foreach (var child in visualElement.Children())
{
if (child.pickingMode is PickingMode.Position)
{
child.tooltip = translate;
}
}
}
switch (visualElement)
{
case Label label:
{
label.text = translate;
}
break;
case Button button:
{
button.text = translate;
}
break;
case ProgressBar progressBar:
{
progressBar.title = translate;
}
break;
case Foldout foldout:
{
foldout.text = translate;
}
break;
default:
{
ContinueWithBaseType(visualElement.GetType());
void ContinueWithBaseType(Type type)
{
while (true)
{
if (type is not null)
{
if (type.GetProperty("label", ReflectionHelper.Flags) is { } propertyInfo)
{
//Debug.Log($"{x.name}:#{x.viewDataKey}");
propertyInfo.SetValue(visualElement,translate);
}
else
{
type = type.BaseType;
continue;
}
}
if (type == null || type == typeof(object))
{
break;
//throw new NotImplementedException($"{visualElement.GetType().Name} is not translatable");
}
}
}
}
break;
}
}
private void Localize(object obj)
{
switch (obj)
{
case VisualElement visualElement:
{
foreach (var x in visualElement.Query(className:USS).Build())
{
Localize(x);
}
/*
foreach (var x in visualElement.Query<Label>(className:USS).ToList())
{
if (string.IsNullOrEmpty(x.viewDataKey))continue;
x.text = _localizationService.GetLocalizedString('#'+x.viewDataKey);
}
foreach (var x in visualElement.Query<Button>(className:USS).ToList())
{
if(string.IsNullOrEmpty(x.viewDataKey))continue;
x.text = _localizationService.GetLocalizedString('#'+x.viewDataKey);
}
foreach (var x in visualElement.Query<ProgressBar>(className:USS).ToList())
{
if(string.IsNullOrEmpty(x.viewDataKey))continue;
x.title = _localizationService.GetLocalizedString('#'+x.viewDataKey);
}
foreach (var x in visualElement.Query(className:USS).ToList())
{
if(string.IsNullOrEmpty(x.viewDataKey))continue;
continue;
}
*/
}
break;
}
}
private void OnLanguageChanged(string arg1, string arg2)
{
if (_uxService.Root is not VisualElement visualElement) return;
Localize(visualElement);
}
public void Dispose()
{
_ticker.Remove(OnTick);
}
}
}