ASP.NET网站多语言的实现
在大中型网站中,有时需求将网站做成多个语言的版本,以适应在不同地区上线运营的需求。要求能够根据网站维护人员在后台的配置来显示不同语言版本。
由于在项目中用到了这种功能,因此将实际应用的方式总结一下,希望能让大家和我自己都能够有所收获。
一.网站实现多语言的主要方面:
在将网站做成一个完整的多语言版本时,主要有两方面的要求:1.页面Html中文字的多语言支持;2.JS提示信息(如alert,confrim等)的多语言支持。下面来分别说明一下这两个方面的具体实现:
1.页面中.Html文字的多语言支持:
这里实现的是对页面上的控件(如Label)中的文字实现多语言支持。只需要应用DotNet中的区域化机制即可,即生成资源文件,然后在WebConfig中配置即可,网上详细说明的文章很多,因此这里只是简单的说明一下实现。
实现步骤:
1.1.添加资源文件
首先使用一种语言正常完成页面,然后切换到页面的设计视图,在【工具】选单下找到【生成本地资源选项】(注意:此选项只有在网页的设计视图下才会呈现),如图:
稍等片刻,VS在同一级目录下会自动为页面生成相应的资源文件,并给页面中的html标签添加资源文件的读取标记(meta:resourcekey="lblNoteResource1)。自动生成的资源文件位于aspx页面的同级目录下的App_LocalResources文件夹下,命名方式为“页面名称+.aspx.resx”(如:Indedx.aspx.resx)。此时有几个需要注意的地方:
(1) 生成资源文件以后,VS会在页面的[<%@ Page]标签下自动添加两个属性: culture="auto"和uiculture="auto"。这两个属性的作用是使页面优先跟据浏览器的语言设置自动加载相应语言的资源文件及时间货币等显示方式,因此我们需要将这两个属性删除,以保证页面按照我们在WebConfig中的配置来显示。
(2) 对于页面中的非服务器端控件,(即input等传统html控件),无法自动生成资源文件,需要手动添加meta:resourcekey标记,并将其添加到资源文件中。(这也是比较头疼的一个地方,不知道大家是如何解决的,如果有好的方式,还请不吝赐教)。添加时还需要保证标签中都有runat="server"标记,否则html标签读取不到相应的资源文件。
(3) 生成的资源文件为默认资源文件,当系统找不到配置的资源文件时,会去读取默认资源文件
资源文件生成完之后,我们需要手动添加多种语言的资源文件,将,例如,添加繁体版的资源文件,则添加Indedx.aspx.zh-TW.resx.命名规则为刚才生成的默认资源文件名中的aspx与resx中添加区域代码如,台湾为(zh-TW).因为资源文件本质上是xml,所以建议使用VS中的XML编辑器来打开编辑。
1.2.添加WebConfig节点
在<system.web>节点下添加节点<globalization culture="zh-TW" uiCulture="zh-TW"/>,其中uiCulture的值表示页面读取的哪个资源文件,为区域代码;culture则代表当前网站的区域文化信息,如时间,货币格式等的显示方式。
2.JS提示及显示信息(如alert,confrim等)的多语言支持
这一部分处理的时候,使用过两种方式,一种是借用Ajax方式来实现,第二种使用js读取XML的方式。区别就是第一种每次js提示时需要到服务器端来读取xml,会加重服务器的负担,因此后来实际中改用了第二种方式。
这种方式的实现步骤:
2.1. 用JS获取网站语言设置
网站当前的语言设置放在WebConfig中,但是可能是由于安全原因的限制,没能用JS读取到WebConfig中的相关配置项信息,因此绕了一下:当网站启动时,先将语言配置从WebConfig读出来,放入一个XML文件,然后用js去读取此文件,获取当前网站的应显示何种语言。具体实现如下:
先在Global.asax中读取标识,并存入XML.
void Application_Start(object sender, EventArgs e)
{
WriteLanguagekeyToXML();
………………………
}
/// <summary>
/// 將判斷大陸版本或臺灣版本的標志寫入Web.xml add by bai_clong
/// </summary>
private void WriteLanguagekeyToXML()
{
//System.IO.FileStream fs = new System.IO.FileStream("/JS/JSXML/Web.xml",System.IO.FileMode.);
System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument();
//xmldoc.Load(HttpContext.Current.Server.MapPath(filePath + fileName));
System.Web.UI.Page pg = new Page();
string lastFilePath = System.AppDomain.CurrentDomain.BaseDirectory;
lastFilePath += "JS\\JSXML\\Web.xml";
if (!System.IO.File.Exists(lastFilePath))
{
CreateWebXml(lastFilePath);
}
xmldoc.Load(lastFilePath);
System.Xml.XmlNode xmlnode = xmldoc.SelectSingleNode("/configuration/add[@key=’languagekey’]");
if (!xmlnode.Attributes["value"].Value.Equals(System.Configuration.ConfigurationManager.AppSettings["languagekey’"].ToString()))
{
xmlnode.Attributes["value"].Value = System.Configuration.ConfigurationManager.AppSettings["languagekey’"].ToString();
xmldoc.Save(lastFilePath);
}
}
/// <summary>
/// 創建WEB.XML文件
/// </summary>
/// <param name="filePath">文件路徑</param>
private void CreateWebXml(string filePath)
{
System.Xml.XmlDocument xmlDoc=new System.Xml.XmlDocument();
System.Xml.XmlDeclaration declaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8","yes");
xmlDoc.AppendChild(declaration);
System.Xml.XmlElement rootNode = xmlDoc.CreateElement("configuration");
System.Xml.XmlElement xmlNode = xmlDoc.CreateElement("add");
System.Xml.XmlAttribute xmlKey = xmlDoc.CreateAttribute("key");
xmlKey.Value = " languagekey’";
xmlNode.Attributes.Append(xmlKey);
System.Xml.XmlAttribute xmlValue = xmlDoc.CreateAttribute("value");
xmlValue.Value = "0";
xmlNode.Attributes.Append(xmlValue);
string commentString = FRIMYLEC.Library.Model.Entity.Common.EventMessage.GetEventMessage(FRIMYLEC.Library.Common.CommonString.WebXmlCommentString);
System.Xml.XmlComment comment = xmlDoc.CreateComment(commentString);
rootNode.AppendChild(comment);
rootNode.AppendChild(xmlNode);
xmlDoc.AppendChild(rootNode);
xmlDoc.Save(filePath);
}
2.2 将JS需要显示的文字及提示信息提取到XML:
将JS需要显示的文字提取出来到XML,也要根据语言做成多个文件,放在网站目录下,不同语言的文件的命名可以自己定义,如图:
以语言为简体和繁体为例,其中AlertMessage.xml为简体内容,AlertMesage_TW为繁体内容,文件内容:
简体:
<?xml version="1.0" encoding="utf-8" ?>
<alertmessage>
<!--Modules\WorkFlowTemplete\AuditRecordQuery.aspx Begin-->
<add key="ApplicationCodeNotExist" value="对象代码不存在,请输入正确的对象代码!"></add>
<!--Modules\WorkFlowTemplete\AuditRecordQuery.aspx End-->
………………………….
繁体:
<?xml version="1.0" encoding="utf-8" ?>
<alertmessage>
<!--Modules\WorkFlowTemplete\AuditRecordQuery.aspx Begin-->
<add key="ApplicationCodeNotExist" value="物件代碼不存在,請輸入正確的物件代碼!"></add>
<!--Modules\WorkFlowTemplete\AuditRecordQuery.aspx End-->
……………………….
2.3使用JS读取当前语言的XML文件
这部分JS代码可以放在单独的JS文件中,在需要实现多语言的页面中引用即可。
具体代码如下:
//獲得對應的漢字, js中调用此方法获取文字(message为Key)
function getMessage(message)
{
loadFile();
String.prototype.trim=function()
{
return this.replace(/(^\s*)|(\s*$)/g,"");
}
return xmlDoc.selectSingleNode("alertmessage/add[@key='"+message.trim()+"']").getAttribute("value");
}
//加載xml文件
function loadFile()
{
getLanguagekey();
createDocumentObject();
if(languagekey=="1")
{
xmlDoc.load(getRootPath()+"/JS/JSXML/AlertMessage_TW.xml");
}
else if(languagekey=="0")
{
xmlDoc.load(getRootPath()+"/JS/JSXML/AlertMessage.xml");
}
}
//firefox並不支援selectSingleNode和selectNodes方法;下面兩段是用XPath來解決firefox
//模擬selectSingleNode和selectNodes方法
function createSelectSingleNodeAddSelectNodesMethod()
{
XMLDocument.prototype.selectSingleNode = Element.prototype.selectSingleNode = function (xpath){
var x = this .selectNodes(xpath)
if ( ! x || x.length < 1 ) return null ;
return x[ 0 ];
}
XMLDocument.prototype.selectNodes = Element.prototype.selectNodes = function (xpath){
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver( this .ownerDocument == null ?
this .documentElement : this .ownerDocument.documentElement);
var result = xpe.evaluate(xpath, this , nsResolver, 0 , null );
var found = [];
var res;
while (res = result.iterateNext())
found.push(res);
return found;
}
}
//創建文檔對象
function createDocumentObject()
{
//ie
if((xmlDoc==null) && window.ActiveXObject)
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");//Msxml2.DOMDocument
}
//FF
else if(document.implementation && document.implementation.createDocument)
{
xmlDoc=document.implementation.createDocument("", "", null);
createSelectSingleNodeAddSelectNodesMethod();
}
xmlDoc.async=false;
}
//獲得大陸或臺灣簡繁體標志信息
function getLanguagekey()
{
var configDoc=null;
//ie
if((configDoc==null) && window.ActiveXObject)
{
configDoc=new ActiveXObject("Microsoft.XMLDOM");//Msxml2.DOMDocument
}
//FF
else if(document.implementation && document.implementation.createDocument)
{
configDoc=document.implementation.createDocument("", "", null);
createSelectSingleNodeAddSelectNodesMethod();
}
configDoc.async=false;
configDoc.load(getRootPath()+"/JS/JSXML/Web.xml");
var languagekeyNode=configDoc.selectSingleNode("configuration/add[@key='languagekey']");
languagekey=languagekeyNode.getAttribute("value");
}
2.4 在JS获取相应的文字信息:
完成了以上功能之后,js中的调用就比较简单了:
例如:
document.getElementById("Label2").innerHTML=getMessage("XMLkey");
alert(getMessage("XMLkey"));
confirm(getMessage("XMLkey"));
二.总结:
在实现多语言的过程中,除了以上两个方面,可能还会遇到其它一些问题,比如时间,货币等格式通常要配套显示等等,有些也可以应用DotNet中已有的国际化支持来实现。对于语言的显示上,上面两个方面的解决应该可以把主要的问题解决掉。不知道大家在项目中有什么更好的方案,尤其是对于JS的国际化,如果有的话,还请大家不吝赐教...