Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requirements for New Localization Extension Point #344

Open
NightOwl888 opened this issue Aug 9, 2014 · 3 comments
Open

Requirements for New Localization Extension Point #344

NightOwl888 opened this issue Aug 9, 2014 · 3 comments

Comments

@NightOwl888
Copy link
Collaborator

It has been brought to my attention that using Local and Global resources in conjunction with MVC is difficult to do and is best avoided because the way the default settings are set up by Visual Studio when adding these resource files will not compile down to something that can be accessed via MVC. Also there were a few requests from people who want to provide their localized resources in a separate library from the MVC application, and the current proposed way is not very flexible in that it

  1. Requires additional logic beyond providing configuration for a ResourceManager
  2. Only supports a single resource file in a single assembly

With that in mind, I think it is time to create a new extension point that accounts for these limitations and makes use of modern techniques and extension points of ASP.NET that are commonly used by MVC (without dropping support for the existing functionality).

I am not really a subject matter expert on globalization, so I would really appreciate any feedback on what use cases need to be solved for and how best to tackle them.

In reading Microsoft's extensive document on ASP.NET localization, I notice that there are actually 2 extensibility points that ASP.NET provides:

  1. ResourceManager - Reads resources from a specific file in a specific assembly.
  2. IResourceProvider/ResourceProviderFactory - Provides alternative logic for getting local and global resources rather than just from the stock ASP.NET folders.

If I understand correctly, the second extension point is designed to plug directly into ASP.NET and affects the HttpContext.Current.GetGlobalResourceObject method (which MvcSiteMapProvider already uses). Therefore, implementing these abstractions and then providing them via web.config is and always has been an option for providing resources in a separate assembly (even if not using DI). Also, it wouldn't make sense for MvcSiteMapProvider to utilize IResourceProvider or ResourceProviderFactory directly since these plug into ASP.NET.

So (I think) the only real nut to crack here is how to make it simple to extend MvcSiteMapProvider to allow the user to supply resources from assemblies that are external to the ASP.NET application in an extensible way. Let's start with a list of requirements. Feel free to add or provide feedback on the requirements list - I will update the list in this 1st post as the feedback rolls in so it is easy to read in one place.

  1. Personally, I am in favor of dropping support for implicit resources (or at least discouraging it until it can be dropped in a major version). This doesn't seem to have any place in a framework as complex as MvcSiteMapProvider - essentially, implicit resources are supposed to be "right next to" the thing you are localizing (assuming the thing is a file of some type) - see Implicit Localization not working #228. However, MvcSiteMapProvider localizes properties of nodes, which can be provided in other ways than files. This only seems to have a place for localizing attributes if they are provided in XML and that XML is provided as a file (which is not a prerequisite of XmlSiteMapNodeProvider).
  2. For backward compatibility with the current syntax for specifying resources, the extension point should provide a method to lookup a value by "providerName" and "resourceKey".
  3. Support should be added for a default value as in microsoft's implementation http://msdn.microsoft.com/en-us/library/vstudio/ms178427(v=vs.100).aspx.
  4. There should be an in-the-box implementation that allows providing a ResourceManager instance.
  5. There should be an in-the-box implementation that allows the developer to specify assemblyName/fullyQualifiedResourceName pairs to wire up multiple resources automatically from various assemblies (and their localized counterparts).
  6. If a ResourceManager-based implementation fails to find a particular fully qualified resource file in an assembly, it should throw an exception that includes a list of all of the existing fully qualified resources in the assembly.
  7. There should be an implementation that calls the HttpContext.Current.GetGlobalResourceObject method that is wired up by default for backward compatibility with the existing functionality and to maintain support for the underlying IResourceProvider implementation provided by ASP.NET.

My current thinking is to add this extensibility point as a constructor argument to the default StringLocalizer class, replacing the explicit call to httpContext.GetGlobalResourceObject with the new provider. Essentially, that means that this feature can be added in a minor version without dropping support for any existing code that relies on the current implementation.

@nrm101
Copy link

nrm101 commented Feb 19, 2015

I think a well working implementation is like the System.ComponentModel.DataAnnotations;

https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.resourcetype(v=vs.95).aspx

[Display(ResourceType=typeof(DisplayResources), Name="LName", Description="LNameDescription")]
public string LastName { get; set; }

@herrquark
Copy link

So where are we on this topic? Currently I'm forced to modify MvcSitemapProvider source code and manually reference custom .dll files which is no good

@NightOwl888
Copy link
Collaborator Author

@herrquark - This implementation has not yet been started, and my current schedule doesn't allow much time to work on MvcSiteMapProvider.

However, there is no reason to modify the source code and compile your own version of MvcSiteMapProvider in order to implement this functionality. Also, this is exactly the way it was done in MvcSiteMapProvider v3.x, which is why this extension point hasn't been given a higher priority.

Current Approaches for Accessing External Resources

If you are using external DI. All you need to do is implement IStringLocalizer as shown in this example. Also note there is a working demo of the solution.

Alternatively, you could implement a ResourceProviderFactory as specified in the MSDN documentation to provide resources from an external assembly for your entire application (whenever you call GetGlobalResourceObject). Since MvcSiteMapProvider calls HttpContext.GetGlobalResourceObject it will automatically use your implementation. You can plug your implementation directly into ASP.NET by using the globalization section of Web.config.

<globalization uiCulture="auto" culture="auto" resourceProviderFactoryType="CustomResourceProviders.ExternalResourceProviderFactory, CustomResourceProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f201d8942d9dbbb1" />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants