不需要了解任何底層知識,就可以漢化!Let`s go!!!


漢化?莫要被這兩個字嚇到。

其實你也可以漢化,跟着我的步驟來,你也可以進行漢化,Let`s go!!!(大鳥飄過)

 

這里漢化的是微軟企業類庫的配置管理工具EntLibConfig.exe。當然,這里的企業類庫是3.0版本的。

准備工作:

      你需要下載Entprise Library,然后找到配置管理工具EntLibConfig.exe。

      將EntLibConfig.exe及其依賴的文件放置在D:\el目錄下

如果不想下載微軟企業類庫,也沒有關系,這里的方法還是適用的。

 首先看一下,要漢化的軟件界面:

 

漢化后的界面(部分):

1.第一步 反匯編EntLibConfig.exe文件

首先,在開始菜單中找到visual studio 命令行工具,然后進入,如下圖:

 

進入visual studio命令行工具后,輸入如下命令行:

d:

cd  el

ildasm /out:el.il EntLibConfig.exe

第一行命令轉到d盤。

第二行命令,進入d:\el目錄

第三行調用ildasm反匯編器,並為其傳遞兩個參數:/out:el.il  EntLibConfig.exe。此時,ildasm反匯編器會將EntLibConfig.exe文件反匯編成il文件。此時你會在d:\el下發現如下文件:

 

這個文件中就包含了EntLibConfig中菜單的資源,換句話說,菜單中的英文字母都在這個文件里,因此,我們的目標就是找到這些英文單詞,然后一一替換成中文即可。

 

第二步:將.resource中的資源提取到一個文本文件中

注:微乳並沒有公開 .resources文件中的資源格式,因此要想讀取或者寫入,必須借助於.net中的System.Resources.ResourceReader和System.Resources.ResourceWriter類。我已經將他們進行了封裝,並且形成一個名為rsc的命令行工具。你可以使用這個工具來將.resources文件中的資源提取到一個文本文件中,並可以將這個文本文件中的資源在寫會到.resoruce文件。

  在本文的最后,我將貼出這個工具的代碼。

 

首先,使用rsc命令行工具將.resoruce文件中的資源提取到一個文本文件中。輸入如下命令(復制):

rsc Microsoft.Practices.EnterpriseLibrary.Configuration.Console.MainForm.resources  r  r.txt

然后,.resource文件中的資源就被提取到了r.txt文本文件中。

 

然后,使用記事本打開r.txt文件,在記事本的查找一欄里搜索Action,最終定位到第204行,如下圖所示:

 

這個&Action字符串就是菜單中的那個Action選項,只需要將其替換成中文即可。我們將其替換為“操作”,如下:

 

 

保存文件。

然后再次使用rsc命令行工具,將r.txt保存到Microsoft.Practices.EnterpriseLibrary.Configuration.Console.MainForm.resources中。請輸入如下命令:

rsc   r.txt    w    Microsoft.Practices.EnterpriseLibrary.Configuration.Console.MainForm.resources

此時,r.txt中的資源已經被寫會到Microsoft.Practices.EnterpriseLibrary.Configuration.Console.MainForm.resources文件中。

 

第三步,重新編譯。

首先,使用ilasm編譯器將el.il重新編譯成exe文件。請輸入如下命令行:

ilasm  /out:good.exe   el.il

這個命令行調用ilasm編譯器,然后為其傳遞兩個參數:/out:good.exe和el.il。ilasm編譯器將el.il文件編譯成good.exe。

 

現在,漢化已經完成。

打開good.exe,你會驚奇的發現Action已經被替換成了"操作",如下:

 

怎么樣,是不是很有成就感!

閱讀到此,相信你依然會有很多疑問,譬如我怎么知道資源就在Microsoft.Practices.EnterpriseLibrary.Configuration.Console.MainForm.resources文件中,為什么第204行的那個Action就是菜單中的那個Action........這篇文章的目的不是讓你徹底了解漢化,只是給你一個大概的思路。

 

上面用到了rsc工具。這個工具的代碼如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Resources;

namespace Wbs
{
    public class ResourceHelper
    {
        private ResourceHelper()
        {}

        /// <summary>
        /// 從指定的資源文件中讀取資源
        /// </summary>
        /// <param name="fileName">要讀取的資源文件</param>
        /// <returns>讀取到的資源</returns>
        public static Dictionary<int,Resource> GetResources(string fileName)
        {
            ResourceReader reader = new ResourceReader(fileName);
            System.Collections.IDictionaryEnumerator resourceIterator= reader.GetEnumerator();
            Dictionary<int, Resource> resources = new Dictionary<int, Resource>();
            int resourceID = 0;
            while (resourceIterator.MoveNext())
            {
                Resource newResource = new Resource(resourceID,(string)resourceIterator.Key, resourceIterator.Value,resourceIterator.Value.GetType());
                resources.Add(resourceID,newResource);
                resourceID++;
            }
            reader.Close();
            return resources;
        }

        /// <summary>
        /// 將資源寫入到指定的文件中。
        /// </summary>
        /// <param name="fileName">要寫入到的資源文件</param>
        /// <param name="resources">被寫入的資源</param>
        public static void WriteResources(string fileName, IEnumerable<Resource> resources)
        {
            if (File.Exists(fileName))
                File.Delete(fileName);
            ResourceWriter writer = new ResourceWriter(fileName);
            foreach (Resource eachResource in resources)
            {
                writer.AddResource(eachResource.Key, eachResource.Value);
            }
            writer.Close();
        }
    
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Text;

namespace Wbs
{
    public class Resource
    {
        int id;
        string key;
        object value;
        Type resourceType;

        public int ID
        {
            get { return this.id; }
            set { this.id = value; }
        }

        public string Key
        {
            get { return this.key; }
            set { this.value = value; }
        }

        public object Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public Type ResourceType
        {
            get { return this.resourceType; }
            set { this.resourceType = value; }
        }

        public Resource(int id,string key, object value,Type resourceType)
        {
            this.id = id;
            this.key = key;
            this.value = value;
            this.resourceType = resourceType;
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Wbs;

namespace rsc
{
    class Program
    {
        static void Main(string[] args)
        {
            if(args.Length ==0)
            {
                Console.WriteLine("假設要漢化a.resource資源文件,請參考如下步驟實現(注:只能漢化字符串資源,如果想要漢化字體顏色等資源請....自己弄去。)");
                Console.WriteLine("第一步:從a.resource中提取資源到r.txt中,請輸入如下命令行:rsc a.resource r r.txt");
                Console.WriteLine("第二步:修改r.txt中需要漢化的資源");
                Console.WriteLine("第三步:從r.txt中將資源寫會到a.resource中,請輸入如下命令行:rsc a.resource w r.txt");
                return;
            }
            string fileName = args[0];
            string readOrWrite = args[1];
            string outputFile = fileName;
            if (args.Length == 3)
            {
                outputFile = args[2];
            }


            if (readOrWrite == "r")
            {
                Dictionary<int,Resource> resources = ResourceHelper.GetResources(fileName);
                WriteTextTo(outputFile, resources);
                Console.WriteLine("已將資源以文本形式寫入到{0}中",outputFile);
                return;
            }

            if (readOrWrite == "w")
            {
                Dictionary<int ,Resource>originalResources= ResourceHelper.GetResources(fileName);
                IEnumerable<Resource> resourceNew = ReadFrom(outputFile);
                ChangeResource(originalResources, resourceNew);
                ResourceHelper.WriteResources(fileName,originalResources.Values);
                Console.WriteLine("已經資源寫入到{0}中",fileName);
                return;
            }
        }
        /// <summary>
        /// 將資源以文本形式寫入到指定的文件
        /// </summary>
        /// <param name="fileName">要將資源寫入到的文件</param>
        /// <param name="resources">資源</param>
        private static void WriteTextTo(string fileName,Dictionary<int,Resource> resources)
        {
            
            System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs,Encoding.UTF8);
            StringBuilder resourceTextBuilder = new StringBuilder();
  
            foreach (var eachResource in resources)
            {
                resourceTextBuilder.AppendFormat("{0},{1},{2}\r\n", eachResource.Key,eachResource.Value.Key, eachResource.Value.Value);            
            }
            sw.WriteLine(resourceTextBuilder.ToString());
            sw.Close();
        }

        /// <summary>
        /// 從指定的資源文本文件中讀取資源。
        /// </summary
        /// <param name="fileNameForText">資源文本文件名</param>
        /// <returns>返回一個資源集合</returns>
        private static IEnumerable<Resource> ReadFrom(string fileNameForText)
        {
            FileStream fs = new FileStream(fileNameForText, FileMode.Open, FileAccess.Read);
            StreamReader reader = new StreamReader(fs,Encoding.Default);
            string line;
            List<Resource> resources = new List<Resource>();
            while ((line = reader.ReadLine()) !="")
            {          
                int resourceID =Convert.ToInt32( line.Substring(0, line.IndexOf(',')));
                string keyvValuePair = line.Substring(line.IndexOf(',') + 1);
                string key=keyvValuePair.Substring(0,keyvValuePair.IndexOf(','));
                string value=keyvValuePair.Substring(keyvValuePair.IndexOf(',')+1);
                Resource newResource = new Resource(resourceID,key,value,null);
                resources.Add(newResource);
            }

            return resources;
        }

        /// <summary>
        /// 將資源修改為指定的資源
        /// </summary>
        /// <param name="originalResource">要修改的資源</param>
        /// <param name="resourceNew">要將資源修改成的新資源</param>
        private static void ChangeResource(Dictionary<int, Resource> originalResource, IEnumerable<Resource> resourceNew)
        {
            foreach (Resource eachResource in resourceNew)
            {
                if(originalResource[eachResource.ID].ResourceType.FullName=="System.String")
                    originalResource[eachResource.ID].Value = eachResource.Value;
            }
        }
    }
}
View Code

 

總結:

    可以先將要漢化的程序集,通過ildasm反匯編器將其反匯編,此時會生成一堆.il文件和.resource文件。你可以在.resource文件中找到要替換的英文。

    由於.resource文件的內部結構時不公開的,但是可以通過System.Resources.ResourceReader和System.Resources.ReousrceWriter來讀取和寫入.resource文件(通過研究這兩個類的源碼,也可以知道.resoruce文件的內部布局),當然,你可以使用我封裝好的rsc工具來讀取和寫入.resource文件。

    使用rsc文件將.resoruce文件中的資源提取到一個文本文件中,然后搜索要漢化的字符差,將其替換成中文,最后在使用rsc將其保存到源文件中。

    到此為止,漢化以基本完成。此時使用ilasm匯編器將生成的il文件重新編譯,漢化完成!!

   

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM