// Copyright (c) Pixel Crushers. All rights reserved. using UnityEngine; using System.Collections; using System.Collections.Generic; namespace PixelCrushers { /// /// Manages localization settings. /// [AddComponentMenu("")] // Use wrapper. public class UILocalizationManager : MonoBehaviour { [Tooltip("The PlayerPrefs key to store the player's selected language code.")] [SerializeField] private string m_currentLanguagePlayerPrefsKey = "Language"; [Tooltip("Overrides the global text table.")] [SerializeField] private TextTable m_textTable = null; [Tooltip("Any additional text tables.")] [SerializeField] private List m_additionalTextTables = null; [Tooltip("Table of fonts to use for specific languages.")] [SerializeField] private LocalizedFonts m_localizedFonts; [Tooltip("When starting, set current language to value saved in PlayerPrefs.")] [SerializeField] private bool m_saveLanguageInPlayerPrefs = true; [Tooltip("When updating UIs, perform longer search that also finds LocalizeUI components on inactive GameObjects.")] [SerializeField] private bool m_alsoUpdateInactiveLocalizeUI = true; [Tooltip("If a language's field value is blank, use default language's field value.")] [SerializeField] private bool m_useDefaultLanguageForBlankTranslations = true; private string m_currentLanguage = string.Empty; public LocalizedFonts localizedFonts { get { return m_localizedFonts; } set { m_localizedFonts = value; } } private static UILocalizationManager s_instance = null; private static bool s_isQuitting = false; /// /// Current global instance of UILocalizationManager. If one doesn't exist, /// a default one will be created. /// public static UILocalizationManager instance { get { if (s_instance == null && !s_isQuitting) { s_instance = GameObjectUtility.FindFirstObjectByType(); if (s_instance == null && Application.isPlaying) { var globalTextTable = GameObjectUtility.FindFirstObjectByType(); s_instance = (globalTextTable != null) ? globalTextTable.gameObject.AddComponent() : new GameObject("UILocalizationManager").AddComponent(); } } return s_instance; } set { s_instance = value; } } public static event System.Action languageChanged = null; #if UNITY_2019_3_OR_NEWER && UNITY_EDITOR [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void InitStaticVariables() { s_instance = null; s_isQuitting = false; } #endif private void OnApplicationQuit() { s_isQuitting = true; } /// /// Overrides the global text table. /// public TextTable textTable { get { return (m_textTable != null) ? m_textTable : GlobalTextTable.textTable; } set { m_textTable = value; } } /// /// (Optional) Any additional text tables. /// public List additionalTextTables { get { return m_additionalTextTables; } set { m_additionalTextTables = value; } } /// /// Gets or sets the current language. Setting the current language also updates localized UIs. /// public string currentLanguage { get { return instance.m_currentLanguage; } set { instance.m_currentLanguage = value; instance.UpdateUIs(value); } } /// /// The PlayerPrefs key to store the player's selected language code. /// public string currentLanguagePlayerPrefsKey { get { return m_currentLanguagePlayerPrefsKey; } set { m_currentLanguagePlayerPrefsKey = value; } } public bool saveLanguageInPlayerPrefs { get { return m_saveLanguageInPlayerPrefs; } set { m_saveLanguageInPlayerPrefs = value; } } public bool useDefaultLanguageForBlankTranslations { get { return m_useDefaultLanguageForBlankTranslations; } set { m_useDefaultLanguageForBlankTranslations = value; TextTable.useDefaultLanguageForBlankTranslations = value; } } private void Awake() { if (s_instance == null) s_instance = this; Initialize(); } public void Initialize() { if (saveLanguageInPlayerPrefs) { if (!string.IsNullOrEmpty(currentLanguagePlayerPrefsKey) && PlayerPrefs.HasKey(currentLanguagePlayerPrefsKey)) { m_currentLanguage = PlayerPrefs.GetString(currentLanguagePlayerPrefsKey); languageChanged?.Invoke(currentLanguage); } } TextTable.useDefaultLanguageForBlankTranslations = m_useDefaultLanguageForBlankTranslations; } private IEnumerator Start() { yield return CoroutineUtility.endOfFrame; // Wait for Text components to start. UpdateUIs(currentLanguage); } /// /// Checks if text table(s) support the specified language. /// public bool HasLanguage(string language) { if (textTable != null && textTable.HasLanguage(language)) return true; if (additionalTextTables != null) { foreach (TextTable additionalTable in additionalTextTables) { if (additionalTable != null && additionalTable.HasLanguage(language)) return true; } } return false; } /// /// Checks if text table(s) have a specified field. /// /// /// public bool HasField(string fieldName) { if (textTable != null && textTable.HasField(fieldName)) return true; if (additionalTextTables != null) { foreach (TextTable additionalTable in additionalTextTables) { if (additionalTable != null && additionalTable.HasField(fieldName)) return true; } } return false; } /// /// Returns the localized text for a field in a specified language. /// public string GetFieldTextForLanguage(string fieldName, string language) { if (textTable != null && textTable.HasField(fieldName)) return textTable.GetFieldTextForLanguage(fieldName, language); if (additionalTextTables != null) { foreach (TextTable additionalTable in additionalTextTables) { if (additionalTable != null && additionalTable.HasField(fieldName)) return additionalTable.GetFieldTextForLanguage(fieldName, language); } } return string.Empty; } /// /// Returns the localized text for a field in the current language. /// public string GetLocalizedText(string fieldName) { return GetFieldTextForLanguage(fieldName, GlobalTextTable.currentLanguage); } /// /// Updates the current language and all localized UIs. /// /// Language code defined in your Text Table. public void UpdateUIs(string language) { m_currentLanguage = language; languageChanged?.Invoke(language); if (saveLanguageInPlayerPrefs) { if (!string.IsNullOrEmpty(currentLanguagePlayerPrefsKey)) { PlayerPrefs.SetString(currentLanguagePlayerPrefsKey, language); } } var localizeUIs = m_alsoUpdateInactiveLocalizeUI ? GameObjectUtility.FindObjectsOfTypeAlsoInactive() : GameObjectUtility.FindObjectsByType(); for (int i = 0; i < localizeUIs.Length; i++) { localizeUIs[i].UpdateText(); } } } }