|
思路
做一个单例: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");
在本地化语言时,需要用到的一些方法。
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; } }} |
|