ASP.NET 2.0 本地化技术之研究

    众所周知ASP.NET 2.0里对本地化(Localization)做了很多工作,大大简化了开发过程。今天终于能抽出时间研究一下这个技术了,资料很多,但大多带着一股咬文嚼字的翻译味道,So......自己写一篇。

1.使用工具自动生成本地化资源(LocalResources)
2.原来Localizable AttributeProperty是这么回事呀
3.手工添加本地化资源
4.显示使用本地化资源
5.全局资源的使用(GlobalResources)
6.如何在后台编程时使用这两种资源
7.编程切换语言设置
8.使用图片资源
9.代码下载


1.使用工具自动生成本地化资源(LocalResources)

首先当然是建立一个WEB工程啦,如图所示:


双击Default.aspx,切换到[设计]视图,从工具箱里拖一个Button进来。点击菜单中的[工具]->[生成本地资源],如图所示:


这时发现在解决方案方案视图里自动增加了一份本地资源,如下图所示:


切换到属性视图,可以看到Text和ToolTip都被加上了一个红色符号,提示“属性是用表达形式隐式绑定的”,如下图所示:(注意:只有在视图状态下选中控件才能看到这两个属性哟


为了增加对多语言的支持,我们现在右键Default.aspx.resx,点击复制,再选中App_LocalResources目录,点击粘贴,将“副本 Default.aspx.resx”重命名为Default.aspx.en-us.resx,如图所示:


分别编辑Default.aspx.resx和Default.aspx.en-s.resx 的内容,如下图示:
Default.aspx.resx


Default.aspx.en-s.resx


打开Default.aspx,在 Page 标签里添加Culture="auto" UICulture="auto",如下所示:
<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" meta:resourcekey="PageResource1" UICulture="auto" Culture="auto" %>

只有这样,后面才能获取浏览器的首选语言设置。如果要加到 Web.config 中,如下所示:
    <system.web>
   
    <globalization uiCulture="auto" culture="auto" />
   
</system.web>

运行网站,效果如下图所示:


点击IE菜单的[工具]->[Internet 选项],在弹出的对话框中点[常规]选项卡的[语言]按钮,弹出[语言首选项]对话框,如下图所示:


点击[添加]按钮,选择英语(美国),并上移到第一位,如下图所示:


一路[确定]点下来,刷新页面,可以看到Button的标题变成“Hello World”啦,如下图所示:


综上所述,使用工具自动生成本地化资源,并隐式的绑定到控件上,来实现页面的本地化是非常简单的,但存在以下几项问题:

    1)必须为每个页生成多份资源文件;
    2)只有控件属性中被标识为Localizable(true)才可能被工具扫描到;
    3)由于是对页面包含的控件进行扫描,所以最好是在页面布局基本确定后再使用该工具,并且在编辑完    资源文件后不要再使用该工具,如果不幸你这样做了。。。会发现默认的资源文件被清空了

2.原来Localizable AttributeProperty是这么回事呀

在我前天写的随笔开发和使用自定义服务器控件中,一直对属性为什么要使用Localizable(true)不清楚。
        [
        Bindable(
true),
        Category(
"Appearance"),
        DefaultValue(
"Hello"),
        Description(
"The welcome message text."),
        Localizable(
true)
        ]
        
public virtual string Text
        {
            
get
            {
                
string s = (string)ViewState["Text"];
                
return (s == null? "Hello" : s;
            }
            
set
            {
                ViewState[
"Text"= value;
            }
        }

查了许多关于WEB控件开发的资料,其中都对这个AttributeProperty做了忽略,原来只有当控件的属性声明为Localizable(true)时,VS的生成本地资源工具才会扫描到。

3.手工添加本地化资源

第一点中提到过生成本地资源工具只能扫描到页面已经包含的控件,那么如果后面由于开发需要又增加了一个新的控件要怎么办呢?虽然大部人都能自己想到,但还是写一下吧。

从工具箱再拖一个Label控件到页面上,切换到源视图,修改代码如下:
<asp:Label ID="Label1" runat="server" meta:resourcekey="Label1Resource1" Text="Label"></asp:Label>

再修改两份本地资源文件,为Label1添加Label1Resource1键值的相关资源,如下图所示:
Default.aspx.resx


Default.aspx.en-s.resx


再运行程序,切换语言设置,可以看到Label1的效果和Button1是一样的,如图所示:
中文(中国)


英语(美国)


4.显示使用本地化资源

OK,前面提到的都是隐式使用本地化资源,那么如何显示的使用本地化资源呢?相对于隐式来讲,显示更加灵活,功能也更强大。

只需要将刚才的Label1的代码,
<asp:Label ID="Label1" runat="server" meta:resourcekey="Label1Resource1" Text="Label"></asp:Label>

修改为,即可。
<asp:Label ID="Label1" runat="server" 
    Text
="<%$ Resources:Label1Resource1.Text %>" 
    ToolTip
="<%$ Resources:Label1Resource1.ToolTip %>" >
</asp:Label>

这时切换到[设计]视图,选中Label1控件,查看属性视图,会发现Text和ToolTip被加上的是蓝色的符号,提示“属性绑定了表达式”。跟上面提到的红色符号比较,少了“隐式”二字,这也就是所谓的显式和隐定的来源吧,如下图所示:


5.全局资源的使用(GlobalResources)

前面提到过,本地资源需要为每个页面分别生成多个资源文件,虽然这样看起来分门别类的挺清楚,但在实际应用过程中,我们有许多资源是可以共享的,总不能不停的重复写来写去吧。其实这种情况我们可以用全局资源(GlobalResources)来解决。

在资源方案视图中选中网站,右键,点击[添加ASP.NET 文件夹]->[App_GlobalResources],如图所示:


再选中App_GlobalResources文件夹,右键,点击[添加新项],在弹出的对话框中选中“资源文件”,命名为“LocalizedText.resx”,点击[添加],如图所示:


双击LocalizedText.resx进行编辑,添加一条新的字符串资源,如图所示:


复制LocalizedText.resx,粘贴到App_GlobalResources目录,重命名为LocalizedText.en-us.resx,双击进行编辑,添加一条新的字符串资源,如图所示:


打开Default.aspx,切换到[设计]视图,从工具箱拖一个TextBox控件到页面上。切换到[源]视图,修改代码:
<asp:TextBox ID="TextBox1" runat="server" Text="<%$ Resources:LocalizedText, Msg1 %>"></asp:TextBox>

运行程序,切换语言设置,可以看到全局资源的使用效果了,如图所示:
中文(中国)


英语(美国)


注意:全局资源不能使用隐式声明。

6.如何在后台编程时使用这两种资源

前面提到的都是在网页中使用这两种资源,那么如何在后台使用这两种资源呢?

打开Default.aspx,切换到[设计]视图,从工具箱拖一个Localize控件(Literal 控件与 Label 控件类似,但 Literal 控件不允许对所显示的文本应用样式。可以通过设置 Text 属性,以编程方式控制在控件中显示的文本。)到页面上。双击Button1,添加以下实现
    protected void Button1_Click(object sender, EventArgs e)
    {
        Localize1.Text 
= (String)GetLocalResourceObject("Label1Resource1.Text"+ " " +
            (String)GetGlobalResourceObject(
"LocalizedText""Msg1");
    }

记得添上这个引用
using System.Globalization;

运行程序,切换语言设置,可以看到和前面使用表达式调用资源的效果是一样的,如图所示:
中文(中国)


英语(美国)


7.动态切换语言设置

以上的介绍都是通过IE浏览器获取语言设置,其实我们可以自己设置使用哪种语言。

1)通过在每个页面里的Page节指定
<%@ Page Culture="en-us" UICulture="en-us" %>

如上所设,该页将使用en-us的语言设置。

注意:这只是个概要式写法,实际的页面中的Page一般都包含更多的属性。

2)通过在Web.Config里的globalization节指定
<system.web>
    
<globalization Culture="en-us" UICulture="en-us" />
</system.web>

3)当然还有一种就是通过编程动态切换语言设置啦,这也是实际项目中经常用到的方式

打开Default.aspx,切换到[源]视图,添加如下代码
        <href="?currentculture=zh-cn">中文(中国)</a>
        
&nbsp;
        
<href="?currentculture=en-us">English(USA)</a> 

打开Default.aspx.cs,添加如下代码
    String s;

    
protected override void InitializeCulture()
    {
        s 
= Request.QueryString["currentculture"];
        
if (!String.IsNullOrEmpty(s))
        {
            
//UICulture - 决定了采用哪一种本地化资源,也就是使用哪种语言
            
//Culture - 决定各种数据类型是如何组织,如数字与日期
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(s);
            Thread.CurrentThread.CurrentCulture 
= CultureInfo.CreateSpecificCulture(s);
        }
    }

记得添上这个引用
using System.Threading;

运行程序,分别点击新增加的两个链接,效果如图所示:
中文(中国)


Enlish(USA)



8.使用图片资源

分别编辑LocalizedText.resx和LocalizedText.en-su.resx,添加图片资源,如图所示:
LocalizedText.resx


LocalizedText.en-su.resx


注意:当图形文件添加到图形资源里时,系统会自动去除扩展名并把“-”替换成“_”,如上图,我的文件名为“en-us-flag.png”添加到资源里变成了“en_us_flag”。

打开Default.aspx,切换到[设计]视图,从工具箱拖一个Image控件到页面上。打开Default.aspx.cs,添加如下代码
    protected void Page_Load(object sender, EventArgs e)
    {
        Image1.ImageUrl 
= "~/Image.aspx?currentculture=" + s;
    }

选中网站右键,创建一个新的WEB窗体,命名为Image.aspx,编辑该页面,在Page节增加如下代码
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Image.aspx.cs" Inherits="Image" Culture="auto" UICulture="auto"%>

注意:默认创建的WEB窗体的Page节,不包括Culture和UICulture这两个属性,一定要手工添上,切记!

打开Image.aspx.cs,添加如下代码
    protected override void InitializeCulture()
    {
        String s 
= Request.QueryString["currentculture"];
        
if (!String.IsNullOrEmpty(s))
        {
            
//UICulture - 决定了采用哪一种本地化资源,也就是使用哪种语言
            
//Culture - 决定各种数据类型是如何组织,如数字与日期
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(s);
            Thread.CurrentThread.CurrentCulture 
= CultureInfo.CreateSpecificCulture(s);
        }
    }

    
protected void Page_Load(object sender, EventArgs e)
    {
        System.Drawing.Bitmap img 
= (System.Drawing.Bitmap)GetGlobalResourceObject(
            
"LocalizedText",
            CultureInfo.CurrentCulture.Name.ToLower().Replace(
"-""_"+ "_flag");

        System.IO.MemoryStream ms 
= new System.IO.MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

        Response.ClearContent();
        Response.ContentType 
= "image/jpeg";
        Response.BinaryWrite(ms.ToArray());

        img.Dispose();
        ms.Dispose();
        ms.Flush();
    }

当然,别忘了添上这两个引用
using System.Threading;
using System.Globalization;

运行程序,分别点击两个链接,效果如图所示:
中文(中国)


English(USA)


9.代码下载

下载地址:http://files.cnblogs.com/reonlyrun/WebLocalizationTaste.rar


注:关于回复中提到的整站资源切换和WebResource的使用,已经放到我的另一篇文章里了
ASP.NET 2.0 本地化技术之研究(二)
posted @ 2007-03-14 01:20 Clark Zheng 阅读(10702) 评论(47)  编辑 收藏 所属分类: A. .NET

  回复  引用  查看    
#1楼 2007-03-14 01:26 | Dflying Chen      
很不错的文章。
若想保持原有内容不消失,你可以在另外的页面中写一个<img>标签,然后让其src属性指向你生成图像的aspx页面就行了。
  回复  引用    
#2楼 2007-03-14 02:26 | 传世私服 [未注册用户]
ASP.NET 是以后网站发展的大方向.

以至于现在一些[url=http://***]传世私服[/url]的网站都有用的了.
  回复  引用  查看    
#3楼 [楼主]2007-03-14 02:32 | reonlyrun      
关于“如何将图像流输出到页面却保持页面原有内容不消失”

@Dflying Chen
谢谢您的帮助,我已调整了相关章节,并重新上传了新的代码。
  回复  引用  查看    
#4楼 2007-03-14 08:21 | JesseZhao      
汗,我看到传奇私服都害怕
  回复  引用  查看    
#5楼 2007-03-14 08:23 | aspnetx      
楼主写的很认真,值得大家学习
  回复  引用  查看    
#6楼 2007-03-14 08:58 | 玉开      
好文章,清晰易懂。
  回复  引用  查看    
#7楼 2007-03-14 08:59 | dearfang      
好文~
  回复  引用  查看    
#8楼 2007-03-14 09:13 | KiddLee      
学习
  回复  引用    
#9楼 2007-03-14 09:25 | teana [未注册用户]
好文!
  回复  引用    
#10楼 2007-03-14 09:32 | www [未注册用户]
wwwwwwwwwwwww
  回复  引用    
#11楼 2007-03-14 09:33 | www [未注册用户]
you@teana

  回复  引用  查看    
#12楼 2007-03-14 10:13 | Cat Chen      
很好的文章,将有关的技术细节都串讲了。

关于如何将资源直接显示……既然控件能够将嵌入dll的资源直接显示,不知道网站能否也将嵌入资源直接调用WebResource显示呢?
  回复  引用  查看    
#13楼 2007-03-14 10:18 | finesite      
很详细,正需要,能否谈谈 不同语种切换,字体格式错位问题
  回复  引用  查看    
#14楼 [楼主]2007-03-14 10:29 | reonlyrun      
@finesite
我认为由于表现机制的原因,ASP.NET是使用CSS来控制一个文本(如标签)的宽度,是不是可以考虑通过编程为不同的语种使用各自的CSS文件呢?
  回复  引用  查看    
#15楼 2007-03-14 10:42 | 哈密瓜牌牛奶      
非常非常好好好好的文章。。。
keep 住了,以后做本地化好办了:)
  回复  引用    
#16楼 2007-03-14 10:47 | hjh [未注册用户]
这只是单个页面的切换,如何做整个站点的切换呢?
希望楼主指点一下!
  回复  引用  查看    
#17楼 [楼主]2007-03-14 11:18 | reonlyrun      
@hjh
似乎得在每个页面里都要重写InitializeCulture函数才行,当然不一定非得URL传参,使用Session或Cookie都可以。
除此以外我还想不到更好的办法,不知道有没有达人能更圆满的解决该问题。
  回复  引用  查看    
#18楼 2007-03-14 15:57 | John.z      
添加不同的language显示不同的resource 只是ie浏览器才支持吗?
  回复  引用  查看    
#19楼 [楼主]2007-03-14 17:38 | reonlyrun      
@John.z
不是,FF一样可以,我测试过。
  回复  引用  查看    
#20楼 2007-03-14 20:53 | 菜菜陈熙尚      
不错..很详细
  回复  引用  查看    
#21楼 2007-03-15 11:38 | 心雨无痕      
lz写的很认真啊,清晰易懂,呵呵
  回复  引用  查看    
#22楼 2007-03-15 20:43 | 生米煮成稀饭      
不错,清晰易懂
  回复  引用  查看    
#23楼 2007-03-16 17:58 | 马志远      
文章不错.是个好孩子.
  回复  引用    
#24楼 2007-03-21 23:01 | 小莫 [未注册用户]
图文并茂,浅俗易懂,赞一个!
  回复  引用    
#25楼 2007-03-22 22:09 | Cable Fan [未注册用户]
看过了,很棒,投朵鲜花!
  回复  引用    
#26楼 2007-03-23 22:48 | 赵红波 [未注册用户]
大家好我是一个小菜鸟,我想学ASP。NET改怎么入门啊?
  回复  引用    
#27楼 2007-03-23 22:48 | 赵红波 [未注册用户]
请好心人回复一下
  回复  引用  查看    
#28楼 2007-03-24 09:01 | 兰亭      
这样写最清楚不过了,谢谢
  回复  引用  查看    
#29楼 2007-04-14 00:10 | 学海无涯,回头是岸      
根目录下的页面可以,如果是子目录下的页面就不行了,博主碰见过码?
  回复  引用  查看    
#30楼 2007-04-23 10:00 | 清晨风      
@hjh
@reonlyrun
直接修改配置文件可以,但是修改后要手动刷新页面才有效果,不知道有没有办法在修改配置文件后自动应用修改.

  回复  引用  查看    
#31楼 [楼主]2007-04-28 18:18 | Clark Zheng      
@学海无涯,回头是岸
没有碰到过
  回复  引用    
#32楼 2007-06-04 10:15 | holyli [未注册用户]
文章写的不错,但是我不知道这是干啥用的,怎么用啊??
  回复  引用    
#33楼 2007-06-04 11:55 | Travle.Cai [未注册用户]
果然不错很清晰.
  回复  引用    
#34楼 2007-06-14 15:40 | mesou [未注册用户]
文章很好!
  回复  引用    
#35楼 2007-08-09 19:24 | myds [未注册用户]
太好了,谢谢,学习学习

文章很好!
  回复  引用    
#36楼 2007-08-27 16:03 | 按时地方 [未注册用户]
写的很好啊!~~
  回复  引用    
#37楼 2007-10-08 20:53 | hhwly [未注册用户]
Thank you.
  回复  引用  查看    
#38楼 2007-10-10 08:14 | 1-2-3      
喔,真是非常有用,收藏。
  回复  引用    
#39楼 2007-10-18 10:01 | SubSonic [未注册用户]
谢谢分享!
  回复  引用  查看    
#40楼 2007-10-30 15:15 | 林子      
写的不错啊 !
  回复  引用    
#41楼 2007-11-03 00:08 | sctianhu [未注册用户]
wowo正用上。
  回复  引用  查看    
#42楼 2008-03-13 20:45 | 笑疯^_^      
写的很不错
  回复  引用    
#43楼 2008-03-14 11:34 | Moonlight [未注册用户]
确实足够详细了,方方面面都有提到,真的不错.谢谢楼主.
  回复  引用    
#44楼 2008-04-29 11:38 | 影之飘逸 [未注册用户]
楼主很不好,顶!!!!!!
大家也应对这多国语言支持!
  回复  引用  查看    
#45楼 2008-06-02 15:20 | 堂吉柯德      
不错, 我有个本地化工具, 发表在www.dotnetcoding.net上, 欢迎交流
  回复  引用  查看    
#46楼 2008-06-02 15:26 | 堂吉柯德      
@reonlyrun


关于语言切换肯定是不需要每个页面都写的, 实际上只需要将语言图片切换做成服务器控件, 写几行代码就可以了。 不过记住, 对线程设置语言一定要早, 不然就要点两下才能切换过来呀。
  回复  引用    
#47楼 2008-06-21 16:37 | ForYou [未注册用户]
对像我这样的初学者非常有用!

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-07-13 09:28 编辑过


相关链接: