AppUITextAutoLanguage.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System;
  2. using System.Collections.Generic;
  3. using AppUI.Localization;
  4. using TMPro;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7. /// <summary>
  8. /// AppUI Prefab 用多语言组件。行为对齐 <see cref="TextAutoLanguage2"/>,但查词走 <see cref="AppUILocalization"/>(新表优先 + 旧表回退)。
  9. /// </summary>
  10. [ExecuteAlways]
  11. public class AppUITextAutoLanguage : MonoBehaviour
  12. {
  13. internal static readonly HashSet<AppUITextAutoLanguage> RegisteredComponents = new HashSet<AppUITextAutoLanguage>();
  14. [SerializeField] string textKey;
  15. [Tooltip("textKey 为空时使用的明文;有 key 时仅作 Editor 预览 fallback")]
  16. [SerializeField]
  17. string fallbackText;
  18. [SerializeField] RectTransform layoutRebuildObject;
  19. public object[] textFormatArgs = { };
  20. [SerializeField] LanguageFontSize[] languageFontSizes = {};
  21. int defaultFontSize = -1;
  22. void Awake()
  23. {
  24. AppUILocalization.Init();
  25. }
  26. void OnEnable()
  27. {
  28. AppUILocalization.OnLanguageChanged += HandleLanguageChanged;
  29. if (!string.IsNullOrEmpty(textKey) || !string.IsNullOrEmpty(fallbackText))
  30. ApplyToText();
  31. }
  32. void Start()
  33. {
  34. RegisteredComponents.Add(this);
  35. ApplyToText();
  36. }
  37. void OnDisable()
  38. {
  39. AppUILocalization.OnLanguageChanged -= HandleLanguageChanged;
  40. }
  41. void OnDestroy()
  42. {
  43. RegisteredComponents.Remove(this);
  44. }
  45. #if UNITY_EDITOR
  46. void OnValidate()
  47. {
  48. if (string.IsNullOrEmpty(textKey) && string.IsNullOrEmpty(fallbackText))
  49. return;
  50. ApplyToText();
  51. }
  52. #endif
  53. void HandleLanguageChanged(LanguageEnum _) => ApplyToText();
  54. public void SetTextKey(string key)
  55. {
  56. textKey = key;
  57. ApplyResolvedText();
  58. }
  59. void ApplyResolvedText()
  60. {
  61. string text = ResolveDisplayText();
  62. if (textFormatArgs != null && textFormatArgs.Length > 0)
  63. text = string.Format(text, textFormatArgs);
  64. else if (text != null && text.IndexOf("{0}", StringComparison.Ordinal) >= 0)
  65. return;
  66. Text textComp = GetComponent<Text>();
  67. if (textComp != null)
  68. {
  69. textComp.text = text;
  70. ApplyFontSize(textComp, value => textComp.fontSize = value, value => textComp.lineSpacing = value);
  71. if (layoutRebuildObject)
  72. LayoutRebuilder.ForceRebuildLayoutImmediate(layoutRebuildObject);
  73. return;
  74. }
  75. ApplyLocalizationToTmpText(text);
  76. }
  77. string ResolveDisplayText()
  78. {
  79. if (!string.IsNullOrEmpty(textKey))
  80. {
  81. #if UNITY_EDITOR
  82. if (!Application.isPlaying)
  83. AppUILocalization.Reload();
  84. #endif
  85. AppUILocalization.Init();
  86. return AppUILocalization.ResolveText(textKey);
  87. }
  88. return fallbackText ?? string.Empty;
  89. }
  90. static TMP_Text ResolveTmpTextTarget(TMP_InputField inputField, TextMeshProUGUI tmpOnSameObject)
  91. {
  92. if (inputField != null)
  93. {
  94. if (inputField.placeholder != null && inputField.placeholder is TMP_Text placeholderTmp)
  95. return placeholderTmp;
  96. if (inputField.textComponent != null)
  97. return inputField.textComponent;
  98. return tmpOnSameObject;
  99. }
  100. return tmpOnSameObject;
  101. }
  102. void ApplyLocalizationToTmpText(string text)
  103. {
  104. TMP_InputField tmpInput = GetComponent<TMP_InputField>();
  105. TextMeshProUGUI tmpUgUi = GetComponent<TextMeshProUGUI>();
  106. TMP_Text tmpTarget = ResolveTmpTextTarget(tmpInput, tmpUgUi);
  107. if (tmpTarget == null)
  108. return;
  109. tmpTarget.text = text;
  110. ApplyFontSize(tmpTarget, value => tmpTarget.fontSize = value, value => tmpTarget.lineSpacing = value);
  111. }
  112. void ApplyFontSize(TMP_Text tmpTarget, Action<float> setFontSize, Action<float> setLineSpacing)
  113. {
  114. if (defaultFontSize == -1)
  115. defaultFontSize = (int)tmpTarget.fontSize;
  116. else
  117. tmpTarget.fontSize = defaultFontSize;
  118. if (languageFontSizes == null || languageFontSizes.Length == 0)
  119. return;
  120. LanguageEnum language = AppUILocalization.GetLanguage();
  121. foreach (var languageFontSize in languageFontSizes)
  122. {
  123. if (languageFontSize.language != language)
  124. continue;
  125. if (languageFontSize.fontSize > 0)
  126. setFontSize(languageFontSize.fontSize);
  127. if (languageFontSize.lineSpacing > 0)
  128. setLineSpacing(languageFontSize.lineSpacing);
  129. break;
  130. }
  131. }
  132. void ApplyFontSize(Text textComp, Action<int> setFontSize, Action<float> setLineSpacing)
  133. {
  134. if (defaultFontSize == -1)
  135. defaultFontSize = textComp.fontSize;
  136. else
  137. textComp.fontSize = defaultFontSize;
  138. if (languageFontSizes == null || languageFontSizes.Length == 0)
  139. return;
  140. LanguageEnum language = AppUILocalization.GetLanguage();
  141. foreach (var languageFontSize in languageFontSizes)
  142. {
  143. if (languageFontSize.language != language)
  144. continue;
  145. if (languageFontSize.fontSize > 0)
  146. setFontSize(languageFontSize.fontSize);
  147. if (languageFontSize.lineSpacing > 0)
  148. setLineSpacing(languageFontSize.lineSpacing);
  149. break;
  150. }
  151. }
  152. public string GetTextKey()
  153. {
  154. return textKey;
  155. }
  156. public void ApplyToText()
  157. {
  158. ApplyResolvedText();
  159. Text text = GetComponent<Text>();
  160. if (text)
  161. onApplyToNext?.Invoke(text);
  162. }
  163. /// <summary>Editor 刷新按钮 / 改 json 后手动调用。</summary>
  164. public void RefreshLocalizedPreview()
  165. {
  166. #if UNITY_EDITOR
  167. if (!Application.isPlaying)
  168. AppUILocalization.Reload();
  169. #endif
  170. ApplyToText();
  171. }
  172. public Action<Text> onApplyToNext;
  173. }