0

我正在使用带有本地化功能的 Core 6.0 开发一个 Web API 项目。

我使用了一些在线指南,主要是这个

我正在为资源使用外部库。

Program.cs

builder.Services.AddLocalization();

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    options.DefaultRequestCulture = new RequestCulture(culture: "en-US");
    options.SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en-US"),
        new CultureInfo("he-IL"),
        new CultureInfo("ru-RU")
    };
    options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider { IndexOfCulture = 3 } };
});

builder.Services.Configure<RouteOptions>(options => 
{
    options.ConstraintMap.Add("lang", typeof(LanguageRouteConstraint));
});

WebApplication app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

IOptions<RequestLocalizationOptions>? localizationOptions = app.Services.GetService<IOptions<RequestLocalizationOptions>>();

if (localizationOptions != null)
    app.UseRequestLocalization(localizationOptions.Value);

app.UseRouting();

app.UseAuthorization();

app.MapControllers();

app.Run();

扩展方法:

public class LanguageRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("lang"))
            return false;

        string? culture = values["lang"]?.ToString();
        return culture == "en-US" || culture == "he-IL" || culture == "ru-RU";
    }
}


public class RouteDataRequestCultureProvider : RequestCultureProvider
{
    public int IndexOfCulture;

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

        string? culture = httpContext.Request.Path.Value is not null && httpContext.Request.Path.Value.Split('/').Length > IndexOfCulture ? httpContext.Request.Path.Value?.Split('/')[IndexOfCulture]?.ToString() : null;

        ProviderCultureResult? providerResultCulture = culture is null ? null : new(culture);

        return Task.FromResult(providerResultCulture);
    }
}

控制器:

[Route("[controller]/[action]/{lang:lang?}")]
[ApiController]
public class AccountController : BaseController
{
    public AccountController(IStringLocalizer<LangRes.App> localizer) : base(localizer)
    {
    }

    public async Task<IActionResult> Test()
    {
        return Ok(GetErrorMessage("TEST"));
    }
}

和 BaseController:

[Route("")]
[ApiController]
public class BaseController : ControllerBase
{
    private readonly IStringLocalizer<LangRes.App> localizer;

    public BaseController(IStringLocalizer<LangRes.App> localizer)
    {
        this.localizer = localizer;
    }

    public string GetErrorMessage(string result)
    {
        return localizer.GetString(result);
    }
}

外部库LangRes有一个空App类和

App.en-US.resxTESTThis is english为值

App.he-IL.resxTESTThis is hebrew为值

App.ru-RU.resxTESTThis is russian为值

使用时options.DefaultRequestCulture = new RequestCulture(culture: "en-US"),两者account/Test/he-ILaccount/Test/ru-RU都不匹配,并且本地化程序使用回退en-US,因此响应为This is english

何时options.DefaultRequestCulture = new RequestCulture(culture: "he-IL")使用:

account/Test/ru-RU不匹配并且定位器使用回退he-IL

但是account/Test/en-US确实匹配正确,结果是This is english

何时options.DefaultRequestCulture = new RequestCulture(culture: "ru-RU")使用:

account/Test/he-IL不匹配并且定位器使用回退ru-RU

但是account/Test/en-US确实匹配正确,结果是This is english

调试显示为每个请求RouteDataRequestCultureProvider返回正确的文化。ProviderCultureResult

我在这里想念什么?这似乎不是预期的行为。

4

1 回答 1

0

Web API 控制器的依赖注入IStringLocalizer依赖于UiCulture,而不是Culture.

所以这种不稳定的行为是由于我没有SupportedUICulturesRequestLocalizationOptions.

完全改变Program.cs

List<CultureInfo> supportedCultures = new()
{
    new CultureInfo("en-us"),
    new CultureInfo("he-il"),
    new CultureInfo("ru")
};

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    options.DefaultRequestCulture = new RequestCulture(culture: "ru");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures; // important bit
    options.RequestCultureProviders = new[] { new RouteDataRequestCultureProvider { IndexOfCulture = 3 } };
});
于 2022-03-03T10:01:26.870 回答