这系列文章我们主要为我们网站设置多语言以及ASP.NET Core全球化与本地化,这里我们将学习多语言站点,我们将支持三种不同语言和文化,英语,法语和西班牙语。
using System.Globalization; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.Options;接下来,在应用程序中添加如下服务,这个通过AddLocalization()方法完成
builder.Services.AddControllersWithViews() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);你需要在应用程序中指定支持的语言和文化,在AddLocalization() 方法之后配置添加如下代码配置:
// 堆代码 duidaima.com // AddLocalization method builder.Services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("fr"), new CultureInfo("es") }; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; });
CultureInfo类是非常重要,该类提供了具体文化信息,例如:语言、子语言,国家/区域,日历和特定文化关联的信息。我们创建了一个数组支持三种语言文化en-us, fr & es (英语, 法语, 西班牙),并且在数组中设置SupportedCultures 和SupportedUICultures 属性,我们通过使用DefaultRequestCulture属性设置了应用程序默认文化为en-us 。
var locOptions = app.Services.GetService<IOptions<RequestLocalizationOptions>>(); app.UseRequestLocalization(locOptions.Value);Localization中间件必须配置在所有的中间件之前,Localization中间件使用了RequestCultureProviders组件确定当前客户端请求语言文化
AcceptLanguageHeaderRequestCultureProvider – 获取用户在客户浏览器中设置的语言,注意:在后面的章节中,我们将展示如何使用这3个RequestCultureProviders 。
@{ ViewData["Title"] = "Home Page"; } @using Microsoft.AspNetCore.Builder @using Microsoft.AspNetCore.Localization @using Microsoft.Extensions.Options @inject IOptions<RequestLocalizationOptions> LocOptions @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var cultureItems = LocOptions.Value.SupportedUICultures .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName }) .ToList(); } <form id="cultureForm" asp-action="Index"> <label>语言:</label> <select onchange="SetCulture(this.value)" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"> </select> </form> <table class="table culture-table"> <tr> <td>Culture</td> <td> @requestCulture.RequestCulture.Culture.Name </td> </tr> <tr> <td>UICulture</td> <td> @requestCulture.RequestCulture.UICulture.Name </td> </tr> <tr> <td>Date</td> <td> @DateTime.Now.ToLongDateString() </td> </tr> <tr> <td>Currency</td> <td> @(98765.00.ToString("c")) </td> </tr> <tr> <td>Number</td> <td> @(987.87m.ToString("F2")) </td> </tr> </table> <script> function SetCulture(selectedValue) { var culture = "/?culture=" + selectedValue + "&ui-culture=" + selectedValue; document.getElementById("cultureForm").action = culture; document.getElementById("cultureForm").submit(); } </script>首先引入必要的命名空间并且注入IOptions对象到视图,将从Program类获取RequestLocalizationOptions对象,我们获取到了在Program类中设置的所有语言文化的值。
@using Microsoft.AspNetCore.Builder @using Microsoft.AspNetCore.Localization @using Microsoft.Extensions.Options @inject IOptions<RequestLocalizationOptions> LocOptions 接下来,使用Context.Features.Get() 获取客户端请求文化, 在List中填充支持的文化 @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var cultureItems = LocOptions.Value.SupportedUICultures .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName }) .ToList(); }接下来,创建一个表单,表单的id为cultureForm并且这个表单内部有选择控件,该控件绑定了cultureItems,这个下拉框显示所有的支持的语言文化"en-us", "fr" & "es"
<form id="cultureForm" asp-action="Index"> <label>Language:</label> <select onchange="SetCulture(this.value)" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"> </select> </form>选择控件的onchange事件调用了JavaScript方法SetCulture,在javascript的代码中我们把选择的值追加到表单的action之后,最后提交表单。
<script> function SetCulture(selectedValue) { var culture = "/?culture=" + selectedValue + "&ui-culture=" + selectedValue; document.getElementById("cultureForm").action = culture; document.getElementById("cultureForm").submit(); } </script>接下来创建html表格显示用户选择信息
<table class="table culture-table"> <tr> <td>Culture</td> <td> @requestCulture.RequestCulture.Culture.Name </td> </tr> <tr> <td>UICulture</td> <td> @requestCulture.RequestCulture.UICulture.Name </td> </tr> <tr> <td>Date</td> <td> @DateTime.Now.ToLongDateString() </td> </tr> <tr> <td>Currency</td> <td> @(98765.00.ToString("c")) </td> </tr> <tr> <td>Number</td> <td> @(987.87m.ToString("F2")) </td> </tr> </table>你能运行应用程序会看到如下所示:
public IActionResult Cookie() { return View(); } [HttpPost] public IActionResult Cookie(string culture) { Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddMonths(1) } ); return RedirectToAction("Cookie"); }这个action方法有一个字符串类型的参数叫culture,这个参数将获取到用户选择文化值,用户从下拉控件中选择文化。我们使用了MakeCookieValue方法创建一个Cookie,CookieRequestCultureProvider, DefaultCookieName 返回默认Cookie名称,使用它来跟踪用户指定的语言信息。
@using Microsoft.AspNetCore.Builder @using Microsoft.AspNetCore.Localization @using Microsoft.Extensions.Options @inject IOptions<RequestLocalizationOptions> LocOptions @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var cultureItems = LocOptions.Value.SupportedUICultures .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName }) .ToList(); } <form asp-action="Cookie" method="post"> <label>Language:</label> <select name="culture" onchange="this.form.submit()" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"> </select> </form> <table> <tr> <td>Culture</td> <td> @requestCulture.RequestCulture.Culture.Name </td> </tr> <tr> <td>UICulture</td> <td> @requestCulture.RequestCulture.UICulture.Name </td> </tr> <tr> <td>Date</td> <td> @DateTime.Now.ToLongDateString() </td> </tr> <tr> <td>Currency</td> <td> @(12345.00.ToString("c")) </td> </tr> <tr> <td>Number</td> <td> @(123.45m.ToString("F2")) </td> </tr> </table>除了表单现在指向提交到Cookie操作方法之外,其它代码都是相同的,选择控件中显示Program类提供的语言文化,分别是"en-us","fr"和 "es"(英语、法语、西班牙语)。
<form asp-action="Cookie" method="post"> <label>Language:</label> <select name="culture" onchange="this.form.submit()" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"> </select> </form>现在运行应用程序并且在浏览器中打开Cookie视图的url,除了文化在Cookie中提供,没有在url中提供之外,其它完全一样。
<table> <tr> <td>Date</td> <td> @DateTime.Now.ToLongDateString() </td> </tr> <tr> <td>Currency</td> <td> @(12345.00.ToString("c")) </td> </tr> <tr> <td>Number</td> <td> @(123.45m.ToString("F2")) </td> </tr> </table>接下来在控制器中添加Browser方法
public IActionResult Browser() { return View(); }删除.AspNetCore.Culture Cookie从浏览器中。
services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("fr"), new CultureInfo("es") }; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context => { var currentCulture = "en"; var segments = context.Request.Path.Value.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (segments.Length >= 2) { string lastSegment = segments[segments.Length - 1]; currentCulture = lastSegment; } var requestCulture = new ProviderCultureResult(currentCulture); return await Task.FromResult(requestCulture); })); });我们现在在浏览器中做测试,打开3个url在浏览器:
services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("fr"), new CultureInfo("es") }; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; options.AddInitialRequestCultureProvider(new MyCultureProvider()); });MyCultureProvider是自定义类,它将从数据库中获取用户选择的语言文化。
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Localization; namespace AspNetCore.GlobalizationLocalization.Models { public class MyCultureProvider : RequestCultureProvider { public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext) { var current_User = await user_Manager.GetUserAsync(HttpContext.User); string user_culture = TblUserName.Where(c => c.Id == current_User.Id).Select(c => c.Culture).FirstOrDefault(); var requestCulture = new ProviderCultureResult(user_culture); return Task.FromResult(requestCulture); } } }这段代码相当简单,首先前2行获取当前用户文化从数据库中并且设置ProviderCultureResult类。