ASP.Net 核心 CookieRequestCultureProvider 不工作

ASP.Net Core CookieRequestCultureProvider not working

我有一个 ASP.Net Core 3.1 应用程序,具有以下 startup.cs(我根据网络搜索尝试了以下配置的各种组合):

public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.Configure<RequestLocalizationOptions>(options =>
        {
            options.RequestCultureProviders = new[] { new CookieRequestCultureProvider() };
        });

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...
            var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
            app.UseRequestLocalization(options.Value);

并且在我的应用程序的登录方法中,我将 Culture Cookie 设置如下:

HttpContext.Response.Cookies.Append(
                            CookieRequestCultureProvider.DefaultCookieName,
                            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture([logged-in-user].CultureCode)));

在后续请求中,我可以在我的浏览器开发工具网络选项卡中看到 cookie:

然而,在服务器上,任何给定的请求仍然为我的开发环境维护默认服务器文化(即 en-ZA)。 (我通过检查服务器操作方法中的任何断点中的 System.Threading.Thread.CurrentThread.CurrentCulture.Name 看到了这一点)

我 运行 遇到客户端和服务器之间的日期转换问题(例如,根据上面的屏幕截图,具有 en-US 文化的客户端)发送日期 3/5/2009 (3 月 5 日)到服务器,服务器将其解释为 5 月 3 日。

为什么我的服务器不支持 CultureCookie?我错过了什么?

如您所述,您已在 ConfigureServices 方法中注册了本地化服务。

我建议的方法是像这样使用它:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services
    .AddControllersWithViews()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();

但不要忘记注册中间件:

// In StartUp.cs Configure method
var SupportedCultures = new CultureInfo[]
{
    new CultureInfo("en"),
    new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(defaultLanguage),
    SupportedCultures = SupportedCultures,
    SupportedUICultures = SupportedCultures
});

关于您的 cookie 结束时间问题,请尝试指定您的 cookie 的结束日期。像这样:

Response.Cookies.Append(
    CookieRequestCultureProvider.DefaultCookieName,
    CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
                    new CookieOptions
                    {
                        Expires = DateTimeOffset.UtcNow.AddYears(1),
                        SameSite = SameSiteMode.None
                    });

我在 asp.net 核心 6.0.

感谢Anduin的回复,对我帮助很大! official doc 具有误导性。

我发现对我来说关键点是:

  1. 服务配置:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("zh-CN")
    };
    options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});
  1. 应用支持:
var SupportedCultures = new[]
{
    new CultureInfo("en"),
    new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"),
    SupportedCultures = SupportedCultures,
    SupportedUICultures = SupportedCultures
});
  1. 具有语言名称但没有 ISO 代码的资源文件:
.\Resources\Controllers\HomeController.zh.resx
.\Resources\Views\Home\Index.zh.resx
  1. 使用 Ajax 以编程方式更改区域性(我添加了一个空默认值):
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = new List<SelectListItem>();
    cultureItems.Add(new SelectListItem { Value = "", Text = Localizer["Select Lang"].Value });
    cultureItems.AddRange(LocOptions.Value.SupportedUICultures
        .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>
</div>
        [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);
        }
  1. IStringLocalizer(我保留了可移动的 _logger):
        private readonly ILogger<HomeController> _logger;
        private readonly IStringLocalizer<HomeController> _localizer;
        public HomeController(ILogger<HomeController> logger, IStringLocalizer<HomeController> localizer)
        {
            _localizer = localizer;
            _logger = logger;
        }
        public IActionResult Index()
        {
            ViewData["Message"] = _localizer["Test Text"];
            return View();
        }
  1. index.cshtml 中的 IViewLocalizer:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = Localizer["Title Text"];
}

并在资源文件中定义键Test TextTitle Text