【发布时间】:2022-01-10 09:32:26
【问题描述】:
我正在使用带有本地化功能的 Core 6.0 开发一个 Web API 项目。
我使用了一些在线指南,主要是this one
我正在为资源使用外部库。
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.resx 与 TEST 键作为 This is english 作为值
App.he-IL.resx 以 TEST 键为 This is hebrew 为值
App.ru-RU.resx 以 TEST 键为 This is russian 为值
当使用options.DefaultRequestCulture = new RequestCulture(culture: "en-US") 时,account/Test/he-IL 和account/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 文化。
我在这里缺少什么?这似乎不是预期的行为。
【问题讨论】:
标签: c# localization asp.net-core-webapi asp.net-core-6.0