实现国际化有三种做法:

  1. 创建资源文件。
  2. 每种语言设置一套单独的View。
  3. 1 + 2。

通常而言,第一种方法的可维护性是最高的。因为随着项目的规模的扩大,为每种语言设置一套单独的View,前期的工作量和后期的维护成本都会太高。

但是如果只采用资源文件的做法,在某些场合下,View的显示会出现问题,诸如一些文字次序是从右到左显示的语言,很显然仅仅更换文字内容也是不合适的。

所以,最终采取何种方式还是要看具体的项目情况而定。接下去的内容只针对第一种做法。

概括起来,有如下步骤:

  1. 创建资源文件
  2. Controller中添加国际化的支持
  3. 配置View

============ Action Now! ============

1. 创建资源文件

1) 不要将资源文件添加到现有的项目中,而是新建一个Class Library的项目, 这样可以在日后复用此资源文件到其它项目中。

2) 创建资源文件。资源文件名可以自由定义,在这里我创建一个名为Resources.resx的资源文件,做为默认的资源文件,通常用于英文。然后再定义一个Resources.zh-CN.resx的资源文件,用于中文。在这里我们可以看出资源文件定义的规律,即Resources.[编码名].resx。创建结果如下:

2. Controller中添加国际化的支持

1) 创建BaseController文件,做为所有Controller的父类。

     public class BaseController : Controller

     {

         protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)

         {

             string cultureName = null;

             // Attempt to read the culture cookie from Request

             HttpCookie cultureCookie = Request.Cookies["_culture"];

             if (cultureCookie != null)

                 cultureName = cultureCookie.Value;

             else

                 cultureName = Request.UserLanguages != null && Request.UserLanguages.Length >  ?

                         Request.UserLanguages[] :  // obtain it from HTTP header AcceptLanguages

                         null;

             // Validate culture name

             cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe

             // Modify current thread's cultures           

             Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);

             Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

             return base.BeginExecuteCore(callback, state);

         }

 }

2) 将每个Controller的父类改为BaseController。

3) 可选。实现设置语言Cookie的方法,这样用户就可以通过自定义语言,而不是只能依赖浏览器的默认语言。

         public ActionResult SetCulture(string culture)

         {

             // Validate input

             culture = CultureHelper.GetImplementedCulture(culture);

             // Save culture in a cookie

             HttpCookie cookie = Request.Cookies["_culture"];

             if (cookie != null)

                 cookie.Value = culture;   // update cookie value

             else

             {

                 cookie = new HttpCookie("_culture");

                 cookie.Value = culture;

                 cookie.Expires = DateTime.Now.AddYears();

             }

             Response.Cookies.Add(cookie);

             return RedirectToAction("Index");

         } 

 4) 创建CultureHelper.cs。

     public static class CultureHelper

     {

         // Valid cultures

         private static readonly List<string> _validCultures = new List<string> { "af", "af-ZA", "sq", "sq-AL", "gsw-FR", "am-ET", "ar", "ar-DZ", "ar-BH", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", "ar-SY", "ar-TN", "ar-AE", "ar-YE", "hy", "hy-AM", "as-IN", "az", "az-Cyrl-AZ", "az-Latn-AZ", "ba-RU", "eu", "eu-ES", "be", "be-BY", "bn-BD", "bn-IN", "bs-Cyrl-BA", "bs-Latn-BA", "br-FR", "bg", "bg-BG", "ca", "ca-ES", "zh-HK", "zh-MO", "zh-CN", "zh-Hans", "zh-SG", "zh-TW", "zh-Hant", "co-FR", "hr", "hr-HR", "hr-BA", "cs", "cs-CZ", "da", "da-DK", "prs-AF", "div", "div-MV", "nl", "nl-BE", "nl-NL", "en", "en-AU", "en-BZ", "en-CA", "en-029", "en-IN", "en-IE", "en-JM", "en-MY", "en-NZ", "en-PH", "en-SG", "en-ZA", "en-TT", "en-GB", "en-US", "en-ZW", "et", "et-EE", "fo", "fo-FO", "fil-PH", "fi", "fi-FI", "fr", "fr-BE", "fr-CA", "fr-FR", "fr-LU", "fr-MC", "fr-CH", "fy-NL", "gl", "gl-ES", "ka", "ka-GE", "de", "de-AT", "de-DE", "de-LI", "de-LU", "de-CH", "el", "el-GR", "kl-GL", "gu", "gu-IN", "ha-Latn-NG", "he", "he-IL", "hi", "hi-IN", "hu", "hu-HU", "is", "is-IS", "ig-NG", "id", "id-ID", "iu-Latn-CA", "iu-Cans-CA", "ga-IE", "xh-ZA", "zu-ZA", "it", "it-IT", "it-CH", "ja", "ja-JP", "kn", "kn-IN", "kk", "kk-KZ", "km-KH", "qut-GT", "rw-RW", "sw", "sw-KE", "kok", "kok-IN", "ko", "ko-KR", "ky", "ky-KG", "lo-LA", "lv", "lv-LV", "lt", "lt-LT", "wee-DE", "lb-LU", "mk", "mk-MK", "ms", "ms-BN", "ms-MY", "ml-IN", "mt-MT", "mi-NZ", "arn-CL", "mr", "mr-IN", "moh-CA", "mn", "mn-MN", "mn-Mong-CN", "ne-NP", "no", "nb-NO", "nn-NO", "oc-FR", "or-IN", "ps-AF", "fa", "fa-IR", "pl", "pl-PL", "pt", "pt-BR", "pt-PT", "pa", "pa-IN", "quz-BO", "quz-EC", "quz-PE", "ro", "ro-RO", "rm-CH", "ru", "ru-RU", "smn-FI", "smj-NO", "smj-SE", "se-FI", "se-NO", "se-SE", "sms-FI", "sma-NO", "sma-SE", "sa", "sa-IN", "sr", "sr-Cyrl-BA", "sr-Cyrl-SP", "sr-Latn-BA", "sr-Latn-SP", "nso-ZA", "tn-ZA", "si-LK", "sk", "sk-SK", "sl", "sl-SI", "es", "es-AR", "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-SV", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PY", "es-PE", "es-PR", "es-ES", "es-US", "es-UY", "es-VE", "sv", "sv-FI", "sv-SE", "syr", "syr-SY", "tg-Cyrl-TJ", "tzm-Latn-DZ", "ta", "ta-IN", "tt", "tt-RU", "te", "te-IN", "th", "th-TH", "bo-CN", "tr", "tr-TR", "tk-TM", "ug-CN", "uk", "uk-UA", "wen-DE", "ur", "ur-PK", "uz", "uz-Cyrl-UZ", "uz-Latn-UZ", "vi", "vi-VN", "cy-GB", "wo-SN", "sah-RU", "ii-CN", "yo-NG" };

         // Include ONLY cultures you are implementing

         private static readonly List<string> _cultures = new List<string> {

             "zh-CN",

             "en-US",

         };

         /// <summary>

         /// Returns true if the language is a right-to-left language. Otherwise, false.

         /// </summary>

         public static bool IsRighToLeft()

         {

             return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.IsRightToLeft;

         }

         /// <summary>

         /// Returns a valid culture name based on "name" parameter. If "name" is not valid, it returns the default culture "en-US"

         /// </summary>

         /// <param name="name" />Culture's name (e.g. en-US)</param>

         public static string GetImplementedCulture(string name)

         {

             // make sure it's not null

             if (string.IsNullOrEmpty(name))

                 return GetDefaultCulture(); // return Default culture

             // make sure it is a valid culture first

             if (_validCultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Count() == )

                 return GetDefaultCulture(); // return Default culture if it is invalid

             // if it is implemented, accept it

             if (_cultures.Where(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)).Count() > )

                 return name; // accept it

             // Find a close match. For example, if you have "en-US" defined and the user requests "en-GB",

             // the function will return closes match that is "en-US" because at least the language is the same (ie English) 

             var n = GetNeutralCulture(name);

             foreach (var c in _cultures)

                 if (c.StartsWith(n))

                     return c;

             // else

             // It is not implemented

             return GetDefaultCulture(); // return Default culture as no match found

         }

         /// <summary>

         /// Returns default culture name which is the first name decalared (e.g. en-US)

         /// </summary>

         /// <returns></returns>

         public static string GetDefaultCulture()

         {

             return _cultures[]; // return Default culture

         }

         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.Length < )

                 return name;

             return name.Substring(, ); // Read first two chars only. E.g. "en", "es"

         }

 }

注意_cultures数组里的是当前系统支持的语言。

3. 配置View

1) 在MVC项目中添加对Resources项目的引用。

2) 修改View目录下的web.config文件,在pages下添加namespace=Resources。这样在View中就能够直接引用Resources。

     <pages pageBaseType="System.Web.Mvc.WebViewPage">

       <namespaces>

         <add namespace="System.Web.Mvc" />

         <add namespace="System.Web.Mvc.Ajax" />

         <add namespace="System.Web.Mvc.Html" />

         <add namespace="System.Web.Optimization"/>

         <add namespace="System.Web.Routing" />

         <add namespace="Resources" />

       </namespaces>

     </pages>

3)       在View中需要的地方写@Resources.[key]。例如:

 <div class="jumbotron">

     <h1>@Resources.ApplicationName</h1>

     <p><a href="http://asp.net" class="btn btn-primary btn-large">@Resources.Expose</a></p>

 </div>

完工。本文忽略了设置语言的前端实现,和后台的资源文件内容的提取。如果有想要知道的朋友,可以提出来,我会另外再写一篇做介绍。

实现MVC.NET 5的国际化的更多相关文章

  1. Spring MVC基础知识整理➣国际化和异常处理

    概述 Spring框架为WEB项目提供了国际化以及异常处理机制.所谓的国际化也就是不同国籍,显示不同国籍的语言与符号.异常处理,也就是能够捕获WEB项目下的所有异常信息,并能处理记录这些异常信息机制. ...

  2. JSR教程2——Spring MVC数据校验与国际化

    SpringMVC数据校验采用JSR-303校验. • Spring4.0拥有自己独立的数据校验框架,同时支持JSR303标准的校验框架. • Spring在进行数据绑定时,可同时调用校验框架完成数据 ...

  3. Spring MVC(十五)--SpringMVC国际化配置项

    Spring MVC中,当DispatcherServlet初始化的时候,会解析一个LocaleResolver接口的实现类,这个实现类就是用来解析国际化的. 一.国际化解析器 Spring MVC中 ...

  4. ASP.NET MVC之国际化(十一)

    前言 在项目中遇到国际化语言的问题是常有的事情,之前在做关于MVC国际化语言时,刚开始打算全部利用AngularJS来实现,但是渐渐发现对于页面Title难以去控制其语言转换,于是对于页面Tiltle ...

  5. MVC之国际化

    MVC之国际化 前言 在项目中遇到国际化语言的问题是常有的事情,之前在做关于MVC国际化语言时,刚开始打算全部利用AngularJS来实现,但是渐渐发现对于页面Title难以去控制其语言转换,于是对于 ...

  6. Spring MVC + Velocity实现国际化配置

    国际化介绍 web开发中,国际化是需要考虑的一个问题,而且这个问题一般是越早敲定越好(不然等到系统大了,翻译是个问题).下面是结合实际项目(Spring MVC+Velocity)对实现国际化的一些总 ...

  7. 前端系列——jquery前端国际化解决方案“填坑日记”

    前言:最近,新的平台还没有开发完成,原来的老项目又提出了新的需求:系统国际化.如果是前后端完全分离的开发模式,要做国际化,真的太简单了,有现成的解决方案,基于Node构建的时下热门的任何一种技术选型都 ...

  8. jquery.i18n.properties前端国际化解决方案“填坑日记”

    但现在的情况是老的项目并没有使用这类架构.说起国际化,博主几年前就做过,在MVC里面实现国际化有通用的解决方案,主要就是通过资源文件的方式定义多语言.最初接到这个任务,并没有太多顾虑,毕竟这种东西有很 ...

  9. 前端系列——jquery.i18n.properties前端国际化解决方案“填坑日记”

    前言:最近,新的平台还没有开发完成,原来的老项目又提出了新的需求:系统国际化.如果是前后端完全分离的开发模式,要做国际化,真的太简单了,有现成的解决方案,基于Node构建的时下热门的任何一种技术选型都 ...

随机推荐

  1. Akka源码分析-local-DeathWatch

    生命周期监控,也就是死亡监控,是akka编程中常用的机制.比如我们有了某个actor的ActorRef之后,希望在该actor死亡之后收到响应的消息,此时我们就可以使用watch函数达到这一目的. c ...

  2. InterferenceSignal-----------挺简单的 一道题 就是英语不好

    InterferenceSignal 时间限制: 2000ms内存限制: 128000KB 64位整型: Java 类名: 上一题 提交 运行结果 统计 讨论版 下一题 类型: 没有 添加 题目描述 ...

  3. Coursera公开课-Machine_learing:编程作业

    第二周编程作业:Linear Regression 分为单一变量和多变量,假想函数为:hθ(x)=θ0+θ1x1+θ2x2+θ3x3+⋯+θnxn.明显已经包含单一变量的情况,所以完成多变量可以一并解 ...

  4. jQuery封装的选项卡方法

    ********************************************************2018/3/15更新********************************* ...

  5. Java中常用的操作PDF的类库

    iText iText是一个能够快速产生PDF文件的java类库.iText的java类对于那些要产生包含文本,表格,图形的只读文档是很有用的.它的类库尤其与java Servlet有很好的给合.使用 ...

  6. CAD绘制一个线型标注(com接口VB语言)

    主要用到函数说明: _DMxDrawX::DrawDimRotated 绘制一个线型标注.详细说明如下: 参数 说明 DOUBLE dExtLine1PointX 输入第一条界线的起始点X值 DOUB ...

  7. 10java内存

    java内存 1.栈---存储的是变量(不仅仅只有变量),不会对存储的内容进行赋值,存储的内容使用完成之后会立即进行清除 2.堆---存储的是对象.会对存储的内容进行赋值,存储内容使用完成之后会在某个 ...

  8. UGUI世界坐标转换为UI本地坐标(游戏Hud的实现)

    实现世界坐标的原理是: 世界坐标和UGUI的坐标分属两个坐标系,他们之间是无法进行转换的,需要通过屏幕坐标系来进行转换(因为屏幕坐标是固定的),即先将游戏场景中的世界坐标通过游戏场景Camera转化为 ...

  9. 怎么选择最适合自己的Linux培训机构?

    Linux培训已经成为入门Linux的一个重要途径,它的优势在于学习知识的系统性.快速性和实用性.Linux培训毕业的学员大多数拥有较强的实战动手能力,能够较快上手,更符合企业需求. 不过,大部分同学 ...

  10. webpack核心概念使用的综合小案例

    注: 由于版本更新很快,同样的配置不同版本很可能会出错(这个就很绝望了) 解决思路 看文档 查看源码接口 网上搜索相应错误 环境 webpack4.x + yarn 文件结构 . ├── dist / ...