思路
做一个单例: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;
}
}
}
网友评论