更改 IStringLocalizer 的语言

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

我正在尝试在运行时动态设置

IStringLocalizer
的语言。唯一可用的方法似乎是
IStringLocalizer.WithCulture
。但是,尝试使用它会导致弃用警告。

public IStringLocalizer GetLocalizer(string locale) {
    this.localizerFactory.Create(typeof(CommonResources)).WithCulture(new CultureInfo(locale));
}

不是使用ASP,我在一个

IHostedService
中执行此操作,该处理来自另一个源(各种网络聊天API)的用户交互。该服务需要符合管理员为聊天服务器或频道设置的语言(存储在数据库中)。

当前设置

IStringLocalizer
语言的正确方法是什么?我应该完全使用另一个类吗?

c# .net-core internationalization
3个回答
17
投票

这应该可以。在获取字符串值之前,您需要将

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
的实例,您可以使用它而不是创建新实例。


0
投票

因为

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"];

-4
投票

您可以编写自己的文化中间件,它可以根据用户设置文化,或者可以使用 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

© www.soinside.com 2019 - 2024. All rights reserved.