• Unity3D研究之多语言用中文做KEY


    

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

    对PoolManager不了解的能够看下初探PoolManager插件非常适合新手学习。

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

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

    1.遍历全部UIPrefab把包括UILabe(或者是你自己写的)组件找出来,而且把文字提取出来。

    2.遍历全部的CS代码。把全部 StrUtil.GetText(成功智慧网 我要换行); 双引號中间的中文以及字符全部提取出来。

    直接上思路代码。

    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---------------------- ";
      LoadDiectoryPrefab(new DirectoryInfo(UIPrefabPath));
      
      //提取CS中的中文
      staticWriteText +="----------------Script---------------------- ";
      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+" ";
        }
       }
      }
     }

        //提取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(" ",@" ");
         staticWriteText+=text+" ";
        }
       }
       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 我要换行");
      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里面。

    Unity3D研究之多语言用中文做KEY(七十六) - 第1张  | 成功智慧网-专注游戏编程开发!

    最后就是让策划拿着生成出来的中文KEY在Excel表里。给出相应的翻译文字。

    另一个重要的知识点就是换行问题,可能你在Prefab上进行的换行的操作,可是 并非字符串。所以我们要把 转成” ”字符串写进去。

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

    反过来在读取表的时候还是须要再把” ”字符串转成 换行符

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

    这样就没问题了。策划也能够直接在数据表里填写 来进行换行了。

    最后的思考

    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}大了” 一类的字符串。所以还是在写一个方法。

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


  • 相关阅读:
    深入剖析Java中的装箱和拆箱
    JDBC(1)
    设计模式
    MySQL学习笔记(3)
    MySQL学习笔记(2)
    MySQL学习笔记(1)
    tomcat 部署项目出现Error thrown in preDeregister method
    JSP页面中的request.getContextPath()出现“ .... .. refers to the missing type String
    myEclipse 导入 jquery包为什么整个项目都会报错
    走楼梯
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7163292.html
Copyright © 2020-2023  润新知