对于有跨国业务的web系统来说,一般都需要提供多语言功能。然而在众多多语言方案里,如.net自带的Resource方式,都会在程序开发时增加程序员的额外负担,不易开发:
1.各种不同的地方实现多语言,如aspx的control绑定,js脚本,cs代码,procedure里的提示信息等,这些多语言实现方式各不相同,加重了开发难度。
2.在要实现多语言的代码中都要与获取语系文字的代码进行强耦合,不方便扩展和维护。如.net的Resource方式某个label实现多语言:
lblName.Text = Resources.Strings.name;
3.开发和维护程序时,程序员都必须同时打开source code和多语言资源文件,特别是在多人开发时,共享一个多语言文件,且对于共享的文字实难处理和同步。
以上这些只是简单地罗列了一下传统多语言开发时的困扰,那有什么方式解决这些问题,轻松实现多语言功能呢?
记得有人说过web编程,实际上就是字符串处理。
为什么呢?因为web,实际上就是Request和Response,而Request和Response就是字符串。在我们各种程序里,最终输出到Browser的都是html格式的字符串,因此,只要我们统一在程序最后一步输出html格式时,能够识别其中需要进行多语言转换的文字,将将其替换为当前设定的语言版本的文字就可以了。
在asp.net中,因为有一个Response.Filter的属性,让这一切变得很简单。
什么是Response.Filter?
简单地说,就是在经过层层转换后,最终asp.net要输出html,在输出的过程中,是将html放到一个管道(pipeline)里,然后在管道那头取出要发往客户端的html进行Response,asp.net提供Response.Filter属性,让你可以对经过的html进行相应的转换。
因此只要将多语言转换功能放在这里,并识别“中文”,将其转换为user设定的相应语系就可以完成了。
1. 首先要实现一个多语言Stream:
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
public class HttpMulLangStream : Stream
{
private Stream strSink;
private long lngPosition;
public HttpMulLangStream(Stream sink)
{
strSink = sink;
}
// The following members of Stream must be overriden.
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return 0; }
}
public override long Position
{
get { return lngPosition; }
set { lngPosition = value; }
}
public override long Seek(long offset, System.IO.SeekOrigin direction)
{
return strSink.Seek(offset, direction);
}
public override void SetLength(long length)
{
strSink.SetLength(length);
}
public override void Close()
{
strSink.Close();
}
public override void Flush()
{
strSink.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return strSink.Read(buffer, offset, count);
}
// 关键代码.
public override void Write(byte[] buffer, int offset, int count)
{
//读出写的文字
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string inputstring = Encoding.UTF8.GetString(data);
//找出汉字(对于复杂一些的,可以设定固定识别方式,如使用这些标记识别[@多语言文字],并按设定的语言作转换
inputstring = Regex.Replace(inputstring, "[\u3000-\u9fff]+", new MatchEvaluator(capText));
//将翻译后的语言写入response
byte[] newdata = Encoding.UTF8.GetBytes(inputstring);
strSink.Write(newdata, 0, newdata.Length);
}
private string capText(Match m)
{
//简单的替换,实际开发过程可以从xml文件,Resouce资源