Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Global Resources Localization Suggestion for ASP.NET


:P
On this page:

ASP.NET provides the ability to use strongly typed resources for Global resources that are contained in App_GlobalResources. This is a nice feature, but it has a pretty major flaw as it's implemented right now.

The way this works is that you have your Resx file in App_GlobalResources and ASP.NET will at compile time generate a class from each of the resource sets (each distinct invariant .resx file) defined. For example a generated class looks like this:

public class resources
{
    // Fields
    private static CultureInfo resourceCulture;
    private static ResourceManager resourceMan;

    // Methods
    internal resources();

    // Properties
    public static string CouldNotCreateNewCustomer { get; }
    public static string CouldNotLoadCustomer { get; }
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public static CultureInfo Culture { get; set; }
    public static string CustomerSaved { get; }
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public static ResourceManager ResourceManager { get; }
    public static Bitmap Sailbig { get; }
    public static string Today { get; }
    public static string Yesterday { get; }
}

Note that this works both with stock ASP.NET projects as well as with WAP. With WAP it's a bit more explicit - you can examine the class in the IDE, where with ASP.NET stock projects this class gets generated at runtime and embedded into the App_GlobalResources assembly that gets dynamically generated. In WAP you get the standard project behavior with a Properties namespace with the resources underneath it.

For the stock projects generated class shown above you can see that the ASP.NET creates a ResourceManager instance field. But hold on here - a ResourceManager is not the proper component that should be referenced for an ASP.NET Resources. ASP.NET works with ResourceProviders which can be swapped via hookups in web.config. You can basically create a custom resource provider and use it instead of the default ResX provider. ResourceManager works, but it's not hooked into the ASP.NET resource architecture.

However, the class generated can't deal with this since it doesn't work with a ResourceProvider, but simply uses a ResourceManager which is hardcoded in the static property get for the ResourceManager:

public static ResourceManager ResourceManager
{
    get
    {
        if (object.ReferenceEquals(resourceMan, null))
        {
            ResourceManager temp = new ResourceManager("Resources.resources", typeof(resources).Assembly);
            resourceMan = temp;
        }
        return resourceMan;
    }
}

This means that if you change the ResourceProvider this sort of strongly typed global resource will no longer work. But even with Resx resources this is a problem: By creating a new ResourceManager ASP.NET is effectively duplicating the resources that might be used by the ResourceProvider (for example if you use those same resources for Explicit or Implicit resource markup strings).

Either way this doesn't sound like a good way to go.

It seems to me if ASP.NET is generating this class anyway, why couldn't it generate code like this instead:

using System;
using System.Web;

namespace AppResources
{
    public class Resources
    {
        public static System.String Yesterday
        {
            get { return (System.String) HttpContext.GetGlobalResourceObject("Resources","Yesterday"); }
        }

        public static System.Drawing.Bitmap Sailbig
        {
            get { return (System.Drawing.Bitmap) HttpContext.GetGlobalResourceObject("Resources","Sailbig"); }
        }

        public static System.String Today
        {
            get { return (System.String) HttpContext.GetGlobalResourceObject("Resources","Today"); }
        }

        public static System.String CustomerSaved
        {
            get { return (System.String) HttpContext.GetGlobalResourceObject("Resources","CustomerSaved"); }
        }

        public static System.String CouldNotCreateNewCustomer
        {
            get { return (System.String) HttpContext.GetGlobalResourceObject("Resources","CouldNotCreateNewCustomer"); }
        }

        public static System.String CouldNotLoadCustomer
        {
            get { return (System.String) HttpContext.GetGlobalResourceObject("Resources","CouldNotLoadCustomer"); }
        }

    }
}

This would ensure that the Provider settings are respected so you could use any ResourceProvider and this would also take care of the duplication issue as the same Provider is used that ASP.NET uses for markup resources.

A while back I created some helper routines as part of my Data Resource Provider that let you run through the ResX resources (or any ResourceSet) and generate a strongly typed class like above.

Class:
http://www.west-wind.com/tools/wwDbResourceProvider/docs/_1Y7185CTQ.htm

Code (as part of the whole provider):
http://www.west-wind.com/files/confererences/conn_Localization.zip

This works, but it'd be nice if this would work like this out of the box instead. Given that ASP.NET generates this anyway - why not generate the 'right' code? <s>

Posted in ASP.NET  Localization  

The Voices of Reason


 

Kevin Pirkl
June 24, 2007

# re: Global Resources Localization Suggestion for ASP.NET

I'm going a little of topic with my comment not exactly specific to "Global Resources Localization Suggestion for ASP.NET" but to ASP.Net approach to web application localization in general. I'm not a fan of what Microsoft provides for current web application localization approaches. Embedding resource into satellite assemblies or database tables, XML or even different files for graphics may all be well and good but runtime approach server side implementation of these strategies is kind of lame IMHO.

I like to think that Microsoft's behind in the game in regards to Web Application Localization approaches considering the effort I have already put in on localization work on over 40 different ASP.Net web applications to date extending into over 12 language localizations with deployments in China and Russia.

Microsoft puts much effort into linear API approaches to such a point they forget entirely about simplicity and process. If you change your thinking about the localization problem set and consider the sensing capabilities for ASP.Net we can turn this problem on it's head and make it much simpler.

1> We already know that web applications can sense browser language support and we can override those settings very easily via URL or Query String parsing.
2> Microsoft has this great tool called ASP.Net AJAX which exists as a a perfect delivery mechanism for localized resources.
3> Microsoft could use a kick in the pants.
4> I would like to see MAB for Localization become a high priority for ASP.Net AJAX.

Adam Greenfield's "Everyware" is an excellent description regarding the form software & computing will take in the next many years. Sensor and delivery of localization from a service based back-end by dropping embedded localized versions of JavaScript into client web pages that contain proper resource pointers, string and how to display those items will reduce the overall heavy lifting required for localization.

ASP.Net already contains all the parts necessary to support this approach as I had tossed together a little video of what I think might be a better approach (http://softwarecommunity.intel.com/videos/home.aspx?fn=1027)

Anyway it's just a thought that they could do even better and not burden us with more one-off approaches stuffed here and there into this form and that so that we end up re-learning things again and again for each language we choose to code in. My thought made somewhat clear in the video link above provides a nicer centralized approach to localization that could be shared by all and just not ASP.Net.

Food for though, anyway I love you work! Thanks for all your community involvement and this blog as well.

Cheers

Kevin

Rick Strahl
June 24, 2007

# re: Global Resources Localization Suggestion for ASP.NET

Kevin, don't think that's the right link above <s>.

I think what you're talking about is a whole different story though. I'm not sure that's what you mean but If you're building a client based UI (ie. most of the UI logic driven through client script) the server side localization built into VS.NET isn't going to help much (although that really depends on what gets localized). However, if you have the right tools - a good central store for your localization data it shouldn't be difficult to generate resources for that scenario either. That's essentially what MS Ajax does for controls but again it doesn't go nearly far enough beyond that simple (for Microsoft) scenario.

I'd be interested to see what you're talking about in more detail though - I haven't spent a ton of time looking at the client side localization issue (even though I'm working more and more with client side code), but I can't imagine that it would be to hard to build a client resource generator that can output a .js file <s>...

Rick Strahl's Web Log
July 19, 2007

# Rick Strahl's Web Log


Bojan
November 27, 2009

# re: Global Resources Localization Suggestion for ASP.NET

Hi Rick, after spending some time trying to integrate different resources, I completely agree that the MS solution is weak.
I would very much like to see your solution, but the source code link doesn't work - would you be so kind to fix that?
Regards, Bojan.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024