Files
bansonic_beta_main/Assets/scripts/localization/LocalizationRuntimeBootstrap.cs
T

182 lines
5.1 KiB
C#

using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.Localization.Components;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.Collections.Generic;
public class LocalizationRuntimeBootstrap : MonoBehaviour
{
private static LocalizationRuntimeBootstrap _instance;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Bootstrap()
{
LocalizationService.EnsureInitialized();
if (_instance != null)
{
return;
}
GameObject go = new GameObject("LocalizationRuntimeBootstrap");
DontDestroyOnLoad(go);
_instance = go.AddComponent<LocalizationRuntimeBootstrap>();
}
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
_instance = this;
SceneManager.sceneLoaded += OnSceneLoaded;
LocalizationService.LanguageChanged += OnLanguageChanged;
}
private void Start()
{
StartCoroutine(ApplyLocalizationDeferred());
}
private void OnDestroy()
{
if (_instance == this)
{
SceneManager.sceneLoaded -= OnSceneLoaded;
LocalizationService.LanguageChanged -= OnLanguageChanged;
_instance = null;
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
StartCoroutine(ApplyLocalizationDeferred());
}
private void OnLanguageChanged(string languageCode)
{
StartCoroutine(ApplyLocalizationDeferred());
}
private IEnumerator ApplyLocalizationDeferred()
{
// Some UI updates its text in Start/OnEnable one or two frames after scene load.
// Re-apply for a few frames so late-bound labels are still captured.
for (int i = 0; i < 4; i++)
{
yield return null;
ApplyLocalizationToLoadedTexts();
}
}
private static void ApplyLocalizationToLoadedTexts()
{
foreach (Text text in EnumerateSceneTexts())
{
if (!IsLocalizable(text))
{
continue;
}
LocalizedLiteralText binding = text.GetComponent<LocalizedLiteralText>();
if (binding == null)
{
binding = text.gameObject.AddComponent<LocalizedLiteralText>();
}
binding.CaptureIfNeeded(text.text, false);
binding.Refresh();
}
foreach (TMP_Text tmp in EnumerateSceneTmpTexts())
{
if (!IsLocalizable(tmp))
{
continue;
}
LocalizedLiteralText binding = tmp.GetComponent<LocalizedLiteralText>();
if (binding == null)
{
binding = tmp.gameObject.AddComponent<LocalizedLiteralText>();
}
binding.CaptureIfNeeded(tmp.text, true);
binding.Refresh();
}
}
private static IEnumerable<Text> EnumerateSceneTexts()
{
int sceneCount = SceneManager.sceneCount;
for (int i = 0; i < sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (!scene.IsValid() || !scene.isLoaded)
{
continue;
}
GameObject[] roots = scene.GetRootGameObjects();
for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
Text[] texts = roots[rootIndex].GetComponentsInChildren<Text>(true);
for (int textIndex = 0; textIndex < texts.Length; textIndex++)
{
yield return texts[textIndex];
}
}
}
}
private static IEnumerable<TMP_Text> EnumerateSceneTmpTexts()
{
int sceneCount = SceneManager.sceneCount;
for (int i = 0; i < sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (!scene.IsValid() || !scene.isLoaded)
{
continue;
}
GameObject[] roots = scene.GetRootGameObjects();
for (int rootIndex = 0; rootIndex < roots.Length; rootIndex++)
{
TMP_Text[] texts = roots[rootIndex].GetComponentsInChildren<TMP_Text>(true);
for (int textIndex = 0; textIndex < texts.Length; textIndex++)
{
yield return texts[textIndex];
}
}
}
}
private static bool IsLocalizable(Component component)
{
if (component == null || component.gameObject == null)
{
return false;
}
GameObject gameObject = component.gameObject;
if (!gameObject.scene.IsValid() || !gameObject.scene.isLoaded || string.IsNullOrEmpty(gameObject.scene.name))
{
return false;
}
if (gameObject.GetComponent<LocalizedText>() != null ||
gameObject.GetComponent<LocalizedTMPText>() != null ||
gameObject.GetComponent<LocalizeStringEvent>() != null)
{
return false;
}
return true;
}
}