找回密码
 立即注册
查看: 402|回复: 0

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

[复制链接]
发表于 2022-1-8 10:08 | 显示全部楼层 |阅读模式
思路

做一个单例:LanguageSys.
它持有2个字典
    语言类型 - id - 文字内容语言类型 - id - 图片资源(Sprite)

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

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

  • 为各目标text和img配置languageId,在初始时设置内容。
    监听“语言类型变化”事件,在事件触发时设置内容。
  • 为各类语言类型配置此时要显示的GameObject,在初始时显示当前语言类型对应的GO,隐藏其他语言类型对应的GO。
    监听“语言类型变化”事件,在事件触发时再次进行前述隐藏和显示GO的操作。在代码中直接调用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");
在本地化语言时,需要用到的一些方法。
    将数字(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开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 23:30 , Processed in 0.063763 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表