5

I am attempting to dynamically set the language of an IStringLocalizer at run time. The only available method that seems to do this is IStringLocalizer.WithCulture. However, attempting to use it results in a deprecation warning.

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

I am not using ASP, I am doing this in an IHostedService that handles user interaction from another source (various web chat APIs). This service needs to conform to the language set for the chat server or channel by the admins (stored in database).

What is the correct, current way of setting the language of an IStringLocalizer? Should I use another class entirely?

  • Would [this](https://stackoverflow.com/questions/58316533/net-core-3-istringlocalizer-withculturecultureinfo-is-obsolete) SO answer help you? – Simon Wilson Mar 14 '20 at 14:53
  • @SimonWilson Unfornutately, no. In the answer they only seem to provide languages at the start of the application, in the form of a default value and a collection of available values. If they programmatically set the lagnuage of the `IStringLocalizer`, it is very well hidden. Moreover, the example is for ASP applications, which is not my case. – Nathan.Eilisha Shiraini Mar 14 '20 at 15:04
  • Moreover, in a comment the OP themselves ask how the provided answer changes the cuture dynamically. – Nathan.Eilisha Shiraini Mar 14 '20 at 15:06
  • probably you can create a middleware that, based on every request can set the currentCulture or the UICulture. The localizer would automatically resolve the string based on the culture set. – Bose_geek Mar 14 '20 at 16:40

2 Answers2

16

This should do it. You need to set CultureInfo.CurrentUICulture to the culture you want before getting the string value.

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

If you have an instance of IStringLocalizer you can use it instead of creating a new one.

Marc Annous
  • 417
  • 5
  • 13
  • There used to be method IStringLocalizer.WithCulture but it's now obsolete. To set CurrentCulture and CurrentUICulture is recommended solution from Microsoft documentation. – Lukáš Kmoch Aug 10 '21 at 15:52
  • 1
    The answer seems correct to me. The comment from @LukášKmoch may be correct (I did not find such documentation), but I noticed that CurrentCulture does not do any difference on this scenario. CurrentUICulture seems to be the main thing to be set. – JoaoRibeiro Feb 23 '22 at 09:33
-4

you may write your own culture middleware which can set the culture based on the user or maybe using the Http Header 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());
        });

Sample Middleware

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);
    }
}

Refer this link if it could help you - https://joonasw.net/view/aspnet-core-localization-deep-dive

Bose_geek
  • 498
  • 5
  • 18
  • There is no HTTP at all. As I said I'm using webchat APIs such as [Discord.Net](https://github.com/discord-net/Discord.Net). I am ***not*** using ASP, this is ***not*** a web app. Moreover your solution doesn't provide a way to pass any object to the culture provider when creating the localizer, it can only recieve objects when configuring the app. – Nathan.Eilisha Shiraini Mar 15 '20 at 17:53