I may be not doing the correct configurations in the startup.cs
file. I have created a demo application to make it working, but after trying various things it is not working. The demo repository is available at following link
https://github.com/gurpreet42/MyAppV3
Configurations of startup.cs files are
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<LocService>();
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("nl")
};
options.DefaultRequestCulture = new RequestCulture("en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
services.AddMvc()
.AddViewLocalization()
.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName);
return factory.Create("SharedResource", assemblyName.Name);
};
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
// Localisation
var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseSession();
app.UseSession();
app.UseCookiePolicy();
}
The code in the LocService
class is
public class LocService
{
private readonly IStringLocalizer _localizer;
public LocService(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)
{
var value= _localizer[key];
return value;
}
}
Now on our controller, we can access the localized string as
localizerService.GetLocalizedHtmlString("my_string")
Under the "Resources" folder we have following files present
SharedResource.cs
SharedResource.en-US.resx
SharedResource.nl.resx
Please suggest where the configurations are wrong or do I need to add some extra package?
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 readd resource files to the Resources
folder.
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);
}
There was a problem with the namespace in my case. Modifying it solved the problem for me.
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 eg
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 :
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()
.
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.
I have been struggling with Localization over the past week, and came across a much simpler solution that I have not yet seen a downside for, and I can't figure out why almost nobody does it this way.
Create a resource file without a culture (eg Resource.resx) for your default strings, and one (or multiple) with a culture (eg Resource.nl.resx).
Then on the Resource file set Access Modifier to 'Public': image where to set access modifier
In your views and controllers you can then just use:
@Resource.CurrentMarketValue
like in the good old days! As long as you are 'using project .Resources'.
No magic strings, IntelliSense, and language switching still works fine. Don't even need to change Startup.cs.
You can set the culture as follows:
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.