Maksim Vi.
Maksim Vi.

Reputation: 9225

Localization. Extending ASP.NET Resx Resource Provider

For my website I have a custom resource provider for localization purposes (localized strings are stored in database). It works just fine, but I would like it to work with the default Resx Resource Provider: look up localized string in resx resources and if doesn't exist then pull it from the database.

But it looks that as soon as I change IIS globalization setting to use my own resource provider factory, then the default resx resource provider factory gets ignored.

I guess the solution would be to extend my own resource provider, but I can't find how to reference resx resources from inside of my resource provider.

Thanks.

Upvotes: 4

Views: 6124

Answers (2)

Maksim Vi.
Maksim Vi.

Reputation: 9225

Okay, it looks that extending custom resource provider with the default resX resource provider doesn't fully solve the issue, since implicit localization expressions (meta:resourcekey) don't get localized.

The possible solution I found here is to use a custom ResourceExpressionBuilder:

Configuring a custom provider is great for situations in which all resources will be stored in an alternate location, and you don't plan to leverage resources located in App_LocalResources and App_GlobalResources, respectively. What if you want to support the standard implementation for local and global resources (default provider), while also having the option to pull some resources from another source (custom provider)? You can achieve this by implementing custom expressions that target the custom resource provider.

This will allow using resX resource provider for implicit and explicit localization and custom expressions for your custom resource provider:

<%-- Local ResX --%>
<asp:Localize ID="locLocal" runat="server" Text="DefaultLocal" meta:resourcekey="locLocal" />
<%-- Global ResX --%>
<asp:Localize ID="locGlobal" runat="server" Text="<%$ Resources:GlobalResourceStrings, locGlobal %>" />
<%-- Custom Resource Provider --%>
<asp:Localize ID="locCust" runat="server" Text="<%$ ExternalResources:MyResources|CustomResourceStrings, locCust %>" meta:localize="false" />

or in code as:

string s = (string)ExternalResourceExpressionBuilder.GetGlobalResourceObject("MyResources|CustomResourceStrings", "locCust");

Upvotes: 0

McGarnagle
McGarnagle

Reputation: 102723

Edit

My answer below is wrong, as pointed out in the comments. You can get the ResXResourceProviderFactory by using reflection as follows.

IResourceProvider resxProvider;
string typeName = "System.Web.Compilation.ResXResourceProviderFactory, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
ResourceProviderFactory factory = (ResourceProviderFactory)Activator.CreateInstance(Type.GetType(typeName));
resxProvider = factory.CreateGlobalResourceProvider(classKey);

(Similar method to get the Local resources provider.)

Then, to get a resource, all that's needed is to call GetObject:

object resource = p.GetObject("ResourceKey", new System.Globalization.CultureInfo("en"));

You can use the GetGlobalResourceObject and GetLocalResourceObject methods (part of the HttpContext class) to work with .ResX files within your custom localization classes.

For example, to get a resource called "ResourceKey" from "MyResxFile.resx" (under *App_GlobalResources*), for the current culture, you would use this:

HttpContext.GetGlobalResourceObject(
    "MyResxFile", 
    "ResourceKey", 
    System.Threading.Thread.CurrentThread.CurrentCulture
);

Upvotes: 4

Related Questions