|
using System;
using System.Resources;
using System.Reflection;
using System.Globalization;
namespace GlobalizationModule
{
/// <summary>
/// Class LocalizeAttribute implements localization of a simple
/// control by loading a language specific string from a resource
/// and assigning it to the target object's property.
/// </summary>
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Field, AllowMultiple = false)]
public class LocalizeAttribute : Attribute
{
/// <summary>
/// Enum LocalizeMode specifies how to localize
/// target control.
/// Fields => localize child objects of target
/// Action => localize target
/// </summary>
public enum LocalizeMode
{
Fields,
Action
}
public LocalizeAttribute()
{
// Default action is to assign to the Text property of the target
action_ = "Text";
mode_ = LocalizeMode.Action;
}
private string action_;
/// <summary>
/// Property of target object to assign to.
/// </summary>
public string Action
{
get { return action_; }
set { action_ = value; }
}
private string resourceName_;
/// <summary>
/// Name of resource to load.
/// </summary>
public string ResourceName
{
get { return resourceName_; }
set { resourceName_ = value; }
}
private string resourceBaseName_;
/// <summary>
/// Base name from which resource will be loaded.
/// </summary>
public string ResourceBaseName
{
get { return resourceBaseName_; }
set { resourceBaseName_ = value; }
}
private LocalizeMode mode_;
/// <summary>
/// Specifies how to localize the target control.
/// Fields => localize child objects of target
/// Action => localize target
/// </summary>
public LocalizeMode Mode
{
get { return mode_; }
set { mode_ = value; }
}
/// <summary>
/// Localize 'target' object by replacing the target's Action
/// property with a localized string.
/// </summary>
/// <param name="target">The object to localize</param>
/// <param name="targetName">Name of the object in its containing class</param>
/// <param name="page">The web page class that contains the target</param>
public virtual void LocalizeObject(object target, System.Web.UI.Page page)
{
// User's page class is superclass of the ASP.NET page class
Type userPageClass = page.GetType().BaseType;
// The user's assembly is the one that holds his/her page class
Assembly targetAssembly = userPageClass.Assembly;
CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentUICulture;
string s = (string)LoadResource(ResourceName, culture, page, targetAssembly);
// Invoke the target's Action property. Most of the time this
// means we'll set the target's Text property.
target.GetType().InvokeMember(
this.Action,
BindingFlags.SetProperty,
null,
target,
new object[]{ s });
}
protected object LoadResource(string resourceName, CultureInfo culture, System.Web.UI.Page page, Assembly assembly)
{
// First check if we have the resource string in cache -
// if so, return it from there.
string key = string.Format("resource.{0}.{1}.{2}", assembly.FullName, culture.Name, resourceName);
object o = page.Cache[key];
if (o != null) return o;
// Load the resource string from the satellite assembly using the
// resource manager, and save it into the cache for future requests.
ResourceManager resMan = GetResourceManager(ResourceBaseName, page, assembly);
// There are a number of ways we could handle the case when a resource
// is not found - we could e.g., simply allow the exception to pass and
// let the global OnError handler handle it. Instead, we'll show a special
// error string.
string localized = string.Format("<font color=\"red\">MISSING RESOURCE '{0}' FOR CULTURE: {1}</font>", resourceName, culture.Name);
try
{
localized = resMan.GetString(resourceName, culture);
}
catch (MissingManifestResourceException)
{}
page.Cache[key] = localized;
return localized;
}
/// <summary>
/// Avoid allocating ResourceManager on every call by allocating
/// it once and storing it into HttpContext to be reused during
/// the request.
/// </summary>
protected ResourceManager GetResourceManager(string baseName, System.Web.UI.Page page, Assembly assembly)
{
string key = string.Format("{0}.{1}", assembly.FullName, baseName);
if (page.Application[key] == null)
page.Application[key] = new ResourceManager(baseName, assembly);
return (ResourceManager)page.Application[key];
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Sami Vaaraniemi has been working as a software developer since 1990, primarily on Microsoft technologies. After 12 years of Win32 API and C++ he switched to .NET. He currently works as an independent consultant and can be contacted through his website at www.capehill.net.