【发布时间】:2017-12-28 01:30:50
【问题描述】:
我正在尝试设置一个 ASP.NET Core MVC 站点以支持多个国家/地区的多语言,例如:
- www.test.com/au/en(澳大利亚,英语)
- www.test.com/au/de(澳大利亚、德语)
为当前用户设置文化,我找到了这段代码
public static class GetRoutesMiddlewareExtensions
{
public static IApplicationBuilder UseGetRoutesMiddleware(this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
var routes = new RouteBuilder(app)
{
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
configureRoutes(routes);
routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
var router = routes.Build();
return app.UseMiddleware<GetRoutesMiddleware>(router);
}
}
public class GetRoutesMiddleware
{
private readonly RequestDelegate next;
private readonly IRouter _router;
public GetRoutesMiddleware(RequestDelegate next, IRouter router)
{
this.next = next;
_router = router;
}
public async Task Invoke(HttpContext httpContext)
{
var context = new RouteContext(httpContext);
context.RouteData.Routers.Add(_router);
await _router.RouteAsync(context);
if (context.Handler != null)
{
httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
{
RouteData = context.RouteData,
};
}
// proceed to next...
await next(httpContext);
}
}
我创建了一个如下所示的 RequestCultureProvider:
public class RequestCultureProvider : IRequestCultureProvider
{
public Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
if (httpContext.GetRouteValue("language") == null)
{
return Task.FromResult(new ProviderCultureResult("en", "en"));
}
var langauge = httpContext.GetRouteValue("language").ToString().ToLower();
return Task.FromResult(new ProviderCultureResult(langauge, langauge));
}
}
设置路线我有这个方法:
private readonly Action<IRouteBuilder> GetRoutes =
routes =>
{
routes.MapRoute(name: "Default",
template: "{area}/{language}/{controller}/{action}",
defaults: new { area = "au", language = "en", controller = "home", action = "Index" },
constraints: new { area = new RequiredRouteConstraint(), language = new RegexRouteConstraint("^(en|de)$") });
};
然后在 Startup.cs 中,在 Configure 中,然后我有
// setup routes
app.UseGetRoutesMiddleware(GetRoutes);
// add localization
var supportedCultures = new List<CultureInfo>() {
new CultureInfo("en"),
new CultureInfo("de"),
};
var requestLocalizationOptions = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(supportedCultures.First()),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
};
requestLocalizationOptions.RequestCultureProviders.Clear();
requestLocalizationOptions.RequestCultureProviders.Add(
new RequestCultureProvider()
);
app.UseRequestLocalization(requestLocalizationOptions);
我不确定它是否相关,但为了以更有条理的方式布局我的视图,我设置了一个如下所示的 CultureViewExpander:
public class CultureViewExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
return viewLocations.Select(s => s.Replace("%1", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName));
}
public void PopulateValues(ViewLocationExpanderContext context)
{
context.Values.Add("Language", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
}
}
它是在 Startup.cs 中的 ConfigureServices 中实现的
services.Configure<RazorViewEngineOptions>(o =>
{
o.ViewLocationExpanders.Add(new CultureViewExpander());
// {0} for the action
// {1} for the controller
// {2} for the area
// %1 for language
o.ViewLocationFormats.Clear();
o.ViewLocationFormats.Add("/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
o.AreaViewLocationFormats.Clear();
o.AreaViewLocationFormats.Insert(0, "/Areas/{2}/Views/{1}/%1/{0}" + RazorViewEngine.ViewExtension);
});
支持的语言工作正常,但是当我导航到 www.test.com/au/fr 时,我只是得到一个空白屏幕,但我需要它来返回 404。我怎样才能让它返回 404路由值无效?
【问题讨论】:
-
您能否展示将
language映射到UI 文化的代码部分?
标签: asp.net-mvc asp.net-core asp.net-core-mvc asp.net-core-2.0