ASP.NET Core 3.1 : Shared Localization not working for version 3.1

There is no need to create the LocService you can use IStringLocalizer.

"Resources" folder structure

SharedResource.cs
SharedResource.en-US.resx
SharedResource.nl.resx

At the class SharedResource, do not add "Resources" in the namespace. Like MyAppV3.Resources. Please keep it just MyAppV3.

namespace MyAppV3
{
    public class SharedResource
    {
    }
}

Add in your .csproj the following property

<PropertyGroup><EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention></PropertyGroup>

Add to startup.cs > ConfigureServices

    services.AddLocalization(options => options.ResourcesPath = "Resources");
    services.AddScoped<IStringLocalizer, StringLocalizer<SharedResource>>();

    services
        .Configure<RequestLocalizationOptions>(options =>
            {
                var cultures = new[]
                                   {
                                       new CultureInfo("en"),
                                       new CultureInfo("nl")
                                   };
                options.DefaultRequestCulture = new RequestCulture("en");
                options.SupportedCultures = cultures;
                options.SupportedUICultures = cultures;
            });

Startup.cs > Configure

   app.UseRequestLocalization(app.ApplicationServices
            .GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);

Add to the controller the IStringLocalizer parameter.

   public MyTestController(IStringLocalizer localizer)
   {
        this.localizer = localizer;
   }

   public IActionResult Get()
   {          
        var value = this.localizer.GetString("RessourceName");
        return this.Ok(value);
   }

I had similar issue during upgrade from 2.2 to 3.1.

In 2.2 my setup was:

        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddMvc(config =>
            {
               ... <omitted for brevity>
            })
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

All resources where in "Resources" folder. SharedResources.cs had recommended namespace of the project:

// *************************
// DO NOT CHANGE NAMESPACE
// *************************
// ReSharper disable once CheckNamespace
namespace MyProject
{
    // Dummy class to group shared resources
    public class SharedResources
    {
    }
}

And View Localizations were based on the path e.g.

Resources
   Pages
      Error.en-US.resx
      Error.ja-JP.resx

With 3.1, recommended setup was (with minimal changes):

        services.AddLocalization();
        services.AddRazorPages().AddRazorRuntimeCompilation();
        services.AddControllersWithViews(config =>
            {
               ... <omitted for brevity>
            })
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

At this point SharedResources was working fine but IViewLocalizer and view localizations were not working.

I found two ways to fix it based on above suggestions and this article:

  1. Opt out of the new naming convention, effectively going back to what was used in 2.2 by adding following to csproj file:

     <PropertyGroup>
         <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
     </PropertyGroup>
    

And, adding options => options.ResourcesPath = "Resources" back to services.AddLocalization().

  1. Keep 3.1 setup and fix each view localization by adding dummy .cs file with namespace that is outside of resources folder, for example:

    Resources
       Pages
          Error.cs
          Error.en-US.resx
          Error.ja-JP.resx
    

Where Error.cs is:

// *************************
// DO NOT CHANGE NAMESPACE
// *************************
// ReSharper disable once CheckNamespace
namespace MyProject.Pages
{
    // Dummy class to group shared resources
    public class Error
    {
    }
}

So if you have lots of View Localizations like me, #1 option would probably be better, as it is configuration change only, leaving all existing view localization as they were.


It turns out that in asp.net core 3.1, you need to place SharedResource.cs out of Resources folder(see this github issue)

If class SharedResource.cs and SharedResource.*.resx in same folder, the namespace will be error in compiled dll xxx.lang.dll.

So, just delete original SharedResource.cs create a new one under the project directly:

namespace MyAppV3
{
    public class SharedResource
    {
    }
}

And read resource files to the Resources folder.