如何在 ASP.NET Core MVC 请求期间手动设置 Culture?

问题描述 投票:0回答:3

我正在寻找类似的东西,比如设置文化的旧行为和在那之后请求中的一切都有那个文化。

类似于 ASP.NET 4.5:

Thread.CurrentThread.CurrentCulture     = culture_info; 
Thread.CurrentThread.CurrentUICulture   = culture_info;

当我现在这样做时,一些代码似乎在 MVC 管道的不同点不断地将 Culture 重置为英语。

我为什么要那个?因为我想通过我的扩展路由逻辑在一个非常大的(和可定制的)平台类型的 Web 项目中设置文化。

默认的 RouteDataRequestCultureProvider 似乎根本不起作用 - 请参阅此处的解释:

https://irensaltali.com/en/asp-net-core-mvc-localization-by-url-routedatarequestcultureprovider/

本地化在通过 QueryString 设置文化时起作用,但在文化在路线中时不起作用

我不想使用作为解决方案呈现的“硬编码”url 解析,因为我的路由逻辑很复杂——不是 all 路由将在 URL 的同一位置定义文化。

我试过设置这个,但也没用:

httpContext.Features.Set<IRequestCultureFeature>(new RequestCultureFeature(request_culture, new DummyProvider()));

是否有任何解决方法可以简单为请求的其余部分设置文化?

asp.net-core asp.net-core-mvc asp.net-mvc-routing culture
3个回答
1
投票

为请求的其余部分简单设置文化的解决方法是使用默认

QueryStringRequestCultureProvider
.

这是整个演示:

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalization(options => options.ResourcesPath = "Resources");

    services.AddControllersWithViews()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();
    //...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("de"),
        new CultureInfo("fr"),
    };

    app.UseRequestLocalization(new RequestLocalizationOptions
    {
        DefaultRequestCulture = new RequestCulture("en-US"),
        // Formatting numbers, dates, etc.
        SupportedCultures = supportedCultures,
        // UI strings that we have localized.
        SupportedUICultures = supportedCultures
    });

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

创建资源文件夹并添加资源文件如下:

如下配置资源文件:

Controllers.HomeController.de.resx

Controllers.HomeController.fr.resx

参考:资源文件命名

控制器:

public class HomeController : Controller
{
    private readonly IStringLocalizer<HomeController> _localizer;

    public HomeController(IStringLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _localizer["Your Title"];
        return View();
    }
}

Index.cshtml:

@ViewData["Title"]

结果:


1
投票

虽然我也找不到为请求的其余部分设置请求文化的方法,但您可以使用 CustomRequestCultureProvider 并使用自定义路由逻辑来设置请求的文化

app.UseRequestLocalization(options =>
{
    options.AddSupportedUICultures(... set some cultures here...)
           .AddSupportedCultures(... and here...)
           .AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context =>
           {
               string cultureCode = await RunCustomRoutingAndGetCulture(context.Request);
               return new ProviderCultureResult(cultureCode);
           }));
});

如果您的自定义逻辑不需要等待删除异步并返回 Task.FromResult


0
投票

我一直在寻找类似于 OP 在请求后设置文化的问题的解决方案。我需要在查询字符串或请求标头中检索文化字符串,@Stilgar 的回答提供了我需要的解决方案。这是他的答案的有效解决方案。它在查询字符串中提取文化键/值对。 (检查请求标头的代码被省略了。)

对于 URL 请求

https://localhost:7181/?culture=fr
,设置文化
fr-FR
。在
OnPost
方法中,
Thread.CurrentThread.CurrentCulture
返回
fr-FR
.

public void OnPost()
{
    // Display the current culture
    System.Diagnostics.Debug.WriteLine("Current culture is " + Thread.CurrentThread.CurrentCulture.EnglishName);
}

program.cs

app.UseRequestLocalization(options =>
    {
        string defaultCulture = "en-US";
        string[] supportedCultures = new string[] { "fr-FR", defaultCulture };

        options.AddSupportedUICultures(supportedCultures)
            .AddSupportedCultures(supportedCultures)
            .AddInitialRequestCultureProvider(
                new CustomRequestCultureProvider(async context =>
                {
                    string? cultureCode =
                        await GetCultureFromRequest(context.Request, supportedCultures) ?? defaultCulture;
                    return new ProviderCultureResult(cultureCode);
                }));
    });

static Task<string?> GetCultureFromRequest(
    HttpRequest request, string[] supportedCultures)
{
    if (request.QueryString.Value is null ||
        !request.QueryString.Value.Contains("culture="))
    {
        return Task.FromResult<string?>(default);
    }

    string? cultureVal =
        request.Query.FirstOrDefault(q => q.Key == "culture").Value;

    if (cultureVal is null || string.IsNullOrEmpty(cultureVal))
    {
        return Task.FromResult<string?>(default);
    }

    string? cultureEntry = supportedCultures
        .Where(c => c.Contains(cultureVal)).FirstOrDefault();

    return Task.FromResult(cultureEntry ?? default);
}

上述解决方案与设置找到的本地化中间件相同here

program.cs

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    CultureInfo[] supportedCultures = new[]
     {
        new CultureInfo("fr"),
    };
    options.DefaultRequestCulture = new RequestCulture("en-US");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.RequestCultureProviders.Insert(0, new QueryStringRequestCultureProvider());
});

IOptions<RequestLocalizationOptions> locOptions = builder.Services.BuildServiceProvider().GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
© www.soinside.com 2019 - 2024. All rights reserved.