美文网首页
Unity中简易的语言本地化思路

Unity中简易的语言本地化思路

作者: 全新的饭 | 来源:发表于2022-01-07 17:37 被阅读0次

    思路

    做一个单例:LanguageSys.
    它持有2个字典

    1. 语言类型 - id - 文字内容
    2. 语言类型 - id - 图片资源(Sprite)

    它向外界提供3个方法 + 1个属性

    1. 根据Id获取文字内容
    2. 根据Id获取图片资源
    3. 获取当前的语言类型
    4. 属性:当前的语言类型。允许外界修改。
      若当前语言类型修改成功(修改前后不是同一语言类型),发出事件:语言类型发生了变化,传出参数:当前的语言类型。

    外界实际根据语言类型设置文字内容时,有几种方式

    1. 为各目标text和img配置languageId,在初始时设置内容。
      监听“语言类型变化”事件,在事件触发时设置内容。
    2. 为各类语言类型配置此时要显示的GameObject,在初始时显示当前语言类型对应的GO,隐藏其他语言类型对应的GO。
      监听“语言类型变化”事件,在事件触发时再次进行前述隐藏和显示GO的操作。
    3. 在代码中直接调用LanguageSys提供的相关方法。

    参考代码

    LanguageSys

    public class LanguageSys
    {
        public static LanguageSys Instance{ get; private set; }
    
        private Dictionary<int, Dictionary<int, string>> _strDict;
        private Dictionary<int, Dictionary<int, Sprite>> _spriteDict;
    
        private const string CurLanguageTypeStorageKey = "CurLanguageType";
    
        public LanguageType CurLanguageType
        {
            get { return IntToLanguageType(CurIntLanguageType); }
            set 
            {
                if (CurLanguageType != value)
                {
                    PlayerPrefs.SetInt(CurLanguageTypeStorageKey, LanguageTypeToInt(value));
                    ChangeCurLanguageTypeEvent?.Invoke(CurLanguageType);
    
                    Debug.Log("修改语言类型:" + CurLanguageType);
                }
            }
        }
        private int CurIntLanguageType
        {
            get { return PlayerPrefs.GetInt(CurLanguageTypeStorageKey, 0); }
        }
    
        public Action<LanguageType> ChangeCurLanguageTypeEvent;
    
        public bool IsDefaultLanguageType
        {
            get { return CurLanguageType == LanguageType.None; }
        }
    
        public static void Init()
        {
            if (Instance == null)
            {
                Instance = new LanguageSys();
            }
        }
    
        private LanguageSys()
        {
            // TODO: 初始化2个字典
        }
    
        public void Destroy()
        {
    
        }
    
        public static int LanguageTypeToInt(LanguageType type)
        {
            return (int)type;
        }
    
        public static LanguageType IntToLanguageType(int value)
        {
            return (LanguageType)value;
        }
    
        public static string GetLanguageName(LanguageType type)
        {
            string name = string.Empty;
            switch (type)
            {
                case LanguageType.Chinese : name = "简体中文";break;
                case LanguageType.English : name = "English";break;
                default:break;
            }
            return name;
        }
    
        // 如果是英文类型,则需要用序数词的形式显示数字
        public string IntToStrByLanguageType(int value)
        {
            string str = value.ToString();
            if (CurLanguageType == LanguageType.English)
            {
                str = value.Ordinal();
            }
    
            return str;
        }
    
    
        public string GetStr(int id)
        {
            string value = string.Empty;
            if (_strDict.ContainsKey(CurIntLanguageType) || _strDict[CurIntLanguageType].ContainsKey(id))
            {
                value = _strDict[CurIntLanguageType][id];
            }
            else
            {
                Debug.LogError("LanguageSys获取目标字符串失败,id:" + id);
            }
    
            return value;
        }
    
        public Sprite GetSprite(int id)
        {
            Sprite value = null;
            if (_spriteDict.ContainsKey(CurIntLanguageType) || _spriteDict[CurIntLanguageType].ContainsKey(id))
            {
                value = _spriteDict[CurIntLanguageType][id];
            }
            else
            {
                Debug.LogError("LanguageSys获取目标图片失败,id:" + id);
            }
    
            return value;
        }
    }
    public enum LanguageType
    { 
        None,
        Chinese,
        English,
    }
    

    外界直接为目标text和img设置内容,需为各目标配置Id

    public class UILanguageLocalize : MonoBehaviour
    {
        [SerializeField]
        private TextAndId[] _texts;
        [SerializeField]
        private ImgAndId[] _imgs;
        private void Start()
        {
            SetData(LanguageSys.Instance.CurLanguageType);
    
            LanguageSys.Instance.ChangeCurLanguageTypeEvent += OnChangeLanguage;
        }
    
        private void OnDestroy()
        {
            if (LanguageSys.Instance != null)
            {
                LanguageSys.Instance.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
            }
        }
    
        private void OnChangeLanguage(LanguageType curType)
        {
            SetData(curType);
        }
    
        private void SetData(LanguageType type)
        {
            Debug.Log("SetData " + type);
            if (_texts != null)
            {
                foreach (var text in _texts)
                {
                    text.Text.text = LanguageSys.Instance.GetStr(text.Id);
                }
            }
    
            if (_imgs != null)
            {
                foreach (var img in _imgs)
                {
                    img.Image.sprite = LanguageSys.Instance.GetSprite(img.Id);
                }
            }
        }
    
        [Serializable]
        private struct TextAndId
        {
            public Text Text;
            public int Id;
        }
    
        [Serializable]
        private struct ImgAndId
        {
            public Image Image;
            public int Id;
        }
    }
    

    外界根据当前语言类型,设置相应GO的显示和隐藏

    public class UILanguageGoLocalize : MonoBehaviour
    {
        [SerializeField]
        private LanguageTypeAndGos[] _gos;
        private void Start()
        {
            SetActive(LanguageSys.Instance.CurLanguageType);
    
            LanguageSys.Instance.ChangeCurLanguageTypeEvent += OnChangeLanguage;
        }
    
        private void OnDestroy()
        {
            if (LanguageSys.Instance != null)
            {
                LanguageSys.Instance.ChangeCurLanguageTypeEvent -= OnChangeLanguage;
            }
        }
    
        private void OnChangeLanguage(LanguageType curType)
        {
            SetActive(curType);
        }
    
        private void SetActive(LanguageType type)
        {
            if (_gos != null)
            {
                foreach (var go in _gos)
                {
                    bool isActive = go.LanguageType == type;
                    foreach (var o in go.Gos)
                    {
                        if (o.activeSelf != isActive)
                        {
                            o.SetActive(isActive);
                        }
                    }
                }
            }
        }
    
        [Serializable]
        private struct LanguageTypeAndGos
        {
            public LanguageType LanguageType;
            public GameObject[] Gos;
        }
    }
    
    

    其他

    需注意,Unity中直接读表(如excel)获取到的string,若其中有换行符"\n",会被变为"\n"。
    因此在读取到str后,需将其中的"\n"替换为"\n"。

    str = str.Replace("\\n", "\n");
    

    在本地化语言时,需要用到的一些方法。

    1. 将数字(int)以序数词的形式显示。
    public static class MyExtension
    {
        // 基数词(int)转为序数词(str)
        public static string Ordinal(this int number)
        {
            const string TH = "th";
            string s = number.ToString();
    
            if (number < 1)
            {
                return s;
            }
    
            number %= 100;
            if ((number >= 11) && (number <= 13))
            {
                return s + TH;
            }
    
            switch (number % 10)
            {
                case 1: return s + "st";
                case 2: return s + "nd";
                case 3: return s + "rd";
                default: return s + TH;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Unity中简易的语言本地化思路

          本文链接:https://www.haomeiwen.com/subject/osojcrtx.html