.Net Core 3 IStringLocalizer.WithCulture(CultureInfo) is obsolete
Asked Answered
T

1

22

I've upgraded a project from .Net Core 2.2 to .Net Core 3.0.

After trying to fix all the warnings and errors I'm now trying to find a solution to this warning:

'IStringLocalizer.WithCulture(CultureInfo)' is obsolete: 'This method is obsolete.
 Use `CurrentCulture` and `CurrentUICulture` instead.'

I'm using this to change the website language per the logged-in user. I have this implementation to change the website culture per user:

public class CultureLocalizer : ICultureLocalizer
{
    private readonly IStringLocalizer localizer;
    public CultureLocalizer(IStringLocalizerFactory factory)
    {
        var type = typeof(Resources.PageResources);
        var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
        localizer = factory.Create("PageResources", assemblyName.Name);
    }

    // if we have formatted string we can provide arguments         
    // e.g.: @Localizer.Text("Hello {0}", User.Name)
    public LocalizedString Get(string key, params string[] arguments)
    {
        return arguments == null ? localizer[key] : localizer[key, arguments];
    }

    public LocalizedString Get(Enum key, params string[] arguments)
    {
        return arguments == null ? localizer[key.ToString()] : localizer[key.ToString(), arguments];
    }

    public LocalizedString Get(CultureInfo culture, string key, params string[] arguments)
    {
        // This is obsolete
        return arguments == null ? localizer.WithCulture(culture)[key] : localizer.WithCulture(culture)[key, arguments];
    }

    public LocalizedString Get(CultureInfo culture, Enum key, params string[] arguments)
    {
        // This is obsolete
        return arguments == null ? localizer.WithCulture(culture)[key.ToString()] : localizer.WithCulture(culture)[key.ToString(), arguments];
    }
}

And this is the dummy class which only holds the .resx file for the translations:

// dummy class for grouping localization resources
public class PageResources
{
}

I couldn't find anything on the web that refers to how to solve this warning except for this discussion on github that appears to have no solution yet.

Had anyone else stumbled upon this warning and found a solution for it?

Toluate answered 10/10, 2019 at 6:15 Comment(1)
Did you ever figure this out? Reading accepted answer, I'm not sure how that addresses what I think you are asking. In my case, I'm needing to write my own ViewLocalizer so I started from Microsoft's implementation from Github and it still has the WithCulture method in there so I'm wondering how I should resolve it.Warenne
L
10

Is already mention in there source code here

    /// <summary>
    /// Creates a new <see cref="IStringLocalizer"/> for a specific <see cref="CultureInfo"/>.
    /// </summary>
    /// <param name="culture">The <see cref="CultureInfo"/> to use.</param>
    /// <returns>A culture-specific <see cref="IStringLocalizer"/>.</returns>
    [Obsolete("This method is obsolete. Use `CurrentCulture` and `CurrentUICulture` instead.")]
    IStringLocalizer WithCulture(CultureInfo culture);

Here is how they use in .Net Core 3.0

public static void Main()  
   {
      // Display the name of the current thread culture.
      Console.WriteLine("CurrentCulture is {0}.", CultureInfo.CurrentCulture.Name);

      // Change the current culture to th-TH.
      CultureInfo.CurrentCulture = new CultureInfo("th-TH", false);
      Console.WriteLine("CurrentCulture is now {0}.", CultureInfo.CurrentCulture.Name);

      // Display the name of the current UI culture.
      Console.WriteLine("CurrentUICulture is {0}.", CultureInfo.CurrentUICulture.Name);

      // Change the current UI culture to ja-JP.
      CultureInfo.CurrentUICulture = new CultureInfo( "ja-JP", false );
      Console.WriteLine("CurrentUICulture is now {0}.", CultureInfo.CurrentUICulture.Name);
   }

Update: This approach is work around until we can have offical announcement from Microsoft

You can create a service like this

public class LocalizationService
    {
        private readonly IStringLocalizer _localizer;

        public LocalizationService(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create("SharedResource", assemblyName.Name);
        }

        public LocalizedString GetLocalizedHtmlString(string key)
        {
            return _localizer[key];
        }
    }

Then in your startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<LocalizationService>();
            services.AddLocalization(options => options.ResourcesPath = "Resources");

            services.Configure<RequestLocalizationOptions>(options =>
            {
                var supportedCultures = new[]
                {
                    new CultureInfo("en"),
                    new CultureInfo("nl")
                };

                options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddDataAnnotationsLocalization(options =>
                {
                    options.DataAnnotationLocalizerProvider = (type, factory) =>
                    {
                        var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName);
                        return factory.Create("SharedResource", assemblyName.Name);
                    };
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            var localizationOption = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
            app.UseRequestLocalization(localizationOption.Value);

            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

You can view my full code here

Laevo answered 10/10, 2019 at 6:23 Comment(6)
I've updated my question with the code that I'm using. Could you please have a look at it? Because it doesn't look compatible with your solution.Toluate
@LiranFriedman where do you get ICultureLocalizer ? I'm try to search for that interface but I cant find itLaevo
Could you please explain how does the culture changes per user? Each user selects his/her preferred language in his profile. Also, how could I check to see that it works?Toluate
For those who use this in a console app - it is important to use CurrentUICulture because CurrentCulture seems to have no effect on StringLocalizer. If using in a web app, you can use services.Configure<RequestLocalizationOptions> to adjust behavior for detecting current user's request language, but be aware of Microsoft defaults - headers, cookies, whatever - for automatic language detection. For this reason I prefer to adjust RequestCultureProviders to my own known mechanism for detecting user's language.Hydr
@tony-ngo Do you know of an update to this approach for dotnet 6?Godart
This post shows how to get the list of default supported cultures.Godart

© 2022 - 2024 — McMap. All rights reserved.