Unity3D研究之多语言用中文做KEY
来源:互联网 发布:实木颗粒板 知乎 编辑:程序博客网 时间:2024/05/22 14:39
做多语言的时候用中文做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上很容易,但是MAC就不行。我知道怎么在Mac上读取excel文件,但是我不知道在mac上怎么生成Excel有哪位大神知道还请告知一下我。要能生成.xlsx的那种,谢谢啦。
3.因为要做图文混排,所以UILabel我已经不直接使用了,而是又写了一个类去管理UILable和UISprite, 其实就是根据XML或者JSON 一类的描述符去动态生成UILable和UISprite在帮它的动态的算坐标,算间距 一类的。因为你的中文KEY需要传参数 比如 “我叫{0}我今年{1}大了” 一类的字符串,所以还是在写一个方法。
最后是本文的下载地址,其实本文主要还是提供一个思路。 如果你有对多语言更好的建议,或者是办法,欢迎在下面给我留言,谢谢。
- Unity3D研究之多语言用中文做KEY
- Unity3D研究院之多语言用中文做KEY
- Unity3D研究院之多语言用中文做KEY(七十五)
- 【Unity3D游戏开发】之多语言缩写对应表 (十五)
- unity 英汉版本互转 中文做key
- CMap在用CString做key方法
- Python 3 之多线程研究
- java之多线程研究(一)
- 做研究
- 利用R语言做可重复性报告研究
- iOS开发之多语言
- Android之多语言设置
- ThinkPHP5之多语言切换
- Thinkphp5之多语言
- ThinkPhp5之多语言笔记
- Thinkphp5之多语言
- 我用Unity3d做游戏(一)
- Unity3D 项目用 git 做版本控制
- Oracle 列合并
- JS判断变量是否为空
- HDU - 3530 Subsequence
- ajax和json跟java实现List、Map直接传递
- 图揭娱圈新一代丑萌代表甜馨黑脸曹格女儿Grace天生喜感
- Unity3D研究之多语言用中文做KEY
- myeclipse的debug模式启动项目超慢解决方案
- UVA 10154 Weights and Measures
- 创建不可删除的IE快捷方式图标
- <7.25>新的启航 Android学习笔记(五)
- 一些简单的dos命令
- swift
- Codeforces 451D Count Good Substrings
- Android如何完全调试framework层代码