代码改变世界

MVC3中实现验证提示信息多语言支持

2011-05-30 00:26  无常  阅读(6213)  评论(8编辑  收藏

导言

上一篇博文中提出一种通过自定义验证适配器自定义模验证提示信息的方法,实现了修改System.ComponentModel.DataAnnotations中提供的默认验证信息,但此方法是把提示信息写死在代码中,不够灵活,比如要多语言支持的情况下,就无能为力了。

本文便继续加以完善,在上文方法的基础上,实现验证提示信息的多语言支持。

改造MyRequiredAttributeAdapter

即是要实现多语言支持,那么提示信息就不能写死在适配器中了。多语言信息内容,一般是保存在独立的XML文件中或者使用ASP.NET中内置的资源文件,本文使用后者。

为了实现更灵活的验证信息,参考了这篇博文的方法,使用 “{CLASSNAME}_{PROPERTY}_required”做为资源名保存提示信息,也就是每个类的每个属性都可以指定不同的提示信息。

修改验证适配器:

image

然后在站点全局资源文件目录App_GlobalResources中添加名为 Message 的资源文件,在资源文件中按照“{CLASSNAME}_{PROPERTY}_required”的格式添加必填验证提示信息比如RegisterModel类的UserName属性的资源名为: RegisterModel_UserName_Required。然后复制填写其它语言版本:

image

至此,实现了从资源文件中获取提示信息的功能。但是HttpContext.GetGlobalResourceObject()方法是根据当前执行线程的文化信息来获取相应语言的资源的,一般是通过站点配置文件的system.web.globalization节点指定当前应用的语言信息,如果没指定则使用操作系统的语言环境设置。

根据浏览器语言信息显示不同语言的提示信息

我们需要网站智能点,比如中国人访问时显示中文的提示,美国人访问时显示英文的提示信息,当然我们不能先去问下访问网站的人是想看中文还是英文微笑 ,但是我们可以从浏览器的语言设置中获取用户的默认语言。

先来实现一个MVC的过滤器,在Action执行前根据用户浏览器语言来设置当前线程的语言文化信息:

    public class CultureInfoAttribute : FilterAttribute, IActionFilter
    {
        /// <summary>
        /// 站点支持的语言列表
        /// </summary>
        public static readonly List<string> AvailableCultures = new List<string>
        {
            "en-US","zh-CN"
        };
        public void OnActionExecuting(ActionExecutingContext
            filterContext)
        {
            string cultureCode = GetBrowserCulture(filterContext);
            if (string.IsNullOrEmpty(cultureCode) ||
                !AvailableCultures.Any(o => o.Equals(cultureCode, 
StringComparison.OrdinalIgnoreCase))) { return; } try { CultureInfo culture = new CultureInfo(cultureCode); System.Threading.Thread.CurrentThread.CurrentCulture = culture; System.Threading.Thread.CurrentThread.CurrentUICulture = culture; } catch (Exception) { } } /// <summary> /// 获取浏览器的语言设置 /// </summary> /// <param name="filterContext"></param> /// <returns></returns> private string GetBrowserCulture(ActionExecutingContext filterContext) { var browerCulture = filterContext.HttpContext.Request.UserLanguages; if (browerCulture == null) { return null; } foreach (var item in browerCulture) { if (AvailableCultures.Any(o => o.Equals(item,
StringComparison.OrdinalIgnoreCase))) { return item; } } return null; } public void OnActionExecuted(ActionExecutedContext filterContext) { } } 然后在程序启动时注册为全局过滤器:
image

完成

做完这步之后,我们在浏览器中更改不同的语言环境,测试看下效果:

英文:

image

中文:

image

Locations of visitors to this page