This project is read-only.

Project Description

Multilanguage Controls is a control library to .NET Framework 2.0 with two common controls used in a web application: Image and ImageButton. The key point is that each control gets the showed image from a resource file rather than get it directly through the property ImageUrl.
The idea came from the need to work with images containing words. In the common way, type some code is necessary to obtain the desired image by changing the ImageUrl property to get the image with translated words according to the selected culture to each Image or ImageButton control in the project. The Multilanguage Controls extends System.Web.UI.WebControls.Image and System.Web.UI.WebControls.ImageButton encapsulating this features and uses a HTTP Handler, included in the control library, to get the image from resource file according to the selected culture and only needs that you register the handler in the web.config file and set three properties of the control.

How to use in a Visual Studio 2005 Web Application

  • The images needs to be added to a global resouces (.resx files located in the App_GlobalResouces ASP.NET folder). See MSDN
  • You can add the controls to the Toolbox; by this way, you can drag and drop controls on web forms. See MSDN
  • Register the HTTP Handler used by the controls in the <system.web> section of the web.config file:
	<system.web>
		...
		<httpHandlers>
			<add verb="*" path="MultilanguageControlsHandler.ashx"
type="MultilanguageControls.Handler, MultilanguageControls"/>
		</httpHandlers>
		
	</system.web>
  • After adding control to the page, you need to define the following three properties:
Properties.jpg
ImageType: indicate the System.Drawing.Imaging.ImageFormat of the desired image. The default value is "Jpeg".
ResourceKeyName: The name of the resource key of the resource file containing the desired image.
ResouceType: The type of the desired resource from the AppGlobalResources folder (e.g., for the Images.resx, Images.en-US.resx, Images.es-ES.resx, the type is Resources.Images_)
The ImageURL property only takes effect at design time. At the run time, ImageUrl is defined to call the registered HTTP handler passing the values of properties above.

    /// <summary>
    /// Image control that obtains the desired image from a resource file
    /// </summary>
    [ToolboxData("<{0}:Image runat=server></{0}:Image>")]
    [Description("Image Control that obtains the desired image from a resource file")]
    [Localizable(true)]
    public class Image : System.Web.UI.WebControls.Image
    {
        . . .
        /// <summary>
        /// Define the ImageUrl property of the image control from 
        /// registered HTTP handler in web.config file
        /// </summary>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e); 
            
            if (_resourceType != null && _resourceKeyName != null)
            {
                this.ImageUrl = string.Format(
"MultilanguageControlsHandler.ashx?culture={0}&resource={1}&key={2}&format={3}", 
Thread.CurrentThread.CurrentUICulture.Name, _resourceType, _resourceKeyName, 
_imageType.ToString());
            }
        }

        . . .

    }

The handler gets the image from resource file that corresponds to the System.Threading.Thread.CurrentThread.CurrentUICulture passed by the control and returns the image to the control.

    public class Handler : IHttpHandler
    {
        private string _culture, _resourceType, _key, _format;
        private MemoryStream _imageStream;

        /// <summary>
        /// Implements the IHttpHandler.ProcessRequest
        /// </summary>
        /// <param name="context">The current execution HTTP process</param>
        public void ProcessRequest(HttpContext context)
        {
            GetParameters(context);
            SaveImage();

            //Return the image to the control
            context.Response.ContentType = 
                string.Format("image/{0}", _format.ToString());
            context.Response.BinaryWrite(_imageStream.GetBuffer());
        }

        /// <summary>
        /// Obtain parameters passed by the image control
        /// </summary>
        private void GetParameters(HttpContext context)
        {
            _culture = context.Request.QueryString["culture"];
            _resourceType = context.Request.QueryString["resource"];
            _key = context.Request.QueryString["key"];
            _format = context.Request.QueryString["format"];
        }

        /// <summary>
        /// Get the image from the resource file and save it on a memory stream
        /// </summary>
        private void SaveImage()
        {
            //Get the image from de resource file
            ResourceManager rm = 
                new ResourceManager(_resourceType, GetResourceAssembly());
            Bitmap bmp = (Bitmap)rm.GetObject(_key, new CultureInfo(_culture));

            //Save the image in a memory stream
            _imageStream = new MemoryStream();
            bmp.Save(_imageStream, GetImageFormat());
        }

        /// <summary>
        /// Implements the IHttpHandler.IsReusable
        /// </summary>
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Find and return the satelite assembly with the resources
        /// </summary>
        /// <returns>System.Reflection.Assembly object</returns>
        private Assembly GetResourceAssembly()
        {
            Assembly assembly = null;

            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (a.FullName.IndexOf("App_GlobalResources") > -1)
                {
                    assembly = a;
                    break;
                }
            }

            return assembly;
        }

        /// <summary>
        /// Find the specified image format in the control's ImageFormat property
        /// </summary>
        /// <returns>ImageFormat object</returns>
        private ImageFormat GetImageFormat()
        {
            ImageFormat imgFormat = ImageFormat.Jpeg;

            foreach (PropertyInfo p in typeof(ImageFormat).GetProperties())
            {
                if (p.Name == _format)
                {
                    imgFormat = (ImageFormat)p.GetValue(null, null);
                    break;
                }
            }

            return imgFormat;
        }
    }

If you not set the ResourceKeyName and ResouceType properties, the controls will act as the base controls.

Test Web Site

The sample web site project use three specified cultures:
Portuguese(Brazil), the default culture, English (United States) and Spanish (Spain).
To select a culture, the project uses the SelectCulture.ascx user control. To load the selected culture, the project uses the PageBase class at the App_Code/PageBase.cs.

App_Code/PageBase.cs

The PageBase class is used as the base class to all the web forms that use the multilanguage features. The PageBase class override the System.Web.UI.Page.InitializeCulture method to get the current culture stored in the session (managed by the static property SelectedCulture) and set this culture as the culture for the current thread. See more about CurrentCulture and CurrentUICulture

public class PageBase : System.Web.UI.Page
{
    /// <summary>
    /// Initialize de culture choosen by the user
    /// </summary>
    protected override void InitializeCulture()
    {
        if (!IsPostBack)
        {
            DefineCulture();
            base.InitializeCulture();
        }
    }

    /// <summary>
    /// Set the culture choosen by the user
    /// </summary>
    /// <remarks>
    /// If the culture was not choosen, the default language 
    //// from the user's browser is defined
    /// </remarks>
    public static void DefineCulture()
    {
        if (SelectedCulture == null)
        {
            SelectedCulture = 
                new CultureInfo(HttpContext.Current.Request.UserLanguages[0]);
        }

        System.Threading.Thread.CurrentThread.CurrentCulture = SelectedCulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = SelectedCulture;
    }

    /// <summary>
    /// Get or set the culture to use
    /// </summary>
    public static CultureInfo SelectedCulture
    {
        get
        {
            return (CultureInfo)HttpContext.Current.Session["SelectedCulture"];
        }
        set
        {
            HttpContext.Current.Session["SelectedCulture"] = value;
        }
    }
}

SelectCulture.ascx

The user control have one flag corresponding to each culture of the project.
When the user clicks a image, a new corresponding System.Globalization.CultureInfo is created and stored in the PageBase.SelectedCulture property. Thus, the control redirects the current page to itself to load the new selected culture.

public partial class SelectCulture : System.Web.UI.UserControl
{
     . . . 

    protected void imgUS_Click(object sender, ImageClickEventArgs e)
    {
        ChangeCulture(new CultureInfo("en-US"));
    }

    /// <summary>
    /// Change the culture and redirects to the same 
    /// page to initialize the new choosen culture
    /// </summary>
    /// <param name="culture">
    /// CultureInfo object that represents the choosen culture
    /// </param>
    private void ChangeCulture(CultureInfo culture)
    {
        PageBase.SelectedCulture = culture;
        Response.Redirect(Request.UrlReferrer.ToString());
    }
}

Default.aspx

The Default.aspx is the sample page that uses the PageBase class as the base class and the SelectCulture.ascx user control to select the culture. The Image1 control is a MultilanguageControl that shows the image flag.gif from Images.resx, Images.en-US.resx or Images.es-ES.resx, according the selected culture.
The other controls use Local Resources to show the contents.

Last edited May 11, 2010 at 8:50 PM by edu1409, version 34