ASP.NET中的几种简体转繁体方法总结
随着公司业务的发展,计划开拓台湾及香港市场,整个平台需要在语言方面支持繁体中文的切换,由此寻找合适的方法转换字体迫切重要。编者尝试很多方法,经验与大家分享,望少走弯路,迎刃解决。
方法一:使用kernel32.dll
ASP中的kernel32.dll 能够实现简单的中文简体和中文繁体相互转换。使用和操作简单易行,但也存在着较大的纰漏:此dll能做到的仅仅是把简体中文字符逐字翻译为繁体中文字符,无法做到根据词意具体分析,比如“日志”翻译为繁体为“日誌”,而在另一个语意里“志气”则翻译为“志氣”。kernel32.dll不会根据上下文分析词义,于是全部机械化翻译为 “志”字。这样的翻译非常不严谨,可能会影响一个企业的形象,无法妥协者慎用。
代码Demo演示
// 首先要引入命名空间
using System.Runtime.InteropServices;
namespace 练习使用Kernel32.dll繁体转化
{
class Program
{
[DllImport("kernel32.dll", EntryPoint = "LCMapStringA")]
public static extern int LCMapString(int Locale, int dwMapFlags, byte[] lpSrcStr, int cchSrc, byte[] lpDestStr, int cchDest);
const int LCMAP_SIMPLIFIED_CHINESE = 0x02000000;
const int LCMAP_TRADITIONAL_CHINESE = 0x04000000;
//转化方法
public static string ToTraditional(string source, int type)
{
byte[] srcByte2 = Encoding.Default.GetBytes(source);
byte[] desByte2 = new byte[srcByte2.Length];
LCMapString(2052, type, srcByte2, -1, desByte2, srcByte2.Length);
string des2 = Encoding.Default.GetString(desByte2);
return des2;
}
static void Main(string[] args)
{
string FanStr = "大戰三國";
string JanStr = ToTraditional(FanStr, LCMAP_SIMPLIFIED_CHINESE); //繁体转简体
Console.WriteLine(JanStr);
string janstr = "大战三国";
string fanstr = ToTraditional(janstr, LCMAP_TRADITIONAL_CHINESE); //简体转繁体
Console.WriteLine(fanstr);
}
}
}
运行结果
方法二:使用Microsoft.VisualBasic.dll
不得不说VB中有些经典的类库还是非常好用的。笔者认为VB类库是最全面的,它里边有很多好用的函数在ASP中没有,比如繁简转换和时间差的计算(现在时间差的计算可以使用两个时间直接相减就可以了,得到的是 TimeSpan结构)。这里所说的Microsoft.VisualBasic.dll就是一个经典的VB类库,它能提供对许多 .NET Framework 类的简单直观的访问,笔者非常喜欢。
但是Microsoft.VisualBasic.dll能做到的繁简转换和kernel32.dll如出一辙,无法做到语意分析。但贵在简单,笔者第一次就是使用的这个方法,被测试团队无情地反驳=.=
这种方法需要引入一个dll,但有的人认为:为了一个小功能引入一个dll,有点过于奢侈。需自行斟酌。
第一步:引入Microsoft.VisualBasic.dll
简单地引入dll后可以写代码了。
代码Demo
//简体转繁体
public static string Fan_TransLate(string str)
{
var resultStr = Microsoft.VisualBasic.Strings.StrConv(str, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, 0);
return resultStr;
}
//繁体转简体
public static string Jan_TransLate(string str)
{
var resultStr = Microsoft.VisualBasic.Strings.StrConv(str, Microsoft.VisualBasic.VbStrConv.SimplifiedChinese, 0);
return resultStr;
}
代码非常简洁,其中**Microsoft.VisualBasic.VbStrConv.枚举值 **枚举值决定转化为哪种类型。0为LocaleID,
如public static string StrConv(string str, VbStrConv Conversion, int LocaleID = 0);系统默认的LocaleID为0。
方法三:使用微软类库Microsoft Visual Studio International Feature Pack 2.0
Microsoft Visual Studio International Feature Pack 2.0包含一组控件和类库,设计用来帮助.NET开发人员创建国际化程序。
下载地址:https://www.microsoft.com/zh-cn/download/details.aspx?id=18970
下载完后:运行文件VSIPSetup.msi 并完成安装 (x86操作系统上的默认安装目录是%SYSTEMDRIVE%\Program Files\Microsoft Visual Studio International Feature Pack 2.0; x64操作系统上的默认安装目录是%SYSTEMDRIVE%\Program Files (x86)\Microsoft Visual Studio International Feature Pack 2.0)
代码Demo
using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
/// <summary>
/// 简体转换为繁体
/// </summary>
/// <param name="str">简体字</param>
/// <returns>繁体字</returns>
public static string GetTraditional(string str)
{
string resultstr = string.Empty;
resultstr = ChineseConverter.Convert(str, ChineseConversionDirection.SimplifiedToTraditional);
return resultstr;
}
/// <summary>
/// 繁体转换为简体
/// </summary>
/// <param name="str">繁体字</param>
/// <returns>简体字</returns>
public static string GetSimplified(string str)
{
string resultstr = string.Empty;
resultstr = ChineseConverter.Convert(str, ChineseConversionDirection.TraditionalToSimplified);
return resultstr;
}
此方法笔者并没有使用,嫌麻烦,并且此方法也只是做了简单的转换,并没有进行语意的分析。与方法二属于换汤不换药的东西,并且这个Microsoft Visual Studio International Feature Pack 2.0包还需要手动下载,费时间,笔者不建议使用。
方法四:利用using Microsoft.Office.Interop.Word;结合词义翻译
利用using Microsoft.Office.Interop.Word可进行词义上的分析,成功的克服了我们所担心的机械硬翻译问题,他的翻译标准和Word里的繁体翻译内容保持一致,拥有一定的可信性,这种方法也是笔者能找到的最恰当的方法了(欢迎补充)。但是此方法有个要求就是服务器环境里必须安装有office,我们调的是office的接口。使用如下:
第一步:添加Microsoft.Office.Interop.Word包
包的下载地址:https://www.nuget.org/packages/Microsoft.Office.Interop.Word/15.0.4797.1003?tdsourcetag=s_pcqq_aiomsg
也可直接在vs环境里添加NeGet包:
第二步:引用Microsoft.Office.Interop.Word; 和 System.Reflection;两个命名空间
using Microsoft.Office.Interop.Word;
using System.Reflection;
第三步:代码Demo
/// <summary>
/// 简体转繁体
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static string CHSToCHT(string src)
{
string des = "";
_Application appWord = new Application();
object template = Missing.Value;
object newTemplate = Missing.Value;
object docType = Missing.Value;
object visible = true;
Document doc = appWord.Documents.Add(ref template, ref newTemplate, ref docType, ref visible);
appWord.Selection.TypeText(src);
appWord.Selection.Range.TCSCConverter(WdTCSCConverterDirection.wdTCSCConverterDirectionSCTC, true, true);
appWord.ActiveDocument.Select();
des = appWord.Selection.Text;
object saveChange = 0;
object originalFormat = Missing.Value;
object routeDocument = Missing.Value;
appWord.Quit(ref saveChange, ref originalFormat, ref routeDocument);
doc = null;
appWord = null;
GC.Collect();//进程资源释放
return des;
}
/// <summary>
/// 繁体转简体
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static string CHTToCHS(string src)
{
string des = "";
_Application appWord = new Microsoft.Office.Interop.Word.Application();
object template = Missing.Value;
object newTemplate = Missing.Value;
object docType = Missing.Value;
object visible = true;
Document doc = appWord.Documents.Add(ref template, ref newTemplate, ref docType, ref visible);
appWord.Selection.TypeText(src);
appWord.Selection.Range.TCSCConverter(WdTCSCConverterDirection.wdTCSCConverterDirectionTCSC, true, true);
appWord.ActiveDocument.Select();
des = appWord.Selection.Text;
object saveChange = 0;
object originalFormat = Missing.Value;
object routeDocument = Missing.Value;
appWord.Quit(ref saveChange, ref originalFormat, ref routeDocument);
doc = null;
appWord = null;
GC.Collect();//进程资源释放
return des;
}
以上便为繁体简体转换的代码,但要特别注意:
_Application appWord = new Microsoft.Office.Interop.Word.Application();和GC.Collect();中
appWord 是个非托管资源,在每一个字段翻译后就调用一次GC.Collect()进行强制垃圾回收。这样存在非常大的性能问题,每次new和GC都会耗费大量资源,翻译速度慢十倍以上。
建议将代码分块:进行
1.初始化非托管资源代码块,放在循环遍历翻译之前。
//初始化非托管资源
appWord = new Microsoft.Office.Interop.Word.Application();
object template = Missing.Value;
object newTemplate = Missing.Value;
object docType = Missing.Value;
object visible = true;
Document doc = appWord.Documents.Add(ref template, ref newTemplate, ref docType, ref visible);
2.循环遍历要翻译的资源,并逐个去调用以下方法翻译。这样避免了每个字段翻译都需要调new和GC,大大提高性能。
//简体转繁体的方法:
public static string CHSToCHT(string src, _Application appWord, Document doc)
{
string des = "";
appWord.Selection.TypeText(src);
appWord.Selection.Range.TCSCConverter(WdTCSCConverterDirection.wdTCSCConverterDirectionSCTC, true, true);
appWord.ActiveDocument.Select();
des = appWord.Selection.Text;
doc = null;
appWord = null;
return des;
}
3.循环翻译完成后,我们在最终调用一次回收托管资源的方法,进行垃圾回收。最好将这个回收代码块放在异常的Finally语句块中,确保每次翻译功能结束都能执行一次垃圾回收。
//关闭非托管资源
object saveChange = 0;
object originalFormat = Missing.Value;
object routeDocument = Missing.Value;
appWord.Quit(ref saveChange, ref originalFormat, ref routeDocument);
GC.Collect();//进程资源释放
通过以上三步的拆分,代码性能和速度都会提高很多。但是当你运行代码时,在
appWord = new Microsoft.Office.Interop.Word.Application();初始化非托管资源时很容易报出如下异常:
检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。 (异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))。
这是由于服务组件权限不够引起的,这个异常网上的解决方法也是众说纷纭,大多都得进控制面板的服务组件修改权限,笔者试完之后并没有什么用。于是把目光放在了IIS身上,修改应用程序池的标识,使其拥有最大权限,就可以消灭此异常。
进入IIS—到自己项目的程序池—右键选择高级设置—修改进程模型下的标识为LocalSystem
修改如下:
这样你的程序就能高效并完美地进行简体繁体转换啦。
但是亲们,一定要注意自家的服务器机器上是否有office,要是没有,这个方法就不能用啦。笔者就是在自己机器上得意忘形,到了服务器上完美失败!收获P1级BUG一枚。
好了这就是我的分享,希望各位小伙伴多多指点!
小石分享: