Search code examples
c#asp.net-corelocalizationasp.net-core-localization

How to create a SharedResource class for localization with default localization


In ConfigureServices I did:

services.AddLocalization(opts => opts.ResourcesPath = "Resources");
services.AddMvc(options => { options.MaxModelValidationErrors = 10; })
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix,
        opts => opts.ResourcesPath = "Resources")
    .AddDataAnnotationsLocalization(options =>
    {
        options.DataAnnotationLocalizerProvider = (type, factory) =>
        {
            var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName);
            return factory.Create("SharedResource", assemblyName.Name);
        };
    });

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

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

//This is the custom service for localization
services.AddSingleton<LocService>();

Created the localization service in LocService like:

public class LocService : StringLocalizer<string>
{
    private readonly IStringLocalizer _localizer;

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

    public override LocalizedString this[string name]
    {
        get => _localizer[name];
    }
}

And configured everything in Configure() like:

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

And in views I inject it as:

@inject LocService Loc
@Loc["wordToTranslate"]

My issue is that this approach doesn't work when there is lack of the relative resource file like, for example, if I don't have the Resources/SharedResource.it.resx and that call(@Loc["wordToTranslate"]) just returns "wordToTranslate" even if in the default Resources/SharedResource.en.resx corresponds to another string ("wordToTranslate" = "Success"). What am I doing wrong?


Solution

  • In ASP.NET Core localization, the default language is what you put inside the brackets, so:

    @Localizer["some text"]
    

    Will render:

    • "some text", because the current language is the default language
    • "some text", because there's no resource file for the current language
    • the translation, given that there's a resource file for the current language

    Alternatively, if you want to use a resource file, just remove the culture from it, i.e someresource.resx