现在ASP.NET MVC 已经出了第四版了,现在多了很多特性,但是如何在 ASP.NET MVC 下方便的实现多语言特性呢?
就一个网站的多语言特性来说,我认为分为两个方面:
1、HTML界面上显示的文字需要多语言
2、HTML界面上JS输出的文字需要多语言
原来在HTML部分直接写的文字都不能直接写要输出的文字,而是要采用标记的方法来替换。JS也是同理。
那么在MVC下怎么能透明的实现多语言呢?所谓透明的实现是指,程序员在开发程序当中,不需要过多的考虑多语言的问题,直接调用一个方法就能实现多语言,而且所要用到的语言文件每个语言一个文件就够了,集中翻译这个语言就完成了多语言的功能。
例如
<html>
<head>
</head>
<body>
多语言输出的文字 //这里就不能直接写中文了,一个好方法是 直接用 <%= Html.Lang("string1") %> 来进行输出
</body>
</html>
这里<%= Html.Lang("clickme") %> 是对 HTMLHelper 进行了扩展,增加了一个 Lang 的方法,参数是需要翻译的资源字符串的Name。
怎么为 HTMLHelper 进行扩展?下面这个类就是增加了的扩展类
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Globalization;
using System.Web.Compilation;
using System.Web.Mvc;
using System.Web.Routing;
using ISell.SiteConfig;//引入读入系统配置文件类
using System.Resources;
namespace System.Web.Mvc
{
public static class LocalizationHelpers
{
/// <summary>
/// 在Html页面中调用
/// </summary>
/// <param name="htmlhelper"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string Lang(this HtmlHelper htmlhelper, string key)
{
string FilePath = htmlhelper.ViewContext.HttpContext.Server.MapPath("/") + "LanguegeResource\\";
string str = GetLangString(htmlhelper.ViewContext.HttpContext, key, FilePath).Trim();
return GetLangString(htmlhelper.ViewContext.HttpContext, key, FilePath).Trim();
}
/// <summary>
/// js调用 输出格式为 var str="aa"
/// </summary>
/// <param name="htmlhelper">当前上下文</param>
/// <param name="key">键</param>
/// <returns></returns>
public static string LangOutJsVar(this HtmlHelper htmlhelper, string key, string resourceFileNamePosfix)
{
string FilePath = htmlhelper.ViewContext.HttpContext.Server.MapPath("/") + "LanguegeResource\\";
string langstr = GetLangString(htmlhelper.ViewContext.HttpContext, key, FilePath);
return string.Format("var {0} = '{1}'", key, langstr);
}
/// <summary>
/// 在 C# 后台中使用
/// </summary>
/// <param name="httpContext">当前上下文</param>
/// <param name="key">键</param>]
/// <returns></returns>
public static string InnerLang(HttpContextBase httpContext, string key)
{
string FilePath = httpContext.Server.MapPath("/") + "LanguegeResource\\";
return GetLangString(httpContext, key, FilePath);
}
/// <summary>
/// 根据键,文件路径获取文本值
/// </summary>
/// <param name="httpContext">当前上下文</param>
/// <param name="key">键</param>
/// <param name="FilePath">存放多语言文件的路径</param>
/// <returns></returns>
private static string GetLangString(HttpContextBase httpContext, string key, string FilePath)
{
return LangResourceFileProvider.GetLangString(key, FilePath);
}
}
/// 获取多语言文本值
/// </summary>
public static class LangResourceFileProvider
{
/// <summary>
///
/// </summary>
/// <param name="Key"></param>
/// <param name="langtype"></param>
/// <param name="FilePath"></param>
/// <returns></returns>
/// <summary>
/// 根据键,语言类型,文件路径获取文本值
/// </summary>
/// <param name="Key">键</param>
/// <param name="langtype">语言类型</param>
/// <param name="FilePath">存放多语言文件的路径</param>
/// <returns></returns>
public static string GetLangString(string Key, string FilePath)
{
//从Config配置文件中读取默认的语种
//string defaultLanguege = ISell.SiteConfig.Config.DefaultLanguage.Trim();
//资源文件后缀(例如获取英文资源文件Languege.en_US,则只需要传入en_US即可,如果系统配置文件中没有配置默认的语种则默认取英文语种资源文件)
//string resourceFileNamePosfix = defaultLanguege.Length == 0 ? "en_US" : defaultLanguege;
//string filename = "Languege." + resourceFileNamePosfix + ".resources";
string result = string.Empty;
string filename=Languege.ru_RU;
#region 第一种读取资源文件方式
try
{
using (ResourceSet rr = new ResourceSet(FilePath + filename))
{
result = rr.GetObject(Key, true).ToString();
}
}
catch (Exception)
{
result = Key;
}
#endregion
#region 第二种读取资源文件方式
System.Resources.ResourceReader reader = new System.Resources.ResourceReader(FilePath + filename);
//string resourcetype;
//byte[] resourcedata;
try
{
//reader.GetResourceData(Key, out resourcetype, out resourcedata);
////去掉第一个字节
//byte[] arr = new byte[resourcedata.Length - 1];
//for (int i = 0; i < arr.Length; i++)
//{
// arr[i] = resourcedata[i + 1];
//}
//result = System.Text.Encoding.UTF8.GetString(arr);
}
catch (Exception ex)
{
result = Key;
}
finally
{
reader.Close();
}
#endregion
return result;
}
}
public enum LangType
{
ru_RU,//俄文
en_US//英文
}
}
这个类叫 LocalizationHelpers ,公开了 Lang,LangOutJsVar,InnerLang 三个方法,其中 Lang,LangOutJsVar 可以在 Html 界面中直接调用,InnerLang 可以在C#后台使用。
这里使用了 .resx 资源文件,注意这里这个文件需要被编译后才能使用,否则找不到已经增加的项。编译这个可以使用.NET 自带的 ResGen.exe。
上面这个类很简单,就是根据传入的 Session["Lang"] 中的语言类型来做判断,该读那个资源文件(资源文件必须在 Resource 目录下),然后读取所需要的NAME,返回对应的字符串VALUE,VALUE中就是最后要输出的文字了。
在前台的 .aspx 中就可以直接用 <%= Html.Lang("String1") %>来输出了。至于JS的输出,看下面例子
<script language="javascript" type="text/javascript">
<%= Html.LangOutJsVar("msg")%>
function show()
{
alert(msg);
}
</script>
这样就OK了。
如果有的需要在C#中取资源字符串,那么可以使用
ViewData["Message"] = LocalizationHelpers.InnerLang(this.ControllerContext.HttpContext, "Welcome");来输出。
我根据ASP.NET MVC 4做了个DEMO,截图如下