views:

550

answers:

2

How do you get the .resx file the page is currently using? For example, if I set culture to fr-FR on Default.aspx, it should give me Default.aspx.fr.resx or Default.aspx.fr-FR.resx or Default.aspx.resx depends on which one exists.

Do they have something like that in ASP.NET or I have to write it myself?

A: 

I'm not aware of a built-in property that would return the current resource file in this fashion.

CultureInfo.CurrentUICulture.Name returns the current UICulture in use, and the Name property is the shortened form. You could use this to build up the info yourself, for example:

string pageResx = VirtualPathUtility.GetFileName(Request.Path) + "." + 
CultureInfo.CurrentUICulture.Name + ".resx";

Depending on what you plan to do with this info I would be somewhat cautious and you should test this approach for your scenario.

Ahmad Mageed
This is what I started with. It'll always tell you .aspx.en-US.resx, even when the page is using .aspx.resx. I added codes to check for the existence of en.resx and en-US.resx to account for fall back cases. It would be nice if there's a standard way of finding it tho...
@Ben: right, that's the caveat with the default resource.
Ahmad Mageed
+1  A: 

You can use the GetResourceFileName() method of the ResourceManager class to construct a valid resource culture name. A quick peek at the methods implementation via reflector shows us that the method utilizes the name property of the CultureInfo object passed by the caller to build the resource file name.

protected virtual string GetResourceFileName(CultureInfo culture)
{
    StringBuilder builder = new StringBuilder(0xff);
    builder.Append(this.BaseNameField);
    if (!culture.Equals(CultureInfo.InvariantCulture))
    {
        CultureInfo.VerifyCultureName(culture, true);
        builder.Append('.');
        builder.Append(culture.Name);
    }
    builder.Append(".resources");
    return builder.ToString();
}

The GetResourceFileName() method calls the internal static method VerifyCultureName() to ensure we have a valid resource culture name. Taking a look into VerifyCultureName() method shows us that some simple validation takes place.

internal static bool VerifyCultureName(CultureInfo culture, bool throwException)
{
    if (culture.m_isInherited)
    {
        string name = culture.Name;
        for (int i = 0; i < name.Length; i++)
        {
            char c = name[i];
            if ((!char.IsLetterOrDigit(c) && (c != '-')) && (c != '_'))
            {
                if (throwException)
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", new object[] { name }));
                }
                return false;
            }
        }
    }
    return true;
}

To make use of the GetResourceFileName() method you will have to derive a class from the ResourceManager type and override the virtual method in the base class. The GetResourceFileName() method is protected so we will have to wrap it in a public method to expose it to the outside world.

public class ResxResourceManager : ResourceManager
{  
    protected override string GetResourceFileName(System.Globalization.CultureInfo culture)
    {
        return base.GetResourceFileName(culture);       
    }

    public string GetResxFileName(System.Globalization.CultureInfo culture)
    {
        return GetResourceFileName(culture).Replace(".resources", ".resx");
    }
}
Phaedrus
This is close to what I get from my custom method, which would return Default.aspx.en-US.resx. But the page is actually using Default.aspx.resx because en-us.resx doesn't exist.I am currently checking if en-us.resx or en.resx exist, then fall back to the default .resx, which works ok. Just wondering if there's a better/standard way of finding it.