Unity多语言(基于ET框架)

1.介绍

1. 代码枚举加语言(编辑器加语言)

2.一张Excle表配置所有语言

3.静态文本加载(编辑模式下可根据key看到value,Default Language为value的语言和游戏中的Language不同

4.动态文本加载 

 

2.核心代码示例

 1.LocalizationService.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace ETModel
{
   
    public class LocalizationService : ScriptableObject
    {
        #region static
        private static LocalizationService _instance;
        public static LocalizationService Instance
        {
            get { return _instance ?? (_instance = Create()); }
        }

        /// <summary>
        /// LocalizationService的asset文件
        /// </summary>
        /// <returns></returns>
        static LocalizationService Create()
        {
            return Resources.Load<LocalizationService>("LocalizationService");
        }

        #endregion

        #region event
        /// <summary>
        /// 语言改变事件
        /// </summary>
        public static Action OnLanguageChanged;
        #endregion

        #region properties

        /// <summary>
        /// 存储所有语言信息
        /// </summary>
        public Dictionary<long, string> Strings = new Dictionary<long, string>();      

        /// <summary>
        /// 默认显示静态文本语言
        /// </summary>
        [HideInInspector]
        public LanguageInfo DefaultLanguage;

        /// <summary>
        /// 当前语言
        /// </summary>
        [HideInInspector]
        private LanguageInfo _language = LanguageInfo.Chinese;
        public LanguageInfo Language
        {
            get { return _language; }
            set
            {
                if (!HasLanguage(value))
                {
                    Debug.LogError("Invalid Language " + value);
                }

                _language = value;

                RaiseLanguageChanged();

                SaveToPrefs();
            }
        }

        /// <summary>
        /// 所有支持的语言
        /// </summary>
        [SerializeField]
        public LanguageInfo[] Languages = LanguageInfo.All;
        #endregion

        #region LocalizationService       

        public void Init()
        {
            LoadLanguage();

#if UNITY_EDITOR
            if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }
#endif
         //   ReadFiles();
        }

        /// <summary>
        /// 默认加载语言
        /// </summary>
        void LoadLanguage()
        {
            var raw = PlayerPrefs.GetString("CurrentLanguage");
            if (string.IsNullOrEmpty(raw))
            {
                bool hasLan = false;
                for (int i = 0; i < Languages.Length; i++)
                {
                    if (Application.systemLanguage == Languages[i].lan)
                    {
                        hasLan = true;
                        Language = Languages[i];
                        break;
                    }
                }
                if (!hasLan)
                {
                    Language = LanguageInfo.Chinese;
                }
                return;
            }


            var lan = Languages.FirstOrDefault(o => o.Name == raw);
            if (lan == null)
            {
                Debug.LogError("Unknown language saved to prefs : " + raw);
                Language = LanguageInfo.Chinese;
            }
            else
            {
                Language = lan;
            }
        }

        /// <summary>
        /// 保存到本地
        /// </summary>
        void SaveToPrefs()
        {
            PlayerPrefs.SetString("CurrentLanguage", Language.Name);
            PlayerPrefs.Save();
        }

        #endregion

        #region internal

        /// <summary>
        /// 是否有配置该语言
        /// </summary>
        /// <param name="language"></param>
        /// <returns></returns>
        bool HasLanguage(LanguageInfo language)
        {
            foreach (var systemLanguage in Languages)
            {
                if (systemLanguage.Equals(language))
                    return true;
            }
            return false;
        }


        /// <summary>
        /// 切换语言
        /// </summary>
        private void RaiseLanguageChanged()
        {
            
            if (Application.isPlaying)
            {
                ReadFiles();
                if (OnLanguageChanged != null)
                    OnLanguageChanged();
            }
        }

        /// <summary>
        /// 读取当前语言配置(ET为例)
        /// </summary>
        void ReadFiles()
        {
            Strings.Clear();

            var configs = Game.Scene.GetComponent<ConfigComponent>().GetAll(typeof(Localization));

            if (!configs.Any())
            {
                Debug.LogError("Localization Files Not Found : " + Language.Name);
            }


            foreach (Localization config in configs)
            {
                ReadCSVAsset(config);
            }
        }

        /// <summary>
        /// 读取单条配置到缓存
        /// </summary>
        /// <param name="config"></param>
        void ReadCSVAsset(Localization config)
        {
            try
            {
                FieldInfo info = typeof(Localization).GetField(Language.Name);
                Strings.Add(config.Id, info.GetValue(config).ToString());

            }
            catch (Exception ex)
            {
                Debug.LogError(ex);
                Debug.LogError(string.Format("Failed to read file : {0}/{1}  ", Language, config.Id));
            }

        }
        #endregion

        #region public

        /// <summary>
        /// 非运行模式下加载文本TODO
        /// </summary>
        public void LoadTextAssets()
        {
            // ReadFiles();
#if UNITY_EDITOR
            Strings.Clear();
            var jsonObj = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/Res/Config/Localization.txt", typeof(TextAsset)) as TextAsset;
            string[] jsonArray = jsonObj.text.Split('n');
            foreach (string tx in jsonArray)
            {
                if (string.IsNullOrEmpty(tx))
                    continue;
                Localization json = JsonHelper.FromJson<Localization>(tx);
                FieldInfo info = typeof(Localization).GetField(DefaultLanguage.Name);
                Strings.Add(json.Id, info.GetValue(json).ToString());
            }           
#endif
        }

        /// <summary>
        /// 从字典获取多语言文本
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string Get(long key)
        {
            return Get(key, string.Empty);
        }

        /// <summary>
        /// 获取多语言文本,没有则返回默认值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="fallback"> if not found</param>
        /// <returns></returns>
        public string Get(long key, string fallback)
        {
            if (!Strings.ContainsKey(key))
            {
             //   Debug.LogWarning(string.Format("Localization Key Not Found {0} : {1} ", Language.Name, key));
                return fallback;
            }

            return Strings[key];
        }


        #endregion


    }
}

2.LocalizationServiceEditor.cs

using ETModel;
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace ETEditor
{
    /// <summary>
    /// 绘制LocalizationService面板
    /// </summary>
    [CustomEditor(typeof(LocalizationService), true)]
    public class LocalizationServiceEditor : UnityEditor.Editor
    {
        protected LocalizationService Target;

        
        [MenuItem("Tools/Foundation/Localization Service")]
        public static void ShowWindow()
        {
            LocalizationInitializer.Startup();
            Selection.activeObject = LocalizationService.Instance;
            EditorGUIUtility.PingObject(LocalizationService.Instance);

        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            LocalizationInitializer.Startup();

            Target = target as LocalizationService;

            if (Application.isPlaying)
                return;

            EditorGUILayout.LabelField("Default Language");
            var di = Array.IndexOf(Target.Languages, Target.DefaultLanguage);
            var di2 = EditorGUILayout.Popup(di, Target.Languages.Select(o => o.Name).ToArray());

            if (di != di2)
            {
                Target.DefaultLanguage = Target.Languages[di2];
                Target.LoadTextAssets();
                EditorUtility.SetDirty(target);
            }

            if (GUILayout.Button("Reset Language List"))
            {
                Target.Languages = LanguageInfo.All;
                Debug.LogError(LanguageInfo.All[0].Name);
                Debug.LogError(LanguageInfo.All[1].Name);
                EditorUtility.SetDirty(target);
            }
        }
    }
}

3.LocalizedText.cs

using UnityEngine;
using UnityEngine.UI;

namespace ETModel
{
    /// <summary>
    /// 静态文本
    /// </summary>
    [RequireComponent(typeof(Text))]
    [AddComponentMenu("Localization/LocalizedText")]
    public class LocalizedText : MonoBehaviour
    {

        [HideInInspector]
        public long Key;

        private void Awake()
        {
            OnLocalization();
            LocalizationService.OnLanguageChanged += OnLocalization;
        }

        private void OnDestroy()
        {
            LocalizationService.OnLanguageChanged -= OnLocalization;
        }

        public void OnLocalization()
        {
            var label = GetComponent<Text>();

            label.text = Game.Scene.GetComponent<LocaliztionComponent>().GetTextByKey(Key);
        }

    }
}

4.LocalizedTextEditor.cs

using ETModel;
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace ETEditor
{
    /// <summary>
    /// LocalizedText面板
    /// </summary>
    [CustomEditor(typeof(LocalizedText), true)]
    public class LocalizedTextEditor : UnityEditor.Editor
    {
        protected LocalizedText Target;

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

         //   LocalizationInitializer.Startup();

            Target = target as LocalizedText;

            if (Application.isPlaying)
                return;

            var service = LocalizationService.Instance;

            if (service != null)
            {
                var p = EditorGUILayout.LongField("Key", Target.Key);

                if (p != Target.Key)
                {
                    Target.Key = p;
                    EditorUtility.SetDirty(target);
                }
                EditorGUILayout.LabelField("Value", service.Get(p));
            }
           
        }
    }
}


5.LocaliztionComponent.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace ETModel
{
    [ObjectSystem]
    public class LocaliztionAwakeSystem : AwakeSystem<LocaliztionComponent>
    {
        public override void Awake(LocaliztionComponent self)
        {
            LocalizationService.Instance.Init();
        }
    }

    [ObjectSystem]
    public class LocaliztionDestroySystem : DestroySystem<LocaliztionComponent>
    {
        public override void Destroy(LocaliztionComponent self)
        {
            if (LocalizationService.Instance.Language != LocalizationService.Instance.DefaultLanguage)
                LocalizationService.Instance.LoadTextAssets();
        }
    }
    public class LocaliztionComponent : Component
    {
        /// <summary>
        /// 获取文本
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetTextByKey(long key)
        {
            return LocalizationService.Instance.Get(key);
        }

        /// <summary>
        /// 切换语言
        /// </summary>
        /// <param name="info"></param>
        public void ChangeLanguage(LanguageInfo info)
        {
            LocalizationService.Instance.Language = info;
        }

        /// <summary>
        /// 动态文本如果切换语言时没有手动刷新界面的话,需要加上这个回调强制刷新
        /// </summary>
        /// <param name="act"></param>
        public void OnLanguageChanged(Action act)
        {
            LocalizationService.OnLanguageChanged += act;
        }
    }
}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>