5

I have tried to create the Razor Class Library with Asp.Net Core in following project structure:

enter image description here

I have used in my web application these settings for localization in Startup class:

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                    .AddViewLocalization(
                        LanguageViewLocationExpanderFormat.Suffix,
                        opts => { opts.ResourcesPath = "Resources"; })
                    .AddDataAnnotationsLocalization();

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

                        opts.DefaultRequestCulture = new RequestCulture("en");
                        opts.SupportedCultures = supportedCultures;
                        opts.SupportedUICultures = supportedCultures;
                    });

....

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

In Index.cshtml:

@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer


<h1>@Localizer["Title"]</h1>

Unfortunately, the result is only string "Title". I can't load these resx files from Razor Class Library.

How can I use the localization in Razor Class Library like above?

UPDATE: This is very similiar use case - https://github.com/aspnet/Localization/issues/328 - that provides some example.

Jenan
  • 2,956
  • 10
  • 52
  • 99

2 Answers2

2

You appear to have forgotten to configure localization correctly using AddLocalization

Using details provided from documentation

Reference Globalization and localization in ASP.NET Core

Configure localization

Localization is configured in the ConfigureServices method:

services.AddLocalization(options => options.ResourcesPath = "Resources"); //<<< This is required

services
    .AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
    

AddLocalization Adds the localization services to the services container. The code above also sets the resources path to "Resources".

AddViewLocalization Adds support for localized view files.

AddDataAnnotationsLocalization Adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions.

Localization middleware

The current culture on a request is set in the localization Middleware. The localization middleware is enabled in the Configure method. The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[] {
    new CultureInfo("en-US"),
    new CultureInfo("en")
};

app.UseRequestLocalization(new RequestLocalizationOptions{
    DefaultRequestCulture = new RequestCulture("en"),
    // Formatting numbers, dates, etc.
    SupportedCultures = supportedCultures,
    // UI strings that we have localized.
    SupportedUICultures = supportedCultures;
});

//...other middleware

app.UseMvcWithDefaultRoute();

The path to the resource file shown in the example image follows the path naming convention given that you are using the ResourcesPath option which was set to "Resources". This should allow the view to find the resource file in the relative path to the "Resources" folder.

An alternative is to not use the ResourcesPath option, and place the .resx file in the same folder as the view, following the naming convention of course.

Base on additional details provided it was indicated that the UI project would be packaged as a nuget package.

Then have the resources files packaged into the nuget package and have them unpacked to the resources folder of the target project when when installed.

The resources need to be in the site root to be available to the view, so you then need to reference all the files in your .nuspec:

<?xml version="1.0"?>
<package>
    <metadata>...
    </metadata>
    <files>
        <!-- Add all resource files -->
        <file src="Resources\**\*.resx" target="content\Resources" />
    </files>
</package>

Reference Creating NuGet packages

Community
  • 1
  • 1
Nkosi
  • 191,971
  • 29
  • 311
  • 378
  • I have tried your code snippets, but unfourtunetly it doesn't work. I have two projects - first project is with web app and second with razor ui where is folder with "resources". I have referenced razor UI to web app project where I used your settings. Is it problem that resources are with razor ui assembly that is referenced to web project? – Jenan Jun 18 '18 at 17:27
  • @Jenan Resources (*.resx*) need to live in the root project base to be accessible. So that would mean they need to be in the web project. – Nkosi Jun 18 '18 at 17:50
  • @Jenan I thought you were using a RazorPages project not just referencing razor pages from another project. That will cause problem when referencing resource files. – Nkosi Jun 18 '18 at 17:52
  • My idea is create a separate DLL with UI - that's provides new razor class library, but the problem is sharing the resource files. How to solve it? Sharing the resx files with UI razor class library? – Jenan Jun 18 '18 at 17:54
  • Just to test try having the resources in the root project and keep the views in the separate library and see if it works. – Nkosi Jun 18 '18 at 17:55
  • That's works, resx files in web project and referenced the razor class library but I want to put resx files in razor class library because I want to publish the UI with localization as a nuget package. :-) – Jenan Jun 18 '18 at 17:58
  • @Jenan Then have the resources files in the nuget package and have it unpack to the resources folder when referenced by a project. You have already seen that it will work. That is how the framework works with resource files. – Nkosi Jun 18 '18 at 17:59
  • @Jenan I have to step out for a bit. I'll check in when I get back later to see how it goes. – Nkosi Jun 18 '18 at 18:01
  • What do you mean with unpack the resources? Do you have some sample for that? I'll be very happy for any point for this idea. – Jenan Jun 18 '18 at 18:04
  • @Jenan check https://docs.microsoft.com/en-us/nuget/reference/nuspec#including-content-files – Nkosi Jun 18 '18 at 18:50
  • Thank you very much for your effort to help with issue. This is similiar use case - https://github.com/aspnet/Localization/issues/328 – Jenan Jun 19 '18 at 09:25
  • @Jenan Do you have a working sample as per answer? Can you please share? – Vikram Jan 04 '21 at 09:24
0

I haven't tried the accepted answer and based on the comments, it seems the OP didn't get it to work. I implemented a pattern similar to the View/Page locator pattern that MVC/Razor Pages uses namely, that resources can be provided in a RCL or separate assembly and use ViewLocalizer and it'll just find the matching resource string from the highest precedence resource. You can read my implementation and see if it might work for you.

https://terryaney.wordpress.com/2021/01/04/migrating-to-net-core-overridable-localization-in-razor-class-libraries/

Terry
  • 1,835
  • 2
  • 22
  • 42