asp.net-core 通过网址路径设置请求区域性

示例

默认情况下,内置的“请求本地化”中间件仅支持通过查询,Cookie或Accept-Language标头设置区域性。这个例子展示了如何创建一个中间件,该中间件可以将文化设置为路径中的一部分,例如in /api/en-US/products。

此示例中间件假定语言环境位于路径的第二段中。

public class UrlRequestCultureProvider : RequestCultureProvider
{
    private static readonly Regex LocalePattern = new Regex(@"^[a-z]{2}(-[a-z]{2,4})?$",
                                                        RegexOptions.IgnoreCase);

    public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        var url = httpContext.Request.Path;

        // 目前无法使用httpContext.GetRouteData()
        // 因为它使用放在httpContext.Features中的IRoutingFeature
        //路由中间件寄存器。本地化中间件时未设置
        // 被调用,因此此示例仅假设语言环境将始终 
        // 位于路径的第二段,例如/ api / en-US / products
        var parts = httpContext.Request.Path.Value.Split('/');
        if (parts.Length < 3)
        {
            return Task.FromResult<ProviderCultureResult>(null);
        }

        if (!LocalePattern.IsMatch(parts[2]))
        {
            return Task.FromResult<ProviderCultureResult>(null);
        }

        var culture = parts[2];
        return Task.FromResult(new ProviderCultureResult(culture));
    }
}

中间件注册

var localizationOptions = new RequestLocalizationOptions
{
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("de-DE"),
        new CultureInfo("en-US"),
        new CultureInfo("en-GB")
    },
    SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("de-DE"),
        new CultureInfo("en-US"),
        new CultureInfo("en-GB")
    },
    DefaultRequestCulture = new RequestCulture("en-US")
};

// 将我们的UrlRequestCultureProvider添加为列表中的第一个对象
localizationOptions.RequestCultureProviders.Insert(0, new UrlRequestCultureProvider
{
    Options = localizationOptions
});

app.UseRequestLocalization(localizationOptions);

自定义路线约束

“路线约束”示例中显示了如何添加和创建自定义路线约束。使用约束简化了自定义路由约束的使用。

注册路线

在不使用自定义约束的情况下注册路线的示例

app.UseMvc(routes => 
{ 
    routes.MapRoute( 
        name: "default", 
        template: "api/{culture::regex(^[a-z]{{2}}-[A-Za-z]{{4}}$)}}/{controller}/{id?}"); 
    routes.MapRoute( 
        name: "default", 
        template: "api/{controller}/{id?}"); 
});