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;
}
}
}