asp.net MVC 3多语言方案--再次写, 配源码
之前写了一篇asp.net MVC多语言方案,那次其实是为American Express银行开发的。有许多都是刚开始接触,对其也不太熟悉。现在再回过头去看,自己做一个小网站,完全用asp.net mvc 3的技术。要实现多语言,并且要求可以动态换语言。在有数据输入的地方,其数据输入校验的界面也是不一样的,比如必须输入的字段,英文显示:required, 中文就显示:请输入,等等。这里的方法和之前的文章的方法略有不同。
1. 资源文件
多语言的资源文件还是一个单独的.net 工程,里面只放资源文件。可以建一个class library的工程。工程名字叫Resource。里面只加入资源文件.resx。资源文件加入时,一种语言一个文件,这个有基础的人都知道,不多说。

唯一要注意的是:要将Access Modifier置成Public。这样IDE会为其产生c#代码。其类是包以外的类也能访问的。

2. 在View中使用资源文件
在_ViewStart.cshtml中最前面加上这么一行。
@{CommonUtil.ResourceLoader.SetCurrentThreadCulture(Session);}
后面会介绍 ResourceLoader.SetCurrentThreadCulture的代码。此方法是根据Session["Culture"]来设置当前线程的Culture和UI Culture。在此处加上这么一行,将会对所有的本应用程序的view有影响。
见这个代码,这是本人这个小网站的layout,即相当于asp.net 2.0时代的master page。

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>@ViewBag.Title</title>
5 <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
6 <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
7 </head>
8 <body>
9 <div class="wrap">
10 <DIV class="header">
11 <DIV id="logo" class="logo">
12 <a href="@Url.Content("~/")"><img border="0" src="@Url.Content(Resource.Views.Shared.Layout.Logo)" /></a>
13 </DIV>
14 <DIV id="logo" class="logo">
15 <img border="0" src="@Url.Content(Resource.Views.Shared.Layout.AnimAd)" />
16 </DIV>
17 <DIV id="Links" class="top_nav">
18 <UL>
19 <LI><A href="@Url.Content("~/English/")">English</A></LI>
20 <LI><A href="@Url.Content("~/Chinese/")">中文</A></LI>
21 <LI><A href="@Url.Content("~/ContactUs/")">@Resource.Views.Shared.Layout.ContactUS</A></LI>
22 </UL>
23 </DIV>
24 </div>
25 <div class="content">
26 @RenderBody()
27 </div>
28 <div id ="FooterSection" class="footer">
29 <p>© @Resource.Views.Shared.Layout.CopyRight </p>
30 </div>
31 </div>
32 </body>
33 </html>

见到使用资源文件的地方了吗?如:@Resource.Views.Shared.Layout.ContactUS,还有@Resource.Views.Shared.Layout.CopyRight,这两个是文本的多语言。还有图片的多语言,即在<img中的Resource.Views.Shared.Layout.Logo。即实现了两个语言版本的图片,用这个资源存储多个语言版本的图片路径。页面中显示哪一个,就根据当前用户的语言偏好。
3. 动态切换语言
注意到上面的代码里有一个English和中文的链接了吗。点这两个链接都会有相应的controller处理。这里的controller是这样的代码:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Threading;
using CommonUtil;
namespace ApplicationExpertShare.Controllers
{
public class EnglishController : Controller
{
//
// GET: /English/
public ActionResult Index()
{
System.Globalization.CultureInfo englishCulture = new System.Globalization.CultureInfo("en-US");
Session["Culture"] = englishCulture;
return this.Redirect(this.Request.UrlReferrer.ToString());
}
}
}

这里调用了一个ResourceLoader类来切换语言。中文的controller也一样:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Reflection;
using System.Threading;
using CommonUtil;
namespace ApplicationExpertShare.Controllers
{
public class ChineseController : Controller
{
//
// GET: /Chinese/
public ActionResult Index()
{
System.Globalization.CultureInfo chineseCulture = new System.Globalization.CultureInfo("zh-CN");
Session["Culture"] = chineseCulture;
return this.Redirect(this.Request.UrlReferrer.ToString());
}
}
}

那么究竟ResourceLoader类做了什么呢,竟然能动态切换语言?看代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Web;
using System.Web.Mvc;
namespace CommonUtil
{
public static class ResourceLoader
{
public static void SetCurrentThreadCulture(HttpSessionStateBase session)
{
if (session != null && session["Culture"] != null)
{
System.Threading.Thread.CurrentThread.CurrentCulture = (System.Globalization.CultureInfo)session["Culture"];
System.Threading.Thread.CurrentThread.CurrentUICulture = (System.Globalization.CultureInfo)session["Culture"];
}
}
}
}

它究竟干了什么呢?
第一步:判断Session是否空,还有Session["Culture"]是否空。因为这两个都有可能为空。
第二步:根据Session["Culture"]设置当前线程的Culture和UI Culture。
4. Model类的多语言
asp.net MVC少不了Model类,Model类在输入界面里还有input validation信息,这些input validation的信息也应该是能多语言的。比如最常见的必须输入字段,我们用英文就显示"Required",用中文就显示:“请输入”。如何做呢?见代码:

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel.DataAnnotations;
4 using System.Web.Mvc;
5 using Resource.Entity;
6
7 namespace DataEntity
8 {
9 public class UserAccount
10 {
11 #region private members
12 private int _iID;
13 private string _strName;
14 private string _strEmail;
15 private string _strPassword;
16 private string _strConfirmPassword;
17 private System.Decimal _Balance;
18 #endregion
19
20 #region Properties
21 public int ID
22 {
23 get
24 {
25 return _iID;
26 }
27 set
28 {
29 _iID = value;
30 }
31 }
32
33 [Required(ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName="Common_Required_ErrorMessage")]
34 [StringLength(30, ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "NAME_StringLength_ErrorMessage")]
35 [RegularExpression(@"[a-zA-Z].*", ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "NAME_RegularExpression_ErrorMessage")]
36 [Display(ResourceType=typeof(Resource.Entity.UserAccount), Name="NAME_DisplayName")]
37 public string NAME
38 {
39 get
40 {
41 return _strName;
42 }
43 set
44 {
45 _strName = value;
46 }
47 }
48
49 [Required(ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
50 [RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
51 , ErrorMessageResourceType=typeof(Resource.Entity.UserAccount), ErrorMessageResourceName="EMAIL_RegularExpression_ErrorMessage")]
52 [Display(ResourceType=typeof(Resource.Entity.UserAccount), Name="EMAIL_DisplayName")]
53 public string EMAIL
54 {
55 get
56 {
57 return _strEmail;
58 }
59 set
60 {
61 _strEmail = value;
62 }
63 }
64
65 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "PASSWORD_DisplayName")]
66 [Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
67 [StringLength(32, ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "PASSWORD_StringLength", MinimumLength = 8)]
68 public string PASSWORD
69 {
70 get
71 {
72 return _strPassword;
73 }
74 set
75 {
76 _strPassword = value;
77 }
78 }
79
80 [Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
81 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "CONFIRMPASSWORD_DisplayName")]
82 [Compare("PASSWORD", ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "CONFIRMPASSWORD_CompareErrorMessage")]
83 public string CONFIRMPASSWORD
84 {
85 get
86 {
87 return _strConfirmPassword;
88 }
89 set
90 {
91 _strConfirmPassword = value;
92 }
93 }
94
95 [Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
96 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDNAME_DisplayName")]
97 public string OldName { get; set; }
98
99 [Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
100 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDEMAIL_DisplayName")]
101 public string OldEmail { get; set; }
102
103 [Required(ErrorMessageResourceType = typeof(Resource.Entity.UserAccount), ErrorMessageResourceName = "Common_Required_ErrorMessage")]
104 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "OLDPassword_DisplayName")]
105 public string OldPassword { get; set; }
106
107 [Display(ResourceType = typeof(Resource.Entity.UserAccount), Name = "Balance")]
108 public decimal Balance { get; set; }
109 #endregion
110 }
111 }

这个类显示了如何在DataAnnotations中使用资源文件的多语言信息。这些Attribute都接受一个ResourceType, 和一个Resource String的名字。这里可以再说一点,就是RegularExpressionAttribute, 可以用资源文件存储正则表达式,这样还可以实现不同的语言采用不同的数据验证规则。剩下的就是如何在Resource工程里规划好资源文件了。稍有基础的人都知道,就不多说了。
5. 结束语
一个全局的资源文件可以带来许多好处。比如集中管理资源。所有资源都在这个特定的工程里面。当然也有坏处,就是当资源越来越多时,就会难于管理。到时可以想一些折衷的办法。要么将资源文件放到两个资源工程里面;要么也可以允许一些local的资源文件。这些的问题只有遇到的时候才会找到合适的办法。需要根据实际情况来采取一些办法。
asp.net MVC 3多语言方案--再次写, 配源码的更多相关文章
- ASP.NET MVC+EF框架+EasyUI实现权限管理(附源码)
前言:时间很快,已经快到春节的时间了,这段时间由于生病,博客基本没更新,所以今天写一下我们做的一个项目吧,是对权限的基本操作的操作,代码也就不怎么说了,直接上传源码和图片展示,下面我们直接进入主题介绍 ...
- ASP.NET MVC:多语言的三种技术处理策略
ASP.NET MVC:多语言的三种技术处理策略 背景 本文介绍了多语言的三种技术处理策略,每种策略对应一种场景,这三种场景是: 多语言资源信息只被.NET使用. 多语言资源信息只被Javascrip ...
- Spring学习之——手写Spring源码V2.0(实现IOC、D、MVC、AOP)
前言 在上一篇<Spring学习之——手写Spring源码(V1.0)>中,我实现了一个Mini版本的Spring框架,在这几天,博主又看了不少关于Spring源码解析的视频,受益匪浅,也 ...
- Go语言GC实现原理及源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 介绍 三色标记法 三色标 ...
- C语言之socket获取网页源码
写爬虫也许你用的是python,类似urlopen(url).read()即可获得普通的网页的源码,或者用的java的网络库加上流操作,或者其他高级语言.但你有没有想过使用C语言来实现呢?我曾经以为用 ...
- Tiny语言执行环境TM机源码
TM机就是TINY语言编译器编译之后的汇编代码的执行环境.TM机的主要功能是将TM的汇编代码读入和执行,它具有一般计算机类似的精简指令级RISC.TM汇编语言和一般的Intel汇编语言差点儿相同,包含 ...
- 数据同步方案(附Java源码)
一.问题背景经常碰到要同步数据的情况,而系统自带的复制功能又不能实现增量同步,每次都要做全量复制,发生异常情况后只能重头再来,非常麻烦,优其是对那种大文件的处理,更是耗时.二.解決方案1.计算源目录数 ...
- CAS进行https到http的改造方案,结合cookie源码分析
先说具体的改造方案: 服务端: 一.CAS Server端的修改 1.找到cas\WEB-INF\deployerConfigContext.xml 对以下Bean增加参数p:requireSecur ...
- APP加固技术历程及未来级别方案:虚机源码保护
传统App加固技术,前后经历了四代技术变更,保护级别每一代都有所提升,但其固有的安全缺陷和兼容性问题始终未能得到解决.而下一代加固技术-虚机源码保护,适用代码类型更广泛,App保护级别更高,兼容性更强 ...
随机推荐
- struts2 result type的类型
一共十种类型 1.dispatcher 默认的类型,相当于servlet的foward,服务器端跳转.客户端看到的是struts2中配置的地址,而不是真正页面的地址.一般用于跳转到jsp页面 2.re ...
- YaHoo Web优化的14条法则
Web应用性能优化黄金法则:先优化前端程序(front-end)的性能,因为这是80%或以上的最终用户响应时间的花费所在. 法则1. 减少HTTP请求次数 80%的最终用户响应时间花在前端程序上,而其 ...
- Ajax应用-定义一套自己的Ajax框架
—————————————————————————— <script type="text/javascript"> //定义个一个functio ...
- HDU1236:排名
Problem Description 今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑 每题的分值,所以并不是最后的排名.给定录取分数线,请你写程序找出最后 ...
- 开机启动 sh
我编辑 /etc/init.d/vsftpd 将 nohup java -jar fff.jar & 放在前面 .就执行了
- eclipse添加桌面快捷方式
linuxmint系统 输入sudogedit /usr/share/applications/eclipse.desktop,在打开的文件中输入以下参数: [Desktop Entry] Encod ...
- 使用shell脚本自定义实现选择登录ssh
在系统bin目录中建立两个脚本分别是pssh tssh pssh #!/usr/bin/expect -f set ip [lindex ] set port [lindex ] set passwo ...
- photoshop 魔术橡皮擦
魔术棒和橡皮的结合,不用解锁就能抠图
- 使用VS软件打开网站在浏览器浏览的方法
1.用VS软件打开网站之后,先检查网站是否使用IIS Express开发 2.若不是,则切换成使用IIS Express开发 3.检查项目使用的托管管道模式设置为经典模式了没有 4.最后选择“在浏览器 ...
- 转: Ant 脚本的结构化设计
引言 Ant 脚本是由 Apache 提供的一种基于 Java 的构建工具,为 Java 开发人员所熟悉.Java 开发人员使用 Ant 脚本可以很方便地完成 Java 开发过程中常见的如拷贝文件.创 ...