1 自定义 多语言加载 ,加载中间件
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddMvc() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) .AddDataAnnotationsLocalization(); services.AddSingleton<IStringLocalizerFactory, CacheStringLocalizerFactory>(); services.AddTransient<IStringLocalizer, CacheStringLocalizer>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); var supportedCultures = new[] { "en-US", "es-ES"}; app.UseRequestLocalization(options => options .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures) .SetDefaultCulture(supportedCultures[1]) ); app.UseStaticFiles(); // To configure external authentication, // see: http://go.microsoft.com/fwlink/?LinkID=532715 app.UseAuthentication(); app.UseMvcWithDefaultRoute(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
2. IStringLocalizer
public class CacheStringLocalizer : IStringLocalizer { private readonly ConcurrentDictionary<string, string> _all; private readonly IHostingEnvironment _hostingEnvironment; private readonly LocalizationOptions _options; private readonly string _baseResourceName; private readonly CultureInfo _cultureInfo; public LocalizedString this[string name] => Get(name); public LocalizedString this[string name, params object[] arguments] => Get(name, arguments); public CacheStringLocalizer(IHostingEnvironment hostingEnvironment, LocalizationOptions options, string baseResourceName, CultureInfo culture) { _options = options; _hostingEnvironment = hostingEnvironment; _cultureInfo = culture ?? CultureInfo.CurrentUICulture; _baseResourceName = baseResourceName+ "." + _cultureInfo.Name; _all = GetAll(); } public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) { return _all.Select(t => new LocalizedString(t.Key, t.Value, true)).ToArray(); } public IStringLocalizer WithCulture(CultureInfo culture) { if (culture == null) return this; CultureInfo.CurrentUICulture = culture; CultureInfo.DefaultThreadCurrentCulture = culture; return new JsonStringLocalizer(_hostingEnvironment, _options, _baseResourceName, culture); } private LocalizedString Get(string name, params object[] arguments) { if (_all.ContainsKey(name)) { var current = _all[name]; return new LocalizedString(name, string.Format(_all[name], arguments)); } return new LocalizedString(name, name, true); } private ConcurrentDictionary<string, string> GetAll() { try { return ReadFromCache(); } catch (Exception) { } return new ConcurrentDictionary<string, string>(); } private ConcurrentDictionary<string, string> ReadFromCache() { //TODO read from Cache ConcurrentDictionary<string, string> dic = new ConcurrentDictionary<string, string>(); if (_baseResourceName.Contains("en-US")) { dic.TryAdd("Hello", "enUS-Cache"); dic.TryAdd("FirstColumn", "FirstColumn"); dic.TryAdd("SecondColumn", "SecondColumn"); dic.TryAdd("ThirdColumn", "ThirdColumn"); dic.TryAdd("One", "One"); dic.TryAdd("Two", "Two"); dic.TryAdd("Three", "Three"); } if (_baseResourceName.Contains("es-ES")) { dic.TryAdd("Hello", "esES-Cache"); dic.TryAdd("FirstColumn", "FirstColumn-esES"); dic.TryAdd("SecondColumn", "SecondColumn-esES"); dic.TryAdd("ThirdColumn", "ThirdColumn-esES"); dic.TryAdd("One", "One-esES"); dic.TryAdd("Two", "Two-esES"); dic.TryAdd("Three", "Three-esES"); } return dic; } }
3 IStringLocalizerFactory
public class CacheStringLocalizerFactory : IStringLocalizerFactory { private readonly string _applicationName; private readonly IHostingEnvironment _hostingEnvironment; private readonly LocalizationOptions _options; public CacheStringLocalizerFactory(IHostingEnvironment hostingEnvironment, IOptions<LocalizationOptions> localizationOptions) { if (localizationOptions == null) { throw new ArgumentNullException(nameof(localizationOptions)); } this._hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); this._options = localizationOptions.Value; this._applicationName = hostingEnvironment.ApplicationName; } public IStringLocalizer Create(Type resourceSource) { TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(resourceSource); //Assembly assembly = typeInfo.Assembly; //AssemblyName assemblyName = new AssemblyName(assembly.FullName); string baseResourceName = typeInfo.FullName; baseResourceName = TrimPrefix(baseResourceName, _applicationName + "."); return new CacheStringLocalizer(_hostingEnvironment, _options, baseResourceName, null); } public IStringLocalizer Create(string baseName, string location) { location = location ?? _applicationName; string baseResourceName = baseName; baseResourceName = TrimPrefix(baseName, location + "."); return new CacheStringLocalizer(_hostingEnvironment, _options, baseResourceName, null); } private static string TrimPrefix(string name, string prefix) { if (name.StartsWith(prefix, StringComparison.Ordinal)) { return name.Substring(prefix.Length); } return name; } }
4 HomeController
public class HomeController : Controller { public IActionResult Index() { return View(); } [HttpPost] public IActionResult SetLanguage(string culture, string returnUrl) { Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) } ); return LocalRedirect(returnUrl); } }
5 view
@{ ViewData["Title"] = "Home Page"; } @using Microsoft.AspNetCore.Builder @using Microsoft.AspNetCore.Http.Features @using Microsoft.AspNetCore.Localization @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.Extensions.Options @using System.Globalization @inject IViewLocalizer Localizer @inject IOptions<RequestLocalizationOptions> LocOptions @{ var requestCulture = Context.Features.Get<IRequestCultureFeature>(); var cultureItems1 = LocOptions.Value.SupportedUICultures .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName }) .ToList(); var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("es-ES"), }; var cultureItems = supportedCultures.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName }) .ToList(); var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}"; } <div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name"> <form id="selectLanguage" asp-controller="Home" asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" method="post" class="form-horizontal" role="form"> <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture" onchange="this.form.submit();" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"></select> </form> <label>Hello:</label> <label>@Localizer["Hello"]</label> </div> <div> <table> <thead> <tr> <th>@Localizer["FirstColumn"]</th> <th>@Localizer["SecondColumn"]</th> <th>@Localizer["ThirdColumn"]</th> </tr> </thead> <tbody> <tr> <td>@Localizer["One"]</td> <td>@Localizer["Two"]</td> <td>@Localizer["Three"]</td> </tr> <tr> <td>@Localizer["One"]</td> <td>@Localizer["Two"]</td> <td>@Localizer["Three"]</td> </tr> <tr> <td>@Localizer["One"]</td> <td>@Localizer["Two"]</td> <td>@Localizer["Three"]</td> </tr> </tbody> </table> </div>