我正在使用带有本地化功能的 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.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
我在这里想念什么?这似乎不是预期的行为。