当前位置: 首页 > news >正文

[Asp.net mvc]国际化

摘要

在实际项目中,经常遇到,开发的项目要提供给不同的国家使用,如果根据国家来开发不同的站点,肯定是非常耗时又耗成本的。asp.net中,提供了一种比较方便的方式,可以使用资源文件的方式,使我们的站点,面向国际化。

一个例子

新建一个mvc项目,如下:

其中文件夹App_GlobalResources,为资源文件文件夹。可以通过右键添加,如图:

Languages.resx:默认中文资源文件。

Languages.en.resx:英文资源文件。

资源项包括

注意,添加过之后,你可以对比一下,这两个文件,其中默认中文资源文件Languages.Designer.cs中有代码,英文资源的是没有代码的(这里不再做分析,之后可以通过反编译工具进行查看)。

测试

为了测试方便,添加一个UserInfo的实体类

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Wolfy.Lang.Models
{ 
    /// <summary>
    /// 默认 资源文件 中文
    /// </summary>
    public class UserInfo
    {

        [Display(Name = "Id", ResourceType = typeof(Resources.Languages))]
        public int Id { set; get; }
        [Display(Name = "Name", ResourceType = typeof(Resources.Languages))]
        public string Name { set; get; }
        [Display(Name = "Gender", ResourceType = typeof(Resources.Languages))]
        public string Gender { set; get; }
        [Display(Name = "Age", ResourceType = typeof(Resources.Languages))]
        public int Age { set; get; }
    }
}

这里采用默认资源中文的资源文件。

获取语言的辅助类,用来获取语言。这里为了设置方便,采用获取cookie中的lang字段作为测试用,当然你也可以使用url进行传递。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Wolfy.Lang.Utilities
{
    public class LanguageHelper
    {
        private static List<string> _cultures = new List<string> { "zh-CN", "en-US" };
        public static string FindLanguageName(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return _cultures[0];
            }
            if (_cultures.Where(l => l.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any())
            {
                return name;
            }
            var partName = GetPartName(name);
            foreach (var item in _cultures)
            {
                if (item.StartsWith(partName))
                {
                    return item;
                }
            }
            return _cultures[0];
        }
        private static string GetPartName(string name)
        {
            if (!name.Contains("-"))
            {
                return name;
            }
            else
            {
                return name.Split('-')[0];
            }
        }
    }
}

添加BaseController,在需要国际化的视图对应的控制器,都需要继承该类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using Wolfy.Lang.Utilities;

namespace Wolfy.Lang.Controllers
{
    public class BaseController : Controller
    {
        protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
        {
            string langName = string.Empty;
            HttpCookie langCookie = Request.Cookies["lang"];
            if (langCookie != null)
            {
                langName = langCookie.Value;
            }
            else
            {
                langName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : string.Empty;
            }
            langName = LanguageHelper.FindLanguageName(langName);
            Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(langName);
            Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
            return base.BeginExecuteCore(callback, state);
        }
    }
}

添加user控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;

namespace Wolfy.Lang.Controllers
{
    public class UserController : BaseController
    {
        // GET: User
        public ActionResult Index()
        {
            ViewBag.submit = Resources.Languages.Submit;
            HttpCookie cookie = Request.Cookies["lang"];
            if (cookie == null)
            {
                //默认中文
                cookie = new HttpCookie("lang", "zh") { Expires = DateTime.Now.AddDays(1) };
                Response.Cookies.Add(cookie);
            }
            return View();
        }
    }
}

对应的视图

@model Wolfy.Lang.Models.UserInfo

@{
    Layout = null;
    var culture = System.Threading.Thread.CurrentThread.CurrentCulture.Name.ToLowerInvariant();
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")


    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
          
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">

                    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Gender, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Gender, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Gender, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="@ViewBag.submit" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
</body>
</html>

 测试

通过切换cookie中lang的值进行语言的切换

切换英文

 

修改cookie中lang字段对应的值为en-US

 总结

之前,国际化都是通过angularjs的方式在前端实现的,今天尝试下mvc中的实现方式。这里需要注意的,在使用特性Display的ResourceType参数时,需要指定Languages是public的,默认是interval,需要修改可访问性。

相关文章:

  • springIOC学习笔记
  • 云服务器Windows 2012 IIS添加站点绑定域名的方法?
  • 用香蕉也能玩电脑游戏—Tensorflow对象检测接口的简单应用
  • 《学习opencv》笔记——矩阵和图像操作——cvSetIdentity,cvSolve,cvSplit,cvSub,cvSubS and cvSubRS...
  • JSF导航规则
  • WebBrowser 安全
  • 四种LaunchMode及其使用场景
  • 常用命令及小技巧等
  • 探究redux源码-衍生-中间件思想
  • 内置方法(1)
  • MYSQL汇总
  • online
  • Visual Studio 15.4发布,新增多平台支持
  • 麦克阿瑟天才奖得主解码计算机视觉“原罪”:AI 如何认识人类世界
  • php 二维数组排序/对数组分组
  • [译] 怎样写一个基础的编译器
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • express + mock 让前后台并行开发
  • HTTP中的ETag在移动客户端的应用
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • oschina
  • Promise面试题2实现异步串行执行
  • React Native移动开发实战-3-实现页面间的数据传递
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 彻底搞懂浏览器Event-loop
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 好的网址,关于.net 4.0 ,vs 2010
  • 回流、重绘及其优化
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 做一名精致的JavaScripter 01:JavaScript简介
  • #pragma data_seg 共享数据区(转)
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (三)uboot源码分析
  • (学习日记)2024.02.29:UCOSIII第二节
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)人的集合论——移山之道
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .bashrc在哪里,alias妙用
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET 设计一套高性能的弱事件机制
  • .NET文档生成工具ADB使用图文教程
  • .NET运行机制
  • :中兴通讯为何成功
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • [ 第一章] JavaScript 简史
  • []Telit UC864E 拨号上网
  • [AIGC] 开源流程引擎哪个好,如何选型?