在WinForm应用程序中快速实现多语言的处理的方法

作者:伍华聪 时间:2023-07-26 10:39:55 

在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化。在Winform应用程序中实现多语言也有常规的处理方式处理,不过需要针对每个语言版本,重新修改Winform界面的显示,对一些常规的辅助类,也需要引入一个统一的资源管理类来处理多语言的问题,相对比较繁琐。本篇随笔针对多语言的需求,希望尽量避免繁琐的操作,既能符合本地语种开发人员的开发习惯,又能快速实现Winform程序的多语言场景处理。

1、多语言开发的困惑和思路

在常规的多语言版本程序中,开发总是伴随着很多不愉快的事情,大概列举一些仅供参考:

1)对窗体的多语言处理时,维护多个语言版本的界面非常繁琐;

2)多语言处理的时候,以资源参照的时候,默认键值为一些英文字符串或者单词,不太符合如中文语境的开发,调整代码则需要很多工作量;

3)对于已开发好的程序,全面引入多语言的处理代码,需要大量修改;

4)对于大量中文的多语言处理,工作量望而却步;

5)对于常规Resx文件的处理觉得繁琐

6)缺乏一个统一处理多语言需求的方案

在多语言的处理上,我一直希望找出一种高效的处理方式,由于我的Winform开发框架中很多模块是现成的,希望能够使用继承处理的方式,实现最简化的处理;

同时大量中文的英文(针对英文版本)翻译也是一个头痛的事情,突然想到百度的翻译API接口可以利用,那么我们可以利用翻译接口实现开始的翻译,然后对资源进行一定的调整则可以提高效率和准确率。

对于编辑和承载多语言的信息,我一直觉得JSON格式挺好的,可以利用它序列化为字典集合,通过字典获取对应键值的多语言版本字符串也是很高效的一种方式,那么就决定用JSON来存储多语言信息了,易读好用。

对于多余的处理逻辑,尽量封装为独立的模块,可以在多个模块中进行调用处理。

2、多语言的处理实现

在思考多语言的合理处理方案过程中,参考了另一位博友的文章《分享两种实现Winform程序的多语言支持的解决方案》,思路有点符合我的期望,因此吸收了一些处理思想进行处理,目的就是提高开发效率。

1)多语言的信息存储和加载

首先,我们来看看多语言处理的目录和格式问题,目录大概是根据多语言的简称进行放置,如下所示。

在WinForm应用程序中快速实现多语言的处理的方法

这个目录就是会输出到debug或者Release的运行目录中,我们就是根据相对于运行目录进行资源读取即可,所有模块共用同一的多语言文件,我们可以把各个模块基础通用的多语言文件放在Basic.json文件中,也可以根据模块独立起名,主程序如TestMultiLanguage的多语言文件我则放在TestMultiLanguage.json文件中。实际上目录名称是为了区分而已,程序加载的时候,会把目录下面所有的JSON文件进行加载,读取里面的键值作为资源的字典参照。

多语言的JSON文件是标准的Json格式,只是我们只用键值的字典参考即可,不需要使用复杂的JSON对象格式,如下是basic.json文件的部分内容。

在WinForm应用程序中快速实现多语言的处理的方法

这些资源文件采用中文-英文的参照方式,我们以我们常规的母语开发,即使我们不做多语言,也不影响代码的正常处理,我们只需要把窗体上和代码里面的中文提取出来,然后进行多语言处理(如变为英文)即可。

由于我们使用键值字典对象的JSON内容,那么我们就可以把这些内容序列号为字典集合,如下代码我们可以通过 JSON.NET 组件把它们序列化为字典集合,这些字典集合就是我们用来做多语言的关键。


var content = File.ReadAllText(file, Encoding.UTF8);
     if (!string.IsNullOrEmpty(content))
     {
       var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(content);
       foreach (string key in dict.Keys)
       {
         //遍历集合如果语言资源键值不存在,则创建,否则更新
         if (!resources.ContainsKey(key))
         {
           resources.Add(key, dict[key]);
         }
         else
         {
           resources[key] = dict[key];
         }
       }
     }

加载多语言处理的时候,我们遍历相对目录下的lang/***里面的文件即可实现多语言信息的加载,如下代码所示。


/// <summary>
   /// 根据语言初始化信息。
   /// 加载对应语言的JSON信息,把翻译信息存储在全属性resources里面。
   /// </summary>
   /// <param name="language">默认的语言类型,如zh-Hans,en-US等</param>
   private void LoadLanguage(string language = "")
   {
     if (string.IsNullOrEmpty(language))
     {
       language = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
     }

this.resources = new Dictionary<string, string>();
     string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("lang/{0}", language));
     if (Directory.Exists(dir))
     {
       var jsonFiles = Directory.GetFiles(dir, "*.json", SearchOption.AllDirectories);
       foreach (string file in jsonFiles)
       {
         LoadFile(file);
       }
     }
   }

我们把多语言的加载和翻译处理,放在一个独立的项目上,如我定义为框架的一个模块:WHC.Framework.Language

这样我们在各个模块中使用多语言处理过程的时候,包含这个模块就可以了。

2)多语言信息的翻译

做多语言的版本程序,翻译工作也是一个繁琐的工作,如果你是非常精通各种语言(如中文、英文、日文等等),那当然不在话下,不过我们做开发的多少也是会一些的,如英语吧,即时不能非常准确,那么也可以做到差不多,但是做这个还是累,还容易敲打错别字,那么用第三方提供的翻译API来预处理后调整,结果就简化很多了,可以极大提高效率的。

这里以我们经常使用的百度翻译来实现(用Google翻译也可以,增加接口实现即可)

百度翻译接口的使用,你先注册一个开发账户,获得相应的秘钥信息就可以使用免费的翻译接口了(http://api.fanyi.baidu.com/api/trans/product/index)。

在WinForm应用程序中快速实现多语言的处理的方法

有了这些准备后,就可以利用C#代码进行翻译处理了。

百度翻译的接口处理代码如下所示。


/// <summary>
   /// 百度接口翻译
   /// </summary>
   /// <param name="inputString">输入字符串</param>
   /// <param name="from">源内容语言</param>
   /// <param name="to">目标语言</param>
   /// <returns></returns>
   private static string BaiduTranslate(string inputString, string from = "zh", string to = "en")
   {
     string content = "";

string appId = "你的APPID";
     string securityId = "你的秘钥";
     int salt = 0;

StringBuilder signString = new StringBuilder();
     string md5Result = string.Empty;
     //1.拼接字符,为了生成sign
     signString.Append(appId);
     signString.Append(inputString);
     signString.Append(salt);
     signString.Append(securityId);

//2.通过md5获取sign
     byte[] sourceMd5Byte = Encoding.UTF8.GetBytes(signString.ToString());
     MD5 md5 = new MD5CryptoServiceProvider();
     byte[] destMd5Byte = md5.ComputeHash(sourceMd5Byte);
     md5Result = BitConverter.ToString(destMd5Byte).Replace("-", "");
     md5Result = md5Result.ToLower();

try
     {
       //3.获取web翻译的json结果
       WebClient client = new WebClient();
       string url = string.Format("http://api.fanyi.baidu.com/api/trans/vip/translate?q={0}&from=zh&to=en&appid={1}&salt={2}&sign={3}", inputString, appId, salt, md5Result);
       byte[] buffer = client.DownloadData(url);
       string result = Encoding.UTF8.GetString(buffer);

var trans = JsonConvert.DeserializeObject<TranslationJson>(result);
       if (trans != null)
       {
         content = trans.trans_result[0].dst;
         content = StringUtil.ToProperCase(content);
       }
     }
     catch(Exception ex)
     {
       Debug.WriteLine(ex);
     }
     return content;
   }

其中把JSON转换为类对象需要两个类,对翻译结果进行转换,如下代码所示。


internal class TranslationJson
 {
   public string from { get; set; }
   public string to { get; set; }
   public List<TranslationResult> trans_result { get; set; }
 }
 internal class TranslationResult
 {
   public string src { get; set; }
   public string dst { get; set; }
 }

这样我们在多语言处理的时候,可以对默认输入为空的键值进行翻译即可(如英文翻译)。


//遍历集合进行翻译
 var value = dict[key];
 if (string.IsNullOrWhiteSpace(value))
 {
   //如果值为空,那么调用翻译接口处理
   var newValue = TranslationHelper.Translate(key, from, to);
   if (!string.IsNullOrWhiteSpace(newValue))
   {
     dict[key] = newValue;
   }
 }

然后重新更新我们的资源文件就可以了


//不排序
 var newContent = JsonConvert.SerializeObject(dict, Formatting.Indented);

File.WriteAllText(file, newContent, Encoding.UTF8);

如果需要对键值进行排序,那么使用SortDictionary进行包装下即可


//进行排序
 SortedDictionary<string, string> sortedDict = new SortedDictionary<string, string>(dict);
 var newContent = JsonConvert.SerializeObject(sortedDict, Formatting.Indented);

在多语言处理的时候,我们一般不必要一次填写完毕中英文对照的资源,我们可以先把字典键值的键写出来,值保留为空,如下文件所示。

在WinForm应用程序中快速实现多语言的处理的方法

运行程序的时候,让翻译的接口先行翻译,然后我们再对翻译的资源进行调整,适应我们程序的语境即可,翻译后的内容后如下所示。

在WinForm应用程序中快速实现多语言的处理的方法

来源:http://www.cnblogs.com/wuhuacong/p/9007270.html

标签:WinForm,多语言
0
投稿

猜你喜欢

  • Java操作Redis详细介绍

    2023-07-27 06:53:04
  • Android用动画显示或隐藏视图

    2023-08-05 20:07:25
  • C#探秘系列(一)——ToDictionary,ToLookup

    2023-04-19 09:16:15
  • C#遍历系统进程的方法

    2021-09-24 15:35:29
  • C#多线程异步执行和跨线程访问控件Helper

    2022-02-09 12:24:32
  • Java BIO,NIO,AIO总结

    2022-02-07 01:48:28
  • Andriod 资源文件之存取操作

    2021-11-22 09:26:52
  • 一次Jvm old过高的排查过程实战记录

    2023-05-07 23:33:49
  • C#获取日期的星期名称实例代码

    2022-10-22 13:25:53
  • C# VB 实现10进制 16进制之间互相转换

    2023-06-24 14:22:55
  • Java校验银行卡是否正确的核心代码

    2022-01-28 19:53:29
  • C#利用异或算法实现加密解密

    2022-08-15 14:48:51
  • Android Studio打包jar及aar包的方法

    2023-06-18 15:59:53
  • Android实现一个完美的倒计时功能

    2022-04-12 11:28:02
  • Android TextView渐变颜色和方向及动画效果的设置详解

    2022-06-13 09:23:58
  • 常见的java面试题

    2023-11-26 18:03:44
  • Spring Boot学习入门之AOP处理请求详解

    2023-11-27 10:55:17
  • Java本地缓存工具之LoadingCache的使用详解

    2023-06-24 11:28:11
  • SpringCloud URL重定向及转发代码实例

    2023-11-19 11:43:18
  • Spring Boot2.x集成JPA快速开发的示例代码

    2022-11-21 04:55:41
  • asp之家 软件编程 m.aspxhome.com