Locating and Using Resources for a Specific Culture

The common language runtime provides support for retrieving culture-specific resources that are packaged and deployed in satellite assemblies. Satellite assemblies contain only resource files, or loose resources, such as .gif files. They do not contain any executable code.

In the satellite assembly deployment model, you create an application with a default assembly (the main assembly) and several satellite assemblies. You package the resources for the default or neutral culture with the main assembly, and create a separate satellite assembly for each language that your application supports. Because the satellite assemblies are not part of the main assembly, you can easily replace or update resources that correspond to a specific culture without replacing the main assembly for the application.

For example, in a simple "Hello world" application, if the default or neutral culture is "en" (English), you can create a resource named Greeting and store in it a single string named HelloString whose value is "Hello world!" To indicate that "en" is the application's default culture, you must also add the following System.Resources.NeutralResourcesLanguageAttribute attribute to the application's AssemblyInfo file or to one of the source code files that will be compiled into the application's main assembly.

<Assembly: NeutralResourcesLanguageAttribute("en")>

You then add support for additional cultures to your application. For example, you can support the "en-US", "fr-FR", and "ru-RU" cultures as follows:

  • To support the "en-US" or English (United States) culture, create a resource file named Greeting.en-US.resx, and store in it a single string named HelloString whose value is "Hi world!".

  • To support the "fr-FR" or French (France) culture, create a resource file named Greeting.fr-FR.resx and store in it a single string named HelloString whose value is "Salut tout le monde!".

  • To support the "ru-RU" or Russian (Russia) culture, create a resource file named Greeting.ru-RU.resx and store in it a single string named HelloString whose value is "Всем привет!".

The System.Resources.ResourceManager class provides access to culture-specific resources at run time and controls the way the application retrieves resources by using the resource fallback process. For more information, see the "Resource Fallback Process" section in the Packaging and Deploying Resources topic.

The ResourceManager object determines which resources to retrieve based upon the current thread's CultureInfo.CurrentUICulture property. For example, if an application is compiled with default English language resources in the main assembly and with French (France) and Russian (Russia) language resources in two satellite assemblies, and the CurrentUICulture property is set to "fr-FR", the ResourceManager object retrieves the French resources.

The CurrentUICulture property can be set explicitly or implicitly. The way this property is set affects how the ResourceManager object retrieves resources based on culture:

  • If the application sets the CurrentUICulture property explicitly to a specific culture in the application code, it guarantees that the resources for that culture are always retrieved, regardless of the user's browser or operating system language. Consider an application that is compiled with default English language resources and three satellite assemblies containing resources for English (United States), French (France), and Russian (Russia). If the CurrentUICulture property is set to "fr-FR", the ResourceManager object always retrieves the French (France) resources, even if the user's operating system language is not French. Make sure that this is the desired behavior before setting this property explicitly.

    Warning

    In ASP.NET applications, you must set the CurrentUICulture property explicitly, because it is unlikely that the setting on the server will match the incoming client requests. An ASP.NET application can set the CurrentUICulture property explicitly to the user's browser accept language.

  • If the CurrentUICulture property is not set explicitly by the application, it is set implicitly by the GetUserDefaultUILanguage function in Windows 2000 and Windows XP. This function is provided by the Multilingual User Interface (MUI), which enables the user to set the default language. If the UI language is not set by the user, it defaults to the system-installed language, which is the language of operating system resources.

The following example sets the CurrentUICulture property explicitly. It defines an array that contains the names of the supported cultures for the simple "Hello world" application. It then randomly selects one of these culture names, uses it to instantiate a CultureInfo object, and makes that culture the current thread's current culture. The call to the MessageBox.Show method (in the C# example) or the Interaction.MsgBox function (in the Visual Basic example) then displays the localized string assigned to the HelloString resource.

Imports System.Globalization
Imports System.Resources
Imports System.Threading

Module Module1
   Sub Main()
      ' Create array of supported cultures 
      Dim cultures() As String = {"en-CA", "en-US", "fr-FR", "ru-RU" }
      Dim rnd As New Random()
      Dim cultureNdx As Integer = rnd.Next(0, cultures.Length)
      Dim originalCulture As CultureInfo = Thread.CurrentThread.CurrentCulture

      Try 
         Dim newCulture As New CultureInfo(cultures(cultureNdx))
         Thread.CurrentThread.CurrentCulture = newCulture
         Thread.CurrentThread.CurrentUICulture = newCulture
         Dim greeting As String = String.Format("The current culture is {0}.{1}{2}", _
                                                Thread.CurrentThread.CurrentUICulture.Name, _
                                                vbCrLf, My.Resources.Greetings.HelloString)

         MsgBox(greeting)
      Catch e As ArgumentException
         Console.WriteLine("Unable to instantiate culture {0}", cultures(cultureNdx))
      Finally
         Thread.CurrentThread.CurrentCulture = originalCulture
         Thread.CurrentThread.CurrentUICulture = originalCulture
      End Try 
   End Sub 
End Module
using System;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Threading;
using System.Windows.Forms;

class Program
{
   static void Main()
   {
      // Create array of supported cultures 
      string[] cultures = {"en-CA", "en-US", "fr-FR", "ru-RU"};
      Random rnd = new Random();
      int cultureNdx = rnd.Next(0, cultures.Length);
      CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;

      try {
         CultureInfo newCulture = new CultureInfo(cultures[cultureNdx]);
         Thread.CurrentThread.CurrentCulture = newCulture;
         Thread.CurrentThread.CurrentUICulture = newCulture;
         ResourceManager rm = new ResourceManager("LocatingCS1.Greetings", 
                                                  typeof(Program).Assembly); 
         string greeting = String.Format("The current culture is {0}.\n{1}",
                                         Thread.CurrentThread.CurrentUICulture.Name,
                                         rm.GetString("HelloString"));

         MessageBox.Show(greeting);
      }
      catch (ArgumentException) {
         Console.WriteLine("Unable to instantiate culture {0}", cultures[cultureNdx]);
      }
      finally {
         Thread.CurrentThread.CurrentCulture = originalCulture;
         Thread.CurrentThread.CurrentUICulture = originalCulture;
      }
   }
}

See Also

Concepts

Resources in Applications

Retrieving Resources in Satellite Assemblies

Other Resources

Encoding and Localization

Resources in ASP.NET Applications

Change History

Date

History

Reason

May 2010

Revised extensively.

Customer feedback.