探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式
如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持。接下来通过一个实例来讲述实践方式。
首先创建一个ASP.NET MVC5应用程序,命名为Internationalization:
然后在Models中添加一个示例的模型类:
public class Employee
{
[Display(Name = "Name", ResourceType = typeof(Resources.Resource))]
[Required(ErrorMessageResourceType = typeof(Resources.Resource),
ErrorMessageResourceName = "NameRequired")]
public string Name { get; set; }
}
这里提到了Resources.Resource命名空间,接下来就创建它:
这是一个单独的项目,用来存放各种语言的资源文件,我们创建了三个资源文件,分别存放了中文(默认)、英文和阿拉伯文,资源文件中存放了如下资源项:
注意:这里的资源因为需要在项目外部使用,所以需要将访问修饰符修改为Public
接下来就是如何来确定访问者要使用的语言了,在每个请求中,都会有一个Accept-language的头,其中定义了可接受的语言类型,但是我们仅可以从它来判断浏览器中设置的语言,而这个语言类型可能并不是访问者实际需要的语言类型,所以,我们将设计一个可供选择的语言列表,然后在服务器端使用发回Cookie的方式保存浏览器端实际需要的语言。
首先需要创建一个CultureHelper类,这个类的功能就是来判断访问者实际需要的语言类型:
public class CultureHelper
{
private static readonly List<string> validCultures = new List<string>() { "zh-cn", "en-us","ar" };
private static readonly List<string> cultures = new List<string>() { "zh-cn", "en-us","ar" }; public static bool IsRightToLeft()
{
return Thread.CurrentThread.CurrentCulture.TextInfo.IsRightToLeft;
} public static string GetImplementedCulture(string name)
{
if (string.IsNullOrEmpty(name))
{
return GetDefaultCulture();
}
if (!validCultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any())
{
return GetDefaultCulture();
}
if (cultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Any())
{
return name;
}
var n = GetNeutralCulture(name);
foreach (var c in cultures)
{
if (c.StartsWith(n))
{
return c;
}
}
return GetDefaultCulture();
} public static string GetDefaultCulture()
{
return cultures[];
} public static string GetCurrentCulture()
{
return Thread.CurrentThread.CurrentCulture.Name;
} public static string GetCurrentNeutralCulture()
{
return GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
} public static string GetNeutralCulture(string name)
{
if (!name.Contains("-"))
{
return name;
}
else
{
return name.Split('-')[];
}
} }
接下来创建一个BaseController类,并且确保之后创建的所有控制器继承自它:
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
string cultureName = string.Empty;
HttpCookie cultureCookie = Request.Cookies["_culture"];
if (cultureCookie != null)
{
cultureName = cultureCookie.Value;
}
else
{
cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > ?
Request.UserLanguages[] : null;
}
cultureName = CultureHelper.GetImplementedCulture(cultureName);
Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback,state);
}
}
创建一个EmployeeController,作为多语言实践的一个示例:
public class EmployeeController : BaseController
{
//
// GET: /User/
public ActionResult Index()
{
return View();
} public ActionResult SetCulture(string culture)
{
culture = CultureHelper.GetImplementedCulture(culture);
HttpCookie cookie = Request.Cookies["_culture"];
if (cookie != null)
{
cookie.Value = culture;
}
else
{
cookie = new HttpCookie("_culture");
cookie.Value = culture;
cookie.Expires = DateTime.Now.AddDays();
}
Response.Cookies.Add(cookie);
return RedirectToAction("Index");
}
}
在程序包管理控制台中,使用PS命令,安装Bootstrap对RightToLeft文字习惯的支持:
Install-Package Twitter.Bootstrap.RTL
然后在App_Start中的BundleConfig.cs中添加两个资源文字的虚拟捆绑路径:
bundles.Add(new ScriptBundle("~/bundles/bootstrap-rtl").Include(
"~/Scripts/bootstrap-rtl.js",
"~/Scripts/respond.js")); bundles.Add(new StyleBundle("~/Content/css-rtl").Include(
"~/Content/css/bootstrap-rtl.css",
"~/Content/site.css"));
最后,创建Index视图:
@model Internationalization.Models.Employee @{
ViewBag.Title = "Index";
var culture = System.Threading.Thread.CurrentThread.CurrentCulture.Name.ToLowerInvariant();
} @helper selected(string c, string culture)
{
if (c == culture)
{
@:checked="checked"
}
} @*选择语言列表*@
@using (Html.BeginForm("SetCulture", "Employee"))
{
<fieldset>
<legend></legend>
<div class="control-group">
<div class="
">
<label for="zh-cn">
<input name="culture" id="zh-cn" value="zh-cn" type="radio" @selected("zh-cn", culture) /> 中文
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label for="en-us">
<input name="culture" id="en-us" value="en-us" type="radio" @selected("en-us", culture) /> English
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label for="en-us">
<input name="culture" id="ar" value="ar" type="radio" @selected("ar", culture) /> عربي
</label>
</div>
</div> </fieldset>
} @*创建员工表单*@
@using (Html.BeginForm())
{
@Html.AntiForgeryToken() <div class="form-horizontal">
<h2>@Resources.Resource.AddEmployee</h2>
<hr />
@Html.ValidationSummary(true) <div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
</div> <div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
} @*在选择语言后,自动提交*@
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
(function ($) {
$("input[type = 'radio']").click(function () {
$(this).parents("form").submit(); // post form
}); })(jQuery);
</script>
}
还需要更改_Layout.cshtml文件,当文字习惯为右到左时,需要切换bootstrap的样式文件:
<!DOCTYPE html>
<html lang="@Internationalization.Helpers.CultureHelper.GetCurrentNeutralCulture()" dir="@(Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "rtl" : "ltr")">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - 我的 ASP.NET 应用程序</title>
@Styles.Render("~/Content/css" + (Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "-rtl" : ""))
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("应用程序名称", "Index", "Home", null, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("主页", "Index", "Home")</li>
<li>@Html.ActionLink("关于", "About", "Home")</li>
<li>@Html.ActionLink("联系方式", "Contact", "Home")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
</footer>
</div> @Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap" + (Internationalization.Helpers.CultureHelper.IsRightToLeft() ? "-rtl" : ""))
@RenderSection("scripts", required: false)
</body>
</html>
演示效果:
最终DEMO地址:点击这里,感谢园友支持,这一期会一直进行下去的
如果您觉得这篇文章对您有用,劳烦给个赞!
如果您觉得这篇文章可能对别人游泳,劳烦您推荐一个!
如果您觉得这篇文章真扯淡,那么你又给我刷了个访问量!
探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式的更多相关文章
- 探寻ASP.NET MVC鲜为人知的奥秘(2):与Entity Framework配合,让异步贯穿始终
Why 在应用程序,尤其是互联网应用程序中,性能一直是很多大型网站的困扰,由于Web2.0时代的到来,人们更多的把应用程序从C/S结构迁移到B/S结构,这样会带来客户端轻量,部署.试试方便快捷等优势, ...
- 探寻ASP.NET MVC鲜为人知的奥秘(1):对LESS的支持
在ASP.NET MVC3中(从那时开始),我们拥有了对js和css等文件的捆绑(Bundling)和压缩(Minification)的能力,这是ASP.NET性能优化工作的一部分. 想一下很久以前, ...
- 总结ASP.NET MVC Web Application中将数据显示到View中的几种方式
当我们用ASP.NET MVC开发Web应用程序的时候,我们都是将需要呈现的数据通过"Controllers"传输到"View"当中,怎么去实现,下面我介绍一下 ...
- 总结ASP.NET MVC视图页使用jQuery传递异步数据的几种方式
在ASP.NET MVC的视图页向控制器传递异步数据,可能是数组,JavaScript对象,json,表单数据,等等. 关于数据,JavaScript对象有时候和json长得一模一样,有么有? var ...
- ASP.NET MVC异步验证是如何工作的01,jQuery的验证方式、错误信息提示、validate方法的背后
ASP.NET MVC借助jQuery的验证机制,提供了一套从客户端到服务端异步验证的解决方案,通常情况下,用起来相当方便.但面对一些相对特殊的情况,可能会遇到验证失效的场景,比如在使用ajax动态异 ...
- 【jqGrid for ASP.NET MVC Documentation】.学习笔记.3.本地化语言包
1 引用本地化语言包 在 js/i18n 文件夹中,提供了大量预定义的语言包.它包括为所有字符串定义的,包括消息,标题,分页信息,搜索/添加/删除 的对话框 文本等. 在jQuery库文件后,在jqG ...
- asp.net mvc 删除栏目、栏目下又有子栏目的处理方式
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合
今天为大家分享下 Asp.net MVC 将数据从前台传递到后台的几种方式. 环境:VS2013,MVC5.0框架 1.基本数据类型 我们常见有传递 int, string, bool, double ...
随机推荐
- 给trac的ticket添加提交时字段验证
我们在项目管理中使用了trac系统,并且对于ticket添加了以下自定义字段并且对它们的格式都有一定要求: svn版本号:格式为 r1234.多个版本号之间使用半角逗号隔开.如:r1234,r5678 ...
- 【vue】饿了么项目-页面骨架开发
1.页面骨架开发 1.1组件拆分 手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没 ...
- python3对数据库的基本操作
其实Python同Java一样,都有对JDBC操作的API. 注意:我的Python版本为3.6.5 Python2.7是应用比较广的,百度博客上很多相关的例子,所以本次不再列出. 只要是用过Java ...
- fiddler常用功能一
fiddler备忘,好久不用,有些步骤忘记了 1.本机pc,目前ie和chrome都可以直接抓取,但是搜狗浏览器暂时抓不到 2.手机端抓包 (1)设置下代理:fiddler客户端查看下端口,然后在手机 ...
- .gitignore设置不生效
.gitignore git中,如果想要让git忽略某些文件,或不想push到远程库,不让其受版本的控制.可以使用git提供的.gitignore文件进行配置.像这样: 一般情况下,在文件还未修改前, ...
- StackStorm利用CORS null origin获得RCE (CVE-2019-9580)
在2.10.3/2.9.3之前,如果请求的来源未知,我们将返回null,null可以导致某些客户端中来自未知来源的成功请求,允许针对StackStorm API进行XSS样式攻击. (Firefox上 ...
- Web | JavaScript的提升机制
作用对象: 函数和变量的声明. 作用效果: 会将其声明提升到其所在的作用域的最顶端.函数会优先于变量的声明. //函数的提升优于变量的提升 test(); var a=2; function test ...
- vim内替换文件内容
几个常用的方法如下: :%s/foo/bar/g 把全部foo替换为bar,全局替换 :s/foo/bar/g 当前行替换foo为bar :%s/foo/bar/gc 替换每个foo为bar,但需要确 ...
- 洛谷P3690 【模板】Link Cut Tree (LCT)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- javascript对象定义及创建
javascript对象 定义 javascript中的对象,可以理解成是一个键值对的集合,键是调用每个值的名称,值可以是基本变量,还可以是函数和对象. 创建方法 第一种方法 通过顶级Object类来 ...