1. 程式人生 > >Unity3D研究之多語言用中文做KEY

Unity3D研究之多語言用中文做KEY

一個 階段 txt mon 多語 適合新手 inf 優點 app



做多語言的時候用中文做KEY絕對是有100%的優點,假設用英文表示那麽代碼裏面給文字賦值的地方全都是英文。寫的代碼多了以後維護起來就沒有人能看懂了,或者看起來非常費勁。

對PoolManager不了解的能夠看下初探PoolManager插件非常適合新手學習。

說說用中文做KEY的原理:Unity中給文字賦值的地方就兩處, 一個是提前預制在UI Prefab上的文字。另一個是寫在代碼裏面的文字。那麽在開發階段我們在Prefab和代碼裏面直接就寫中文,等項目後期通過工具把所有中文的地方所有提取出來。然後把提取出來的中文交給策劃。讓策劃他們去翻譯去,這樣我們之前寫的中文就是多語言的KEY。終於顯示的界面上的文字是用這個中文KEY讀表讀出來的。

NGUI裏全部的文字都是在UILabel中,但是我們要做圖文混排,一般都是在UILabel上在拓展一個自己的腳本,用這個腳本在生成相應的UILabel和UISprite。這篇文章我就先以UILabel來說明原理。

1.遍歷全部UIPrefab把包括UILabe(或者是你自己寫的)組件找出來,而且把文字提取出來。

2.遍歷全部的CS代碼。把全部 StrUtil.GetText(成功智慧網\n我要換行); 雙引號中間的中文以及字符全部提取出來。

直接上思路代碼。

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

public class TestStart :Editor
{
//UIPrefab文件夾文件夾
private static string UIPrefabPath = Application.dataPath + "/UI";
//腳本的文件夾文件夾
private static string ScriptPath = Application.dataPath + "/Scripts";
//導出的中文KEY路徑
private static string OutPath = Application.dataPath +"/out.txt";

private static List<string>Localization = null;
private static string staticWriteText = "";
[MenuItem("Tools/導出多語言")]
static void ExportChinese()
{
Localization = new List<string>();
staticWriteText ="";

//提取Prefab上的中文
staticWriteText +="----------------Prefab----------------------\n";
LoadDiectoryPrefab(new DirectoryInfo(UIPrefabPath));

//提取CS中的中文
staticWriteText +="----------------Script----------------------\n";
LoadDiectoryCS(new DirectoryInfo(ScriptPath));


//終於把提取的中文生成出來
string textPath = OutPath;
if (System.IO.File.Exists (textPath))
{
File.Delete (textPath);
}
using(StreamWriter writer = new StreamWriter(textPath, false, Encoding.UTF8))
{
writer.Write(staticWriteText);
}
AssetDatabase.Refresh();
}

//遞歸全部UI Prefab
static public void LoadDiectoryPrefab(DirectoryInfo dictoryInfo)
{
if(!dictoryInfo.Exists) return;
DirectoryInfo []chindDictoryInfos = dictoryInfo.GetDirectories();
foreach(DirectoryInfo chindDictoryInfo in chindDictoryInfos)
{
LoadDiectoryPrefab(chindDictoryInfo);
}
FileInfo[] fileInfos = dictoryInfo.GetFiles("*.prefab", SearchOption.AllDirectories);
foreach (FileInfo files in fileInfos)
{
string path = files.FullName;
string assetPath = path.Substring(path.IndexOf("Assets/"));
GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)) as GameObject;
GameObject instance = GameObject.Instantiate(prefab) as GameObject;
SearchPrefabString(instance.transform);
GameObject.DestroyImmediate(instance);
}
}

//遞歸全部C#代碼
static public void LoadDiectoryCS(DirectoryInfo dictoryInfo)
{

if(!dictoryInfo.Exists) return;
DirectoryInfo []chindDictoryInfos = dictoryInfo.GetDirectories();
foreach(DirectoryInfo chindDictoryInfo in chindDictoryInfos)
{
LoadDiectoryPrefab(chindDictoryInfo);
}
FileInfo[] fileInfos = dictoryInfo.GetFiles("*.cs", SearchOption.AllDirectories);
foreach (FileInfo files in fileInfos)
{
string path = files.FullName;
string assetPath = path.Substring(path.IndexOf("Assets/"));
TextAsset textAsset = AssetDatabase.LoadAssetAtPath(assetPath, typeof(TextAsset)) as TextAsset;
string text = textAsset.text;
//用正則表達式把代碼裏面兩種字符串中間的字符串提取出來。
Regex reg = new Regex("StrUtil.GetText\\(\".*?\"");
MatchCollection mc = reg.Matches(text);
foreach(Match m in mc)
{
string format = m.Value;
format = format.Replace("StrUtil.GetText(\"","");
format = format.Replace("\"","");
if(!Localization.Contains(format) && !string.IsNullOrEmpty(format)){
Localization.Add(format);
staticWriteText+=format+"\n";
}
}
}
}

//提取Prefab上的中文
static public void SearchPrefabString(Transform root)
{
foreach(Transform chind in root)
{
//由於這裏是寫樣例,所以我用的是UILabel
//這裏應該是寫你用於圖文混排的腳本。
UILabel label = chind.GetComponent<UILabel>();
if(label != null)
{
string text = label.text;
if(!Localization.Contains(text) && !string.IsNullOrEmpty(text)){
Localization.Add(text);
text = text.Replace("\n",@"\n");
staticWriteText+=text+"\n";
}
}
if(chind.childCount >0)
SearchPrefabString(chind);
}
}
}

比方這個是個簡單界面上賦值的代碼。用StrUtil.GetText()去取中文。StrUtiL類是我們自己寫的。

using UnityEngine;
using System.Collections;
public class UIMain : MonoBehaviour
{
private UILabel mName = null;
void Awake ()
{
mName = transform.Find("name").GetComponent<UILabel>();
mName.text = StrUtil.GetText("雨松MOMO\n我要換行");
mName.text = StrUtil.GetText("我是{0}我的網名{1}","宣雨松","雨松MOMO");
}
}

StrUtiL類裏面去處理Key從本地數據表裏中替換相應多語言顯示的文字。

using UnityEngine;
using System.Collections;

public class StrUtil
{
static public string GetText( string text)
{
//通過傳進來的中文KEY 去數據表裏面讀相應替換的多語言文字
return text;
}

static public string GetText(string text,params object[] args)
{
//通過傳進來的中文KEY 去數據表裏面讀相應替換的多語言文字
return string.Format(text,args);
}
}

使用工具代碼提取,終於將全部多語言中文的地方提取在txt裏面。

技術分享

最後就是讓策劃拿著生成出來的中文KEY在Excel表裏。給出相應的翻譯文字。

另一個重要的知識點就是換行問題,可能你在Prefab上進行的換行的操作,可是\n並非字符串。所以我們要把\n轉成”\n”字符串寫進去。

text.Replace(“\n”,@”\n”);

反過來在讀取表的時候還是須要再把”\n”字符串轉成\n換行符

text.Replace(@”\n”,”\n”);

這樣就沒問題了。策劃也能夠直接在數據表裏填寫\n來進行換行了。

最後的思考

1.開發的過程中可能要改動代碼或者要加新功能刪功能,所以我們要把差異性的中文Key提取出來,也就是把新添加的KEY 或者 新刪除的KEY列舉出來。

由於沒有變化的就不須要策劃又一次翻譯了。

2.最好能直接幫策劃生成Excel文件。Windows上非常easy。可是MAC就不行。我知道怎麽在Mac上讀取excel文件。可是我不知道在mac上怎麽生成Excel有哪位大神知道還請告知一下我。

要能生成.xlsx的那種。謝謝啦。

3.由於要做圖文混排,所以UILabel我已經不直接使用了,而是又寫了一個類去管理UILable和UISprite, 事實上就是依據XML或者JSON 一類的描寫敘述符去動態生成UILable和UISprite在幫它的動態的算坐標,算間距 一類的。

由於你的中文KEY須要傳參數 比方 “我叫{0}我今年{1}大了” 一類的字符串。所以還是在寫一個方法。

最後是本文的

p=1014">下載地址,事實上本文主要還是提供一個思路。 假設你有對多語言更好的建議,或者是辦法。歡迎在以下給我留言,謝謝。


Unity3D研究之多語言用中文做KEY