Working with Resources Files, Culture & Regions in .Net

Resources Files are a way to store data that the application will use such as strings and images which can be translated via localisation.

1,421 words, estimated reading time 5 minutes.
Introduction to Programming with C#

This article is part of a series of articles. Please use the links below to navigate between the articles.

  1. Learn to Program in C# - Full Introduction to Programming Course
  2. Introdution to Programming - C# Programming Fundamentals
  3. Introduction to Object Oriented Programming for Beginners
  4. Introduction to C# Object-Oriented Programming Part 2
  5. Application Flow Control and Control Structures in C#
  6. Guide to C# Data Types, Variables and Object Casting
  7. C# Collection Types (Array,List,Dictionary,HashTable and More)
  8. C# Operators: Arithmetic, Comparison, Logical and more
  9. Using Entity Framework & ADO.Net Data in C# 7
  10. What is LINQ? The .NET Language Integrated Query
  11. Error and Exception Handling in C#
  12. Advanced C# Programming Topics
  13. All About Reflection in C# To Read Metadata and Find Assemblies
  14. What Are ASP.Net WebForms
  15. Introduction to ASP.Net MVC Web Applications and C#
  16. Windows Application Development Using .Net and Windows Forms
  17. Assemblies and the Global Assembly Cache in C#
  18. Working with Resources Files, Culture & Regions in .Net
  19. The Ultimate Guide to Regular Expressions: Everything You Need to Know
  20. Introduction to XML and XmlDocument with C#
  21. Complete Guide to File Handling in C# - Reading and Writing Files

Localisation is the process of writing software that can sense the user's locale and change its behaviour based on that information. This includes language, date and number formatting and currency.

We revisit the Hello World application and localise it to demonstrate the techniques and features used in creating global applications. We will then look at resource files and see how they can be used for localisation and storing branding, allowing you to create generic applications with customer-specific branding.

First, let's see a simple Hello World application which shows the current date and time.

C#
using System;
class Hello
{
  public static void Main()
  {
    Console.WriteLine("Hello World!");
    Console.WriteLine("The Time is: " + DateTime.Now.ToString());
    Console.WriteLine("Please enter your name: ");
    string name = Console.ReadLine();
    Console.WriteLine("Hello " + name + ". Welcome to our test program.");
  }
}

When it is run, the application will look the same regardless of the user's locale, be it Japanese, Chinese, Arabic or Italian. To localise the application, we need to remove all references to hard-coded values, but first, we need to create our resource file.

Adding Resource Files to Applications

This is done by adding a resource file to the project from the "Add New Item" menu. It is advisable to create these resources within a separate folder in your solution to keep them together. This resource file will be our default language so name it "resources.resx".

By default, Visual Studio will show the resource editor, if it hasn't shown you can open the file from the solution explorer.

We are going to need to add a few string resources to the file, one for each string that has been hard-coded in the application.

Key name Value
HelloWorld Hello World!
TheTime The Time is: {0}
EnterName Hello World!
HelloMessage Hello {0}. Welcome to our test program.

Now our program needs a few changes to display these new values. Since the resources file is a strongly typed data object we can use resources as an object and access its properties (resources are the name of the resource file. You can change the name to match the file you created).

C#
using System;
namespace ConsoleApplication1
{
  class Hello 
  {
    public static void Main()
    {
      Console.WriteLine(resources.HelloWorld);
      Console.WriteLine(string.Format(resources.TheTime, DateTime.Now.ToString()));
      Console.WriteLine(resources.EnterName);
      string name = Console.ReadLine();
      Console.WriteLine(string.Format(resources.HelloMessage, name));
    }
  }
}

Now we have an application with no hard-coded strings. You will notice that I have used a string.Format to output data. This allows different languages to change the position of a name or any data object within the string.

Adding Languages to Resources

To create different language resources simply copy the default language file and rename it including the culture identification, e.g. for France our resources.resx will be renamed resources.fr-FR.resx.

Visual Studio does not compile all the resources into a single output assembly. Instead, it compiles each of these localised resource files into a separate assembly called satellite assemblies.

Your project structure will now look like this:

C#
- ConsoleApplication1.exe
- fr-FR
- - ConsoleApplication1.resources.dll
- it-IT
- - ConsoleApplication1.resources.dll
- de-DE
- - ConsoleApplication1.resources.dll

You will notice that the default resources are not shown, this is because they have been compiled into the application executable.

You can also generate satellite assemblies manually using the Assembly Linker tool, details of which can be found in our tutorial Creating and Implementing Satellite Assemblies.

This technique can also be used for using application settings.

Localized Number Formatting

In addition to strings, other data such as currency, dates and numbers must also be localised so that they display in the way the user will expect.

For example, in England, one million is written 1,000,000.00 but in France, it is written 1 000 000,00 and in Germany 1.000.000,00.

Numbers can be written using the correct formatting using the ToString method of the object.

C#
int i = 1000000;
Console.WriteLine(" " + i.ToString("N"));

Where N is the format character for an int. If you are outputting currency you can use C instead, which will format the number as well as add a currency symbol in the correct place.

Localisation in ASP.Net

Resources in ASP.Net Applications are created in much the same way as Forms or Console applications. Simply create a new ASP.Net folder by right-clicking on the project in Solution Explorer, followed by Add ASP.Net Folder, then App_GlobalResources. Next, right-click on this new folder and Add New Item. Select Resource and call it 'GlobalLanguages.resx'.

This will create the default language file and Visual Studio will then display the resource designer window where we can enter our data into. GlobalLanguages can be any name you wish, just substitute your name for GlobalLanguages in the code below.

On the left column (name) you enter an identifier name for the string, for example, "WelcomeMessage" and in the right-hand column (value) enter the actual message, for example, "Hello and Welcome to our Website". You can optionally add information to the comments column.

Save and close this file, then from Solution Explorer duplicate this file, giving it the name of GlobalLanguages.it.resx (it is the two-letter country code for Italy/Italian). Replace "Hello and Welcome to our Website" with the Italian "Ciao e benvenuto al nostro Website". Save and close this file.

As with the applications above, ASP.Net resources are strongly typed, so you can access them with IntelliSense using the methods shown below. After you make changes to the resource files you will need to build the project for IntelliSense to pick up on the extra or modified values.

Displaying Resource Messages with ASP.Net

Now, all we need to do is output these messages on the screen. There are a few methods for this, so pick the best one for your needs.

Setting the value of a label in the C# code behind

C#
Label1.Text = Resources.GlobalLanguages.WelcomeMessage;

Raw HTML in the ASPX

C#
<a href="#"><%=Resources.GlobalLanguages.WelcomeMessage %></a>

Reading the Value into a String object

C#
string WelcomeMessage = Resources.GlobalLanguages.WelcomeMessage;

When you run the application you will see the English message written out on the screen.

Changing Resource Languages

You can change the resource file language that is displayed by changing the current resource provider culture. The constructor of the CultureInfo class takes the five-character language code to use from the Messages.xx.resx filename. Shown below is the code to change to Italian.

C#
Resources.GlobalLanguages.Culture = new CultureInfo("it");

For this tutorial, I have hard-coded the language, but it can be loaded from a configuration file, query string, session variable or profile information or any other method you desire. If you specify a language to the CultureInfo that does not have a Messages.xx.resx file then the default Messages.resx will be used.

You can also use string placeholders in the resource file, so you could have a string "Welcome back {0}, you have {1} new messages" and use a string.format to enter usernames and numbers. You can see an example of this in action in the sample download below.

The example uses three languages - English, French and Italian with buttons to change the language. I am also outputting the date so I have changed the System.Threading.Thread.CurrentThread.CurrentCulture to match the language selected so that when the day is outputted the system automatically outputs the correct day for the language.

Using Resource Files in C# Applications

As well as being used for application localisation, resource files can also be used to hold files associated with the application, such as images, sounds and other data objects. For example, you can create a generalised application and use resource files and satellite assemblies to create custom-branded or specific applications without recompiling the application.

Resources can hold many different types, including Bitmap images. In the resource editor, you can change the type of resource from the drop-down list. The strongly typed resources will return an object of the correct class when you access the key. When you access a string it will return a string object and when you access an image it will return a Bitmap object.

C#
Bitmap bmp = applicationStringResources.MyLogo;

Assemblies can be individually compiled into DLL satellite assemblies which can be dropped into the application directory or global assembly cache so they can be used at runtime using the ResourceManager. The process of creating and using satellite assemblies is described in more detail in the Creating and Implementing Satellite Assemblies tutorial.

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 3 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. ES

    On Friday 19th of August 2011, Ekrem SABAN said

    Hello!

    I am asking about a bit more complicated case, where the "Hello, World!" program can also greet the World in German.

    I modified your code to

    C#
    static void Main(string[] args)
    {
        Console.Write("0: English, 1: German");
        int language = Console.Read();
    
        switch (language)
        {
            case 1:     / de
                Console.WriteLine(applicationResourcesDE.Hello);
                break;
            default:    / en
                Console.WriteLine(applicationResources.Hello);
                break;
        }
    
        Console.Read();
    }

    I also created a second resource with the name above for German that has the same "Hello" label in it. All done in Microsoft Visual Studio 2010 Express...

    When I now try to run it, there is a compile-time error which reads

    The name "applicationResourcesDE" does not exist in the current context.

    So, I am asking about the more complicated case of creating somehow a "current context" that also "knows" about German greeting...

    Thank you for your reply!

  2. ES

    On Friday 19th of August 2011, Ekrem SABAN said

    Found what was missing: I had to select on the top of the applicationResourceDE in the combo box "Internal" (defaults to "no code generation").

  3. AK

    On Sunday 3rd of April 2011, Akky said

    Hello!
    I have a list of strings stored in a file called as "Data.txt" that i have added to the Resources.resx.
    Now, i was to compare it with a String stored in the Windows form.
    I know that i can access the file using
    "Properties.Resources.Data"
    but now how can i compare its contents with the sting stored in Windows Application From.
    Like i have :-
    string s1 = "bus";
    and in the Data.txt , I have i list like this....
    cat
    mat
    bus
    road
    shard
    see
    help
    me
    out
    people

    So, how can i compare this list in Data.txt with "s1" and find out if s1 is a part of Data.txt or not....??
    P.S. :- "Please Help"