unity 英汉版本互转 中文做key

做多语言的时候用中文做KEY绝对是有100%的好处,如果用英文表示那么代码里面给文字赋值的地方全都是英文,写的代码多了以后维护起来就没有人能看懂了,或者看起来很费劲。

说说用中文做KEY的原理:Unity中给文字赋值的地方就两处, 一个是提前预制在UI Prefab上的文字,还有一个是写在代码里面的文字。那么在开发阶段我们在Prefab和代码里面直接就写中文,等项目后期通过工具把所有中文的地方全部提取出来。然后把提取出来的中文交给策划,让策划他们去翻译去,这样我们之前写的中文就是多语言的KEY,最终显示的界面上的文字是用这个中文KEY读表读出来的。

NGUI里所有的文字都是在UILabel中,可是我们要做图文混排,一般都是在UILabel上在拓展一个自己的脚本,用这个脚本在生成对应的UILabel和UISprite。这篇文章我就先以UILabel来说明原理。

1.遍历所有UIPrefab把包含UILabe(或者是你自己写的)组件找出来,并且把文字提取出来。

2.遍历所有的CS代码,把所有 StrUtil.GetText(雨松MOMO\n我要换行); 双引号中间的中文以及字符全部提取出来。

直接上思路代码。



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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 ;
         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 ;
         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类是我们自己写的。

StrUtiL类里面去处理Key从本地数据表里中替换对应多语言显示的文字。

使用工具代码提取,最终将所有多语言中文的地方提取在txt里面。

Unity3D研究院之多语言用中文做KEY(七十五) - 雨松MOMO程序研究院 - 1 最后就是让策划拿着生成出来的中文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}大了” 一类的字符串,所以还是在写一个方法。

最后是本文的下载地址,其实本文主要还是提供一个思路。 如果你有对多语言更好的建议,或者是办法,欢迎在下面给我留言,谢谢。

http://pan.baidu.com/s/1pJmGbzl


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值