I'm trying to implement localization in my Blazor WebAssembly app, by following one of tutorials found on internet, such as: Localization in Blazor
I have set up everything described in tutorials, but I cannot get a localized value for a specific key, I get a KEY displayed as text I want to localize.
Here is my code: Program.cs - hardcoded culture, to make sure i choose the right one:
builder.Services.AddLocalization(opts => { opts.ResourcesPath = "Localization"; });
var culture = new CultureInfo("sr");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
In my .razor file I injected a IStringLocalizer:
@inject IStringLocalizer<General> localizer
And I use a localizer like this: <MudTooltip Text="@localizer["Open"]">
My Class generated from .resx is called General. Here is my resources setup: Added a resx as Embedded resource and code gen tool PublicResXFileCodeGenerator
My localized resx for Serbian language is set as EmbeddedResource and with no code generation tool.
The IStringLocalizer<T>
doesn't rely on a generated class from the .resx
file. During the build process, the ResourceManager
embeds the resource in the main dll and creates satellite dlls. The default implementation of IStringLocalizer<T>
rely on the ResourceManager
to read the files inside the assembly or satellite assembly. So turn off the code generation should solve your problem.
Update:
The <T>
is referring to any possible class. There is no constraint enforce. However, there should be a link between the namespace of the class and the file location.
Assume you have the file Pages/Users/AddUserPage.razor
@inject IStringLocalizer<AddUser> Localizer
If you don't specify a namespace manually, AddUserPage
class will end up in the namespace <ProjectRootNamespace>.Pages.Users
.
So, you need to create a .resx file reflecting the folder structure. Your root is specified as Localization
so you need to create the file Localization/Pages/Users/AddUserPage.resx
or and their locazied counterparts like Localization/Pages/Users/AddUserPage.sr.resx
In some cases, it makes sense to group certain localization, like the caption of buttons (Ok, Close, Yes, No, etc.). To avoid having these keys in each .resx file, you can create an empty class. I like to name it SharedRessources
. However, the name is not important as long as you name your .resx file accordingly.
namespace <ProjectRootNamespace>
{
public class SharedRessources
{
}
}
Because the class is in the root namespace of your project, the .resx file should be placed inside the root folder of your .resx file. In your case, Localization
. So, the name should be Localization/SharedRessources.resx
and Localization/SharedRessources.sr.resx
Now, you can this can be injected too.
@inject IStringLocalizer<AddUser> Localizer
@inject IStringLocalizer<SharedRessources> SharedLocalizer
<p> Hi from @Localizer["KeyLocalToAddUser"] </p>
<p> Do you want to delete the user? <span> @SharedLocalizer["No"] or SharedLocalizer["Yes"]