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() .Description; builder.BuildAction(code, () => Localize(visualElement, code)); } */ builder.BuildAction("Default", () => Localize(visualElement, _localizationService.CurrentLanguage)); builder.Build(); } private UniTask 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