Click here to Skip to main content
15,895,084 members
Articles / Desktop Programming / Windows Forms

Run .NET applications in a specific culture

Rate me:
Please Sign up or sign in to vote.
4.09/5 (7 votes)
28 Jan 2010CPOL3 min read 33.9K   303   27   1
How to make a .NET application run in a specific culture

CustomCultureDemo

Introduction

As we all know, when we run a .NET application, it will use the culture installed in the machine. But sometimes, we want to run our application in a specific culture. In the beginning, I thought it would be very simple, by setting the CurrentCulture and CurrentUICulture of the application's thread to the culture we want to use. But, if there is more than one thread running in our application, we will have a problem: the culture of the other threads would still be the installed culture of the machine. Theoretically, we can set the CurrentCulture and CurrentUICulture properties of a thread when we start it. But, actually, in some cases, we cannot know exactly when a thread is created or started if it is in a ThreadPool or is created by the Invoke/BeginInvoke method of a Control or a Delegate.

Background

You should have some knowledge about CultureInfo. For more details, please go to http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28VS.80%29.aspx.

Using the Code

In my demo application, I resolved these problems by creating a class named CultureManager. It has a static property, CurrentCulture, which stores the value of the current culture used by the application.

C#
private static CultureInfo _currentCulture = CultureInfo.InvariantCulture;

public static CultureInfo CurrentCulture
{
    get { return _currentCulture; }
    set
    {
        if (value == null || value.Equals(_currentCulture))
            return;
        _currentCulture = value;
    }
}

Now, assume we store the name of the culture we want to use in the application's configuration file (to understand more about the CultureInfo class and its name, please visit http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28VS.80%29.aspx). In the CultureManager class, we have a method to create the specific culture:

C#
public static void LoadApplicationCulture()
{
    string cultureName = string.Empty;
    try
    {
        cultureName = ConfigurationSettings.AppSettings["cultureName"];
    }
    catch
    {
        cultureName = string.Empty;
    }
    if (string.IsNullOrEmpty(cultureName))
        cultureName = string.Empty;
    CurrentCulture = new CultureInfo(cultureName);
}

This method will be called in the Main() method of the application:

C#
[STAThread]
static void Main()
{
    CultureManager.LoadApplicationCulture();

Now, we have the specific culture, and we need to apply this culture for all the threads in our application. To do this, I created a method in the CultureManager class:

C#
public static void SetThreadCulture(System.Threading.Thread thread)
{
    if (!thread.CurrentUICulture.Equals(_currentCulture))
    {
        thread.CurrentCulture = _currentCulture;
        thread.CurrentUICulture = _currentCulture;
    }
}

public static void SetCurrentThreadCulture()
{
    SetThreadCulture(System.Threading.Thread.CurrentThread);
}

Using this method, we can set the current culture for any thread. For example, to apply a culture for the main thread of the application, we put a call (bold text) in the Main() method:

C#
[STAThread]
static void Main()
{
    CultureManager.LoadApplicationCulture();
    CultureManager.SetCurrentThreadCulture();

Of course, we can use this method for other threads we create using the new keyword. Here is an example:

C#
Thread t = new Thread(new ThreadStart(ShowDialogInNewThread));
CultureManager.SetThreadCulture(t);
t.Start();

Because we always need the call to the SetThreadCulture method after creating a new thread, I simplify it by adding some CreateThread methods to create threads in the class. There are four CreateThread methods, corresponding to the four versions of the constructor of the Thread object.

C#
#region CreateThread methods

public static Thread CreateThread(ParameterizedThreadStart start)
{
    Thread t = new Thread(start);
    SetThreadCulture(t);
    return t;
}

public static Thread CreateThread(ThreadStart start)
{
    Thread t = new Thread(start);
    SetThreadCulture(t);
    return t;
}

public static Thread CreateThread(ParameterizedThreadStart start, 
                                  int maxStackSize)
{
    Thread t = new Thread(start, maxStackSize);
    SetThreadCulture(t);
    return t;
}

public static Thread CreateThread(ThreadStart start, int maxStackSize)
{
    Thread t = new Thread(start, maxStackSize);
    SetThreadCulture(t);
    return t;
}
#endregion

So now, to create a new thread, we simply use one of the four methods:

C#
Thread t = CultureManager.CreateThread(
               new ThreadStart(ShowDialogInNewThread));
t.Start();

Next, we have to look for a way to set the culture for the threads created by Invoke/BeginInvoke methods of a Control or a Delegate. This is not very easy because we don't know when this kind of threads are created and started. In case the invoker is a Control, the problem can be resolved because the created thread will use the culture of that control. But with a Delegate we create manually, we have to add a call to set the culture of the thread at the beginning of the method represented by that delegate. An example is (the call is in bold text):

C#
private delegate void ShowDialogDelegate();
private void ShowDialog_Callback(IAsyncResult result) { }

private void btnDelegate_Click(object sender, EventArgs e)
{
    ShowDialogDelegate showDialogDelegate = ShowDialogByDelegate;
    AsyncCallback callback = new AsyncCallback(ShowDialog_Callback);
    showDialogDelegate.BeginInvoke(callback, null);
}

private void ShowDialogByDelegate()
{
    // Put the call to set culture at the beginning of method
    CultureManager.SetCurrentThreadCulture();
    ProgressDialog dlg = new ProgressDialog();
    dlg.ShowDialog();
}

In my demo application, the culture is Italian. There are some important notes here:

  1. The culture name must in the format "-"; for instance, "it-IT" instead of "it", because it helps you to avoid errors like: "Culture 'it' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture." (See http://msdn.microsoft.com/en-us/library/system.threading.thread.currentculture.aspx for more details).
  2. To allow a form or control to be localized, you can set their Localizable property to true.

Points of Interest

I also have some code that allows .NET applications to change culture "on the fly", but I still have some issues with it. I will post a new article about it later.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead IMIP
Vietnam Vietnam
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralChange Culture on the Fly Pin
Grant Frisken1-Feb-10 16:46
Grant Frisken1-Feb-10 16:46 

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

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