如何使用RouteDataRequestCultureProvider

一日,想做多语言的站点,使用.net core 3.1,目前最新的东西^_^。

希望使用的地址是这样的:https://localhost:6001/zh-cn/home/index

1. 在 ConfigureServices 里加如下代码:

services.AddLocalization(options => options.ResourcesPath = "Resources");//多语言的资源文件放在 Resources 文件夹下,是一些 resx 文件

            var builder = services.AddControllersWithViews()
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                .AddDataAnnotationsLocalization();

            var supportedCultures = new[]
            {
                new CultureInfo("zh-cn"),
                new CultureInfo("en"),
            };
            services.Configure<RequestLocalizationOptions>(options =>
            {
                options.DefaultRequestCulture = new RequestCulture(culture: "zh-cn", uiCulture: "zh-cn");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
                options.RequestCultureProviders.Clear();
                options.AddInitialRequestCultureProvider(new RouteDataRequestCultureProvider()//url里的地址参数是 lang,特别注意该参数不是存在于 querystring 里的而是在 path 里的。这个比较重要,下面会用到。
                {
                    Options = options,
                    RouteDataStringKey = "lang",
                    UIRouteDataStringKey = "lang"
                });
            });

2. 在 Configure 里加如下代码:

app.UseRequestLocalization(); //因为上面使用了 RouteDataRequestCultureProvider,所以本行代码一定要加在 app.UseRouting() 下面!!!否则将不生效!

3. 接2,同样在 Configure 里加代码。在 UseEndpoints 里加入如下一节:

endpoints.MapControllerRoute(
    name: "en",
    pattern: "{lang=zh-cn}/{controller=Home}/{action=Index}/{id?}");

4. 在项目下建 Resources 文件夹,里面再建 Controllers.HomeController.en.resx 类似的资源文件。

5. 在 HomeController 里加:

private readonly IStringLocalizer<AboutController> _localizer;

并从构造函数里注入,不表。

6. 使用多言语:

ViewBag.TestTitle = _localizer["关于标题"];

7. 还可以在 View 里使用:

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

 

碰到的问题就是一开始并没有把 app.UseRequestLocalization() 放到 app.UseRouting() 的后面而是放到了 Configure 里的第一行,所以一直死活不生效,为什么?

仔细想想,我使用的是 RouteDataRequestCultureProvider,看看这名字吧:RouteDataXXX,是不是和 Route 有关?而 Configure 里不就是配置所有中间件的地方吗?中间件执行是不是有先后顺序啊?那是不是先配置的先执行啊?一上来就想执行 UseRequestLocalization 这个中间件,还没有经过 Route 这一步,显然是 RouteData 还没解析好啊!

还去看了下 RouteDataRequestCultureProvider 的源码:https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/Localization.Routing/src/RouteDataRequestCultureProvider.cs,非常简单,实在没有出错的理由,那只能是自己用错了。

所以就去看 Routing 的文档了:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-3.1,很官方!仔细看还是有收获的。

备忘,以上。

posted @ 2020-03-28 16:28  透明飞起来了  阅读(605)  评论(0编辑  收藏  举报