Click here to Skip to main content
Click here to Skip to main content

Dynamic Website Multi-languages Management

, 18 Aug 2007
Rate this:
Please Sign up or sign in to vote.
A smart way to manage languages on a multilingual website, using resources and globalization,localization
  • Download SampleCode - 99.4 KB

    Introduction

    A website which can support many languages and change according to the culture of a specific geographical location is not a new topic. Though there are many articles which explain the subject well, I still see that many of them are complicated to "beginners", and none of them provide a dynamic way to manage available languages on the website. This article aims to approach a more dynamic way to manage languages regarding globalization/localization concepts.

    Screenshot - GUI_Vietnamese.gif

    Screenshot - GUI_French.gif

    Screenshot - GUI_Hindi.gif

    Background

    Using resource and globalization/localization may not a best choice in providing an ability to support multiple languages in the website. However, the resource has an advantage that binany objects can also be stored (image for instance), and ASP.Net provides a way to map controls on the webpage with resources by using Expression.

    Therefore, and since this article was written to target on "beginners" rather than experienced developers, I would appreciate to listen to all open valuable suggestions. Thanks for your interests and supports.

    Now, back again to requirements that most of developers or customers may ask for:

    1. Website has to be able to change to other languages. In the scope of this article, resource will be used.

    And the change should only effect the current visitor browser. You may think of SESSION, sure.

    2. Sometimes French in France and French which spoken in Canada are different, same to English-British and English-US. ASP.Net introduces a concept called CultureInfo.

    3. What happens if language file (resource file) in a specific language (that visitor chose) doesn't have text value which needed to display on a specific position on the website? Luckily, ASP.Net introduces a concept called FallBack. There is a resource file as a backup (or default) for the others. If no key is found in a chosen resource, ASP.Net will take the value from there.

    4. Developers would like to put language files (resources) into an easy-managed hierachy folders structure but somehow the website should be able to detect what languages are currently available (by looking at available language files) and it should understand which resource file is a language file and which not. How? The following section will go more in details to explain how to approach that, together with an easy way to create a multilingual website.

    Using resources

    First, let create resource files (*.resx) and put in different folders, but those should be inside App_GlobalResources folder in ASP.Net 2.0.

    Screenshot - resxStruct.jpg

    Because languages also depend upon the geographical location. For e.g.: Linguistically speaking of Canadian French is quite different from French spoken in France. Therefore the language needs to be associated with the particular region where it is spoken, and this is done by using locale (language + location). Our resource files therefore have to be in the format of PrefixName.language-location.resx. For e.g.: fr is the code for French language. fr-FR means French language in France. So fr specifies only the language whereas fr-FR is the locale. Similarly fr-CA defines another locale implying French language and culture in Canada. Here we have lang.fr-FR.resx.

    Then, we need a way to load them at runtime when the user changes culture dynamically. Fortunately implementing this in ASP.NET 2.0 is quite easy. See the code below:

    String welcome = Resources.lang.Welcome;

    But the recommended way to localize the UI controls on a page is to set this using the VS IDE. Select the label control, go to Properties window, select Expressions->Text. Then choose Resources from the drop down and enter the class name and the Resource key:

    Screenshot - localization.jpg

    Detect and load available languages

    Now we need a smart way to detect available language files we are having on our website and when the visitor change to use another language, text in all webpages should also changed.

    We build a class to manage them, call it LanguageManager:

    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Threading;
    /// <span class="code-SummaryComment"><summary>
    </span>/// Class to manage language on the website
    /// <span class="code-SummaryComment"></summary>
    </span>public sealed class LanguageManager
    {
        /// <span class="code-SummaryComment"><summary>
    </span>    /// Default CultureInfo
        /// <span class="code-SummaryComment"></summary>
    </span>    public static readonly CultureInfo DefaultCulture = new CultureInfo("en-US");
        /// <span class="code-SummaryComment"><summary>
    </span>    /// Available CultureInfo that according resources can be found
        /// <span class="code-SummaryComment"></summary>
    </span>    public static readonly CultureInfo[] AvailableCultures;
        static LanguageManager()
        {
            //
            // Available Cultures
            //
            List<string> availableResources = new List<string>();
            string resourcespath = Path.Combine(System.Web.HttpRuntime.AppDomainAppPath, "App_GlobalResources");
            DirectoryInfo dirInfo = new DirectoryInfo(resourcespath);
            foreach (FileInfo fi in dirInfo.GetFiles("*.*.resx", SearchOption.AllDirectories))
            {
                //Take the cultureName from resx filename, will be smt like en-US
                string cultureName = Path.GetFileNameWithoutExtension(fi.Name); //get rid of .resx
                if (cultureName.LastIndexOf(".") == cultureName.Length - 1)
                    continue; //doesnt accept format FileName..resx
                cultureName = cultureName.Substring(cultureName.LastIndexOf(".") + 1);
                availableResources.Add(cultureName);
            }
            List<CultureInfo> result = new List<CultureInfo>();
            foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
            {
                //If language file can be found
                if (availableResources.Contains(culture.ToString()))
                {
                    result.Add(culture);
                }
            }
            AvailableCultures = result.ToArray();
            //
            // Current Culture
            //
            CurrentCulture = DefaultCulture;
            // If default culture is not available, take another available one to use
            if (!result.Contains(DefaultCulture) && result.Count>

    Now we can add as much as posible resource files and don't have to worry how many languages we had in our website. The class will help to detect that.

    And because this class should be used in all webpages, we dont want to repeat the code which uses it in every page, we create a PageBase class. Here Session will be used to save chosen language state:

    using System.Globalization;
    using System.Web.UI;
    public class PageBase : Page
    {
        private const string SESSION_KEY_LANGUAGE = "CURRENT_LANGUAGE";
        protected override void InitializeCulture()
        {
            base.InitializeCulture();
            
            //If you would like to have DefaultLanguage changes to effect all users,
            // or when the session expires, the DefaultLanguage will be chosen, do this:
            // (better put in somewhere more GLOBAL so it will be called once)
            //LanguageManager.DefaultCulture = ...
            //Change language setting to user-chosen one
            if (Session[SESSION_KEY_LANGUAGE] != null)
            {
                ApplyNewLanguage((CultureInfo) Session[SESSION_KEY_LANGUAGE]);
            }
        }
        private void ApplyNewLanguage(CultureInfo culture)
        {
            LanguageManager.CurrentCulture = culture;
            //Keep current language in session
            Session.Add(SESSION_KEY_LANGUAGE, LanguageManager.CurrentCulture);
        }
        protected void ApplyNewLanguageAndRefreshPage(CultureInfo culture)
        {
            ApplyNewLanguage(culture);
            //Refresh the current page to make all control-texts take effect
            Response.Redirect(Request.Url.AbsoluteUri);
        }
    }

    All pages which inherit from PageBase don't have to care about what language visitor chosing. InitializeCulture method was called very earlier in the page life-cycle. Whenever a visitor select a new language, we just have to call the protected method ApplyNewLanguageAndRefreshPage which was implemented in the base class.

            if (ddlLanguages.Items.Count > 0) //make sure there is a SelectedValue
            {
                ApplyNewLanguageAndRefreshPage(new CultureInfo(ddlLanguages.SelectedValue));
            }

    We are ready with our globalization framework. Now the only thing left is the adding of resource specific data in the resource files. For each culture we need to have a separate (and appropriately named) resource file. This process is localization. In my web.config file I have used the following properties:

    <globalization responseEncoding"=utf-8" requestEncoding="utf-8" 
    fileEncoding="utf-8" />

    Note the encoding attributes: utf-8 (8 bit Unicode Transformation Format) is used since
    it is variable length character encoding and can represent languages such as Vietnamese (in this article sample code), Greek, Arabic etc., beside ASCII compatible. For more info, see this link:
    http://en.wikipedia.org/wiki/UTF-8

    Points of Interest

    If you are using Resharper, you can download a plugin which support localization:

    Screenshot - resharper_plugins.png

    This is a pretty cool plugin which help you to detect and refactor all none-resource text and move them into resource files.

    Screenshot - resharper_1movetoresource.png

    Screenshot - resharper_2alreadyexistsinresource.png

    Screenshot - resharper_4newline.png

    Screenshot - resharper_menu.png

    History

  • 2007/08/16 - First try, using LanguageManager as Instance - 11.9 KB
  • 2007/08/18 - Use LanguageManager As StaticClass - 99.4 KB
  • Trung tam di dong qui tu cac cua hang lon nhat Vietnam

    Other good tutorials

  • Install a Windows Service in a smart way instead of using Windows Installer MSI package
  • Create animation in dotNet with alpha-blending PNG images by calling API
  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    nguyenthanhtungtinbk
    Team Leader
    Vietnam Vietnam


    PERSONAL DETAILS


    Full Name : Nguyen Thanh Tung
    Sex : Male
    Date of Birth : October 06, 1983
    Nationality : Vietnamese

    PERSONAL PROFILE

    Trustworthy, efficient, capable work under pressure, outgoing person and capable work in a team.

     

    AREA OF EXPERTISE

      • Proficient in Programming: .Net 1.0/1.1/2.0/3.0/3.5 (C#, VB.Net, ASP.Net,
        AJAX, WCF, WWF), VB4/5/6, ASP, PHP, HTML, CSS, Script, XML.
        Experience with Vs Source Safe, Team System, MsBuild, SVN/CVS. Knowledge about
        UnitTest, Test-Driven development.
      • Experience with Databases: SQL Server 2000/2005, MySQL
        4.x/5.x/6.x, Oracle, PostgreSQL, Ms. Access.
      • Experience in EIS: ERP, CRM, SCM ...
      • Experience with Microsoft Products: CRM3/4, Sharepoint
        2003/2007 ...
      • Proficient in OS: Linux (Redhat, Fedora, Mandrake, Suse), Windows (2000/2003
        Server, XP, Vista).
      • Proficient in Graphics (Flash, Photoshop, 3DMax …); Microsoft Office, Visio,
        Microsoft Project.
      • Proficient in Network Devices: Router, Switch, Firewall Server, Mail Server,
        FTP Server, DNS, VPN.
        Experience in Servers: IBM, HP, Sun, Dell ...
      • Familiar with OO and SOA concepts.
      • Knowledge about project management: CMMI, Agile and Scrum, Software
        Engineering, System Analysis and Design, IT Project Management. 
      • Knowledge in Accounting and Finance: Financial Statement, Income
        Statement ...
       


      MAIN PROJECTS DONE IN THE PAST
      • SMS Gateway.
      • POP3-IMAP-SMTP App.
      • Products Management Sys.
      • Hedge Fund Management Sys.
      • Motion detection.
      • 3D games engine (C# using OpenGL Lib).
      • Video Conference.
      • Information Retrieval.
      • Microsoft CRM3/4
      • Microsoft Sharepoint Portal 2003/2007
      • CMS
      • E-Commerce


    Comments and Discussions

     
    QuestionDynamic Website Multi-languages Management [modified] Pinmemberiyad ish4-Feb-13 1:53 
    GeneralGlobalResource folder does not exist Pinmembercsamateur26-Jul-10 16:23 
    Questionis there any way to add or rewrite global resources file prograsmatically? Pinmembermohandesmehran10-Jun-10 9:00 
    GeneralMy vote of 1 PinmemberMark Newton30-Jan-09 1:09 
    GeneralThe resource object with key "Test" was not found PinmemberMember 319848815-Nov-08 6:33 
    Generalreg: Video Conferencing Pinmembervibgyor21-Sep-08 18:55 
    GeneralVideo conferencing Pinmemberboa sovann17-Jul-08 16:04 
    GeneralGood Article PinmemberGanesan S30-Sep-07 18:59 
    GeneralRe: Good Article Pinmembernguyenthanhtungtinbk1-Oct-07 1:30 
    AnswerRe: Good Article PinmemberGanesan Sankaran3-Oct-07 2:19 
    GeneralSMS Gateway PinmemberNguyen Thanh Luc18-Aug-07 23:54 
    GeneralRe: SMS Gateway Pinmembernguyenthanhtungtinbk18-Aug-07 23:59 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web02 | 2.8.140721.1 | Last Updated 18 Aug 2007
    Article Copyright 2007 by nguyenthanhtungtinbk
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid