我正在尝试构建一个应该以英语和德语提供的ASP.NET Core应用程序。我的问题是IViewLocalizer
总是返回德语文本,即使文化设置为英语。如何获得当前文化的正确文本?
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddLocalization(opt => opt.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var cultures = new[] { new CultureInfo("en"), new CultureInfo("de") };
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en"),
SupportedCultures = cultures,
SupportedUICultures = cultures
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
HomeController.cs
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Index.cshtml
<!DOCTYPE html>
@using Microsoft.AspNetCore.Mvc.Localization;
@inject IViewLocalizer Localizer
<html>
<body>
<h1>@Localizer["Hello, World!"]</h1>
<ul>
<li>CurrentCulture: @System.Globalization.CultureInfo.CurrentCulture</li>
<li>CurrentUICulture: @System.Globalization.CultureInfo.CurrentUICulture</li>
</ul>
</body>
</html>
资源文件位于Resources\Views.Home.Index.de.resx
预期产出:
Hello, World! CurrentCulture: en CurrentUICulture: en
页面输出:
Hallo Welt! CurrentCulture: en CurrentUICulture: en
请求标题:
GET / HTTP/1.1
Host: localhost:61904
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,es;q=0.6,de;q=0.4
答案 0 :(得分:4)
我从昨天起就遇到了同样的问题。
看起来LocalizationProvider无法设置正确的文化。
实现自定义LocalizationProvider后,IViewLocalizer
也开始完美地适用于Views
和ViewComponents
。
我还必须通过以下方式将语言实现到url中:
http://somedomain.com/<2-letter-iso-language-name>/controller/action
这是我做的:
<强> Startup.cs 强>
public static string defaultCulture = "uk-UA";
public static List<CultureInfo> supportedCultures
{
get
{
return new List<CultureInfo> {
new CultureInfo("en-US"),
new CultureInfo("uk-UA"),
new CultureInfo("de-DE") };
}
}
在ConfigureServices
方法中,我添加了CultureToUrlActionFilter()
。它从url检索2个字母的语言代码并设置正确的CultureInfo
。如果网址包含不允许的文化代码,则会重定向到默认文化。
public void ConfigureServices(IServiceCollection services)
{
services
.AddLocalization(options => options.ResourcesPath = "Resources")
.AddMvc(options => { options.Filters.Add(new CultureToUrlActionFilter()); })
.AddViewLocalization()
.AddDataAnnotationsLocalization();
}
在Configure方法中,我设置了自定义本地化提供程序,并将其作为第一个插入提供程序队列中:
var options = new RequestLocalizationOptions() {
DefaultRequestCulture = new RequestCulture(defaultCulture),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures };
options.RequestCultureProviders.Insert(0, new UrlCultureProvider());
app.UseRequestLocalization(options);
如果网址后面没有包含文化代码的网址,我会重定向到http://somedomain/<2-letter-culture-code>
(默认文化版)。网址必须始终指定文化。
路线:
app.UseMvc(routes => {
routes.MapRoute("home_empty", "", defaults: new { culture="", controller = "Home", action = "Redirect" });
routes.MapRoute("home", "{culture}", defaults: new { controller = "Home", action = "Index" });
我在HomeController,Redirect action
中重定向它<强> HomeController.cs 强>
public IActionResult Redirect() {
return RedirectToAction("Index", new { culture = Startup.defaultCulture });
}
<强> UrlCultureProvider.cs 强>
using Microsoft.AspNetCore.Localization;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Globalization;
namespace astika.Models
{
public class UrlCultureProvider: IRequestCultureProvider {
public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
var pathSegments = httpContext.Request.Path.Value.Trim('/').Split('/');
string url_culture = pathSegments[0].ToLower();
CultureInfo ci = Startup.supportedCultures.Find(x => x.TwoLetterISOLanguageName.ToLower() == url_culture);
if (ci == null) ci = new CultureInfo(Startup.defaultCulture);
CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = ci;
var result = new ProviderCultureResult(ci.Name, ci.Name);
return Task.FromResult(result);
}
}
}
<强> CultureToUrlActionFilter.cs 强>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using System;
using System.Globalization;
namespace astika.Models
{
public class CultureToUrlActionFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context) { }
public void OnActionExecuting(ActionExecutingContext context)
{
bool redirect = false;
string culture = context.RouteData.Values["culture"].ToString().ToLower();
redirect = String.IsNullOrEmpty(culture);
if (!redirect)
{
try
{
CultureInfo ci = new CultureInfo(culture);
redirect = Startup.supportedCultures.FindIndex(x => x.TwoLetterISOLanguageName.ToLower() == culture) < 0;
}
catch
{
redirect = true;
}
}
if (redirect)
{
CultureInfo cid = new CultureInfo(Startup.defaultCulture);
context.Result = new RedirectToRouteResult(new RouteValueDictionary(new { culture = cid.TwoLetterISOLanguageName, controller = "Home", action = "Index" }));
}
}
}
}
resx文件都位于同一文件夹中
/Resources/Views.Home.Index.en.resx
/Resources/Views.Home.Index.de.resx
/Resources/Views.Shared.Components.Navigation.Default.en.resx
等