aspnet / Mvc

[Archived] ASP.NET Core MVC is a model view controller framework for building dynamic web sites with clean separation of concerns, including the merged MVC, Web API, and Web Pages w/ Razor. Project moved to https://github.com/aspnet/AspNetCore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support localization resources in a separate assembly

fabercs opened this issue · comments

Is this a Bug or Feature request?:

It is a feature, but not sure if it exists or not

Description of the problem:

I am trying to move the localization resources(MyProject.Web.Resources) in MyProject.Web asp.net core mvc project to another separate MyProject.Resources project. I guess it is only doable for a shared resource, however, by doing this, I still want to make use of the IStringLocalizer work in my views and controllers. It seems it does not right now.

Version of Microsoft.AspNetCore.Mvc

commented

Hi. It looks like this is a question about how to use ASP.NET Core. While we do our best to look through all the issues filed here, to get a faster response we suggest posting your questions to StackOverflow using the asp.net-core-mvc tag.

commented

@ryanbrandenburg, can you please answer this question when you get time? Thanks!

You can use ResourceLocationAttribute

@mkArtakMSFT There is a post on this subject at stackoverflow, however there is not a real answer, check the link

@ryanbrandenburg , @hishamco I did lots of thing but I couldn't get it work. Is there any real world application that works like this way? I know resources and pages or classes follow namespace convention, but I couldn't understand how using an assemblyInfo solves this.

Here what I did;

  • Moved Resources folder in Web project to new MyProject.Resources class library project as shown my previous post. So, all resources wrapped inside a Resource folder.

  • Added an AssemblyInfo.cs in the root of MyProject.Resources and added following line;
    [assembly: ResourceLocation("Resources")]

  • In Startup.cs, removed ResourcePath option from the AddLocalization middleware. (I tried with the option as well).
    Last status is; services.AddLocalization()

Do we need any other configuration in Startup.cs?

And project structure is as follows;

|--MyProject.Infrastructure
|--MyProject.Core
|--MyProject.Web
    |--Controllers
    |--ViewModels
    |--Views
       |--Customer
          |--Index.cshtml
|--MyProject.Resources
    |--Resources
       |--Controllers
       |--ViewModels
       |--Views
          |--Customer
             |--Index.en-US.resx
             |--Index.tr-TR.resx
       |--SharedResource.cs
       |--SharedResource.en-US.resx
       |--SharedResource.tr-TR.resx   

SharedResources are the only working part in project right now btw. I suspect AssemblyInfo should be placed in Web project, maybe?

SharedResources are the only working part in project right now btw. I suspect AssemblyInfo should be placed in Web project, maybe?

Nope, it should be on MyProject.Resources

@fabercs could you please share with us a minimal repo to reproduce your issue?

@hishamco please find the minimal repo solution linked

Sure, I will investigate on this ..

I notice there 're many thing missing such as: Suffix views with culture code Index.tr-TR.resx, AddViewLocalization() extension method .. etc.
Also there's a confusion on middleware order, please refer to Localization.StarterWeb

I also realized about Suffix option missing middleware and commited it. I added AddMvcLocalization() instead AddViewLocalization(), it also covers the data annotation localization, anyway I changed it to AddViewLocalization(). So after these still no effects.

Again AddLocalization() should become before AddMvc(), anyhow please make sure that your app reading the resources from within the same assembly, after that we will figure out what's the wrong with the separated assembly

Ok, I have deleted the solution and added a new one with the Resources folder included in web project and localization works. The class library project also included, you can play with unload/reload.

https://github.com/fabercs/Issue8739

@ryanbrandenburg how ViewLocalizer at this line https://github.com/aspnet/Mvc/blob/master/src/Microsoft.AspNetCore.Mvc.Localization/ViewLocalizer.cs#L110 will aware about the ResourceAttribute while we pass the view execution path as base name to the localizer factory?!!

@hishamco, as IViewLocalizerFactory is derived from IStringLocalizerFactory, it calls the same Create logic of its base. However, for view localization, because of this line

_applicationName = hostingEnvironment.ApplicationName;

you always pass the executing assembly to the factory Create logic.

https://github.com/aspnet/Localization/blob/60a3d57a3e8b8b6d69232815a9596b5a495a7d0b/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs#L181

So it crates the ResourceManager based on that assembly. I have it worked by implementing my own IViewLocalizer class and overriding _applicationName for now.

There's no IViewLocalizerFactory!! the ViewLocalizer using IHtmlLocalizer which is construct from IHtmlLocalizerFactory

So it crates the ResourceManager based on that assembly. I have it worked by implementing my own IViewLocalizer class and overriding _applicationName for now.

Cool, but still I'm not sure why we need to subclass if the localizer aware about ResourceLocationAttribute, @ryanbrandenburg is there an easy way to achieve this without subclass ViewLocalizer?

@hishamco my mistake, I just meant to IViewLocalizerFactory, however, at the end, all make use of IStringLocalizerFactory :)

private readonly IStringLocalizerFactory _factory;

@fabercs it's unclear to me if you're sorted now. If you're sorted we'll close this out. If your not could you re-state your current problem?

@ryanbrandenburg indeed I was expecting all will work properly when moving all my working (conventional) localization system from Web project to a separate project, however adding only a ResourceLocation attribute didn't do the trick. While keeping the ResourceLocation attribute, as I said above, I had to implement my own IViewLocalizer for views' localization. For data annotation localization, I had to quit namespace convention and create a shared resource which is working fine. If you say, that's what we meant to be done in our samples for localization, it is ok, you may close the issue. I have my all project localized.

For your ViewLocalizer issue refer to this issue. It boils down to this being an abstraction issue that would force us to make assumptions about the contents of a different assembly.

For your DataAnnotations issue, could you file a new issue (now against the aspnet/AspNetCore repo since we're moving everything) so that we can keep its context clean?