我正在尝试在运行时动态设置
IStringLocalizer
的语言。唯一可用的方法似乎是IStringLocalizer.WithCulture
。但是,尝试使用它会导致弃用警告。
public IStringLocalizer GetLocalizer(string locale) {
this.localizerFactory.Create(typeof(CommonResources)).WithCulture(new CultureInfo(locale));
}
我不是使用ASP,我在一个
IHostedService
中执行此操作,该处理来自另一个源(各种网络聊天API)的用户交互。该服务需要符合管理员为聊天服务器或频道设置的语言(存储在数据库中)。
当前设置
IStringLocalizer
语言的正确方法是什么?我应该完全使用另一个类吗?
这应该可以。在获取字符串值之前,您需要将
CultureInfo.CurrentUICulture
设置为您想要的区域性。
private string GetStringValue(string stringName, string culture)
{
var specifiedCulture = new CultureInfo(culture);
CultureInfo.CurrentCulture = specifiedCulture;
CultureInfo.CurrentUICulture = specifiedCulture;
var options = Options.Create(new LocalizationOptions { ResourcesPath = "Resources" });
var factory = new ResourceManagerStringLocalizerFactory(options, new LoggerFactory());
var localizer = new StringLocalizer<RecipeController>(factory);
return localizer[stringName];
}
如果您有
IStringLocalizer
的实例,您可以使用它而不是创建新实例。
因为
IStringLocalizer
是在 ResourceManagerStringLocalizer
设置上实现的 CultureInfo.CurrentUICulture
将动态改变文化。
IStringLocalizer Localizer = ServiceHelper.GetService<IStringLocalizer<AppStrings>>();
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = Localizer["Hello"];
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = Localizer["Hello"];
但是,自动生成的 ResX 文件具有
ResourceManager
信息,同时支持 CultureInfo.CurrentUICulture
和本地 Culture
。这是两者的演示:
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = AppStrings.Hello;
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = AppStrings.Hello;
AppString.Culture = new CultureInfo("es-ES");
var HelloES = AppStrings.Hello;
当前
ResourceManagerStringLocalizer
不知道 AppStrings.Culture
属性,因此,您不能将其与 IStringLocalizer
一起使用。
一个解决方案是使用反射构建您自己的,以从
Culture
中检索 ResourceManager
和 ResX
:
public class ResourceStringLocalizer<TStringResource> : IStringLocalizer
{
private Type _stringResource;
private PropertyInfo _cultureProperty;
private PropertyInfo _resourceManagerProperty;
private ResourceManager _resourceManager;
private CultureInfo Culture
=> _cultureProperty?.GetValue(null) as CultureInfo;
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{
throw new NotImplementedException();
}
public LocalizedString this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var value = _resourceManager?.GetString(name, Culture);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
}
}
public LocalizedString this[string name, params object[] arguments]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var format = _resourceManager?.GetString(name, Culture);
var value = string.Format(format ?? name, arguments);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
}
}
public ResourceStringLocalizer()
{
_stringResource = typeof(TStringResource);
_cultureProperty = _stringResource?.GetProperty("Culture", BindingFlags.Static | BindingFlags.NonPublic);
_resourceManagerProperty = _stringResource?.GetProperty("ResourceManager", BindingFlags.Static | BindingFlags.NonPublic);
_resourceManager = _resourceManagerProperty?.GetValue(null) as ResourceManager;
}
}
这是上述类的演示:
IStringLocalizer Localizer = new ResourceStringLocalizer<AppStrings>();
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = Localizer["Hello"];
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = Localizer["Hello"];
AppStrings.Culture = new CultureInfo("es-ES");
var HelloES = Localizer["Hello"];
您可以编写自己的文化中间件,它可以根据用户设置文化,或者可以使用 Http 标头 Accept-Language
app.UseRequestLocalization(roptions =>
{
IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("fr"),
};
roptions.DefaultRequestCulture = new RequestCulture("en-US");
roptions.SupportedCultures = supportedCultures;
roptions.SupportedUICultures = supportedCultures;
roptions.RequestCultureProviders.Add(new YourCustomCultureProvider());
});
中间件示例
public class YourCustomCultureProvider : RequestCultureProvider
{
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
var culture = //Some Logic
if (string.IsNullOrEmpty(culture))
{
// No values specified for either so no match
return Task.FromResult((ProviderCultureResult)null);
}
var requestCulture = new ProviderCultureResult(culture);
return Task.FromResult(requestCulture);
}
}
如果可以帮助您,请参阅此链接 - https://joonasw.net/view/aspnet-core-localization-deep-dive