Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#2.0

Architecture FAQ for Localization and Globalization: Part 2

3.43/5 (25 votes)
18 Jun 2013CPOL11 min read 2  
Architecture FAQ for localization and globalization: Part 2.

Table of contents

Introduction

You can see the part 1 of the article at LocalizationGlobalizPart1.aspx.

When we look around we see that architectures mainly discuss about loose coupling, scalability, performance, etc. Many architectures forget one of the important aspects in software which is making an application globalized. Depending on the project some applications would not really want to have multi-language based websites, but I am sure many will. So in this article we will go through a series of FAQ which will give you a quick start on making applications multi-language based.

Lately I have been writing and recording videos mostly on design patterns, UML, and many architectural stuff and you can visit http://www.questpond.com for the design patterns and UML videos. You can read my previous articles on design patterns and UML in the below links:

  • Part 1 – Design patterns Factory, Abstract factory, builder, prototype, shallow and deep copy, and singleton and command patterns: SoftArchInter1.aspx 
  • Part 2 – Design patterns Interpreter, Iterator, Mediator, Memento and observer patterns: SoftArch2.aspx
  • Part 3 – Design patterns State, Strategy, Visitor, Adapter and fly weight pattern: SoftArch3.aspx
  • Part 4 Design patterns Bridge, Composite, Decorator, Facade, COR, Proxy and template pattern: SoftArch4.aspx
  • Loosely coupled architecture using IOCDI.aspx
  • You can download by architecture interview question book from http://www.questpond.com/softArchi.zip.zip

(A) What is AL.EXE and RESGEN.EXE?

In the previous section, you have seen how we can use resource files to store data according to localized languages. However when you actually go for deployment you will not like to also install the “resx” or “txt” files. It is definitely not a good deployment practice to install data, which can be easily modified. In short some how we should install this in a binary format so that no end user can change it. That is why Microsoft introduced satellite assemblies. Satellite assemblies are assemblies which do not contain source code. They only contain resource files. You can create a satellite assembly using rsgen.exe and al.exe. They are in binary DLL format which makes it easier to ship it during deployment. So finally during deployment you do not need to ship the resx files but only the compiled satellite DLL.

Image 1

Figure 14.15: resgen.exe and al.exe in action

The above diagram will give you a complete picture of how to generate a satellite assembly. You can see from the above figure that we need two exes, resgen.exe and al.exe. Once you have made your resx file or text file, you should first convert in to a “.resource” file. This is done by using resgen.exe. Below is the command snippet for resgen.exe where LoginScreen.aspx.el.resx is the resx file and the output is the Greek. Resources file. If you do not provide the output file name it will generate “LoginScreen.resources”.

Resgen LoginScreen.aspx.el.resx Greek.Resources

You can also generate resx files from a text file using resgen.exe, below is the code snippet for that:

Resgen MyLanguage.txt MyLanguage.resx

The above command snippet will generate a MyLanguage.resx using the MyLanguag.txt file. You can make a DLL using resource files and not resx so you should make this conversion. Now once the resource file is generated it is time to make the compiled assembly so that it can be shipped during deployment. This is accomplished by using the assembly linker tool al.exe provided by Microsoft. Below is the command code snippet for the same:

al.exe /out: el.dll /c: de /embed: greek.resources

In the /out switch you need to provide the output DLL name. In /c you need to specify the culture of the resource file. With /embed you need to specify all the resources which are present in the resource file. As said previously other than strings you can also put image files like GIF, BMP, etc. So those physical resources you can specify in the /embed switch. You can specify more than one resource use “,” as a separator to specify more than one resource file.

(I) What is the use of the resource manager class?

A Resource Manager class helps us to read resource files and get the values using a key. First, you need to create an object of the resource manager. You need to specify the resource name and the assembly in the constructor.

C#
privateResourceManagerobjResourceManager = 
  new ResourceManager("Globalization.resource",
  System.Reflection.Assembly.GetExecutingAssembly());

Once the resource manager is populated with details, you can then use the GetString function to get the value by key. For instance in the below code snippet we are using the cmdAddNew key to get the value for the button cmdAddNew.

C#
cmdAddNew.Text = objResourceManager.GetString("cmdAddNew");

(A) What precautions do we need to take while deploying satellite assemblies?

When we deploy the assembly, the folder structure has to very organized. The below table shows how the folder structure should be organized. The main folder is the main application folder. All satellite assemblies should be deployed in the main application folder within their own respective folders. The respective folder is denoted by the culture code.

Image 2

Figure 14.16: Satellite Assembly folder structure

You can see from the above figure the Hindi satellite assembly is deployed in the hi folder, Greek satellite assembly is deployed in the el folder, and so on. If the program does not find resource files for a culture it uses the invariant culture satellite assembly. The above folder structure is a strict requirement when we deploy the satellite assembly. Any mismatch in the folder structure will lead to inappropriate results.

(A) Can we get a strongly typed resource class rather than using the resource manager?

In the previous question, we had seen how the resource manager class could be used to read a string from the resource file. However, there has been considerable improvement in VS.NET 2005 for resource support. You no more need to load using the resource manager class. However, Microsoft has still kept it for backward compatibility. You can now get strongly typed classes in your VS.NET intelligence as shown in the figure below.

Image 3

Figure 14.17: Strongly typed resource class

All belongs to the Resources namespace. Let us do a small sample and see how the strongly typed classes work in VS.NET 2005 and the simplicity which they bring while implementing globalization in projects. Below is the screenshot of the project. It is a simple login screen with a user ID and password text boxes. The user has options to select the language. Currently only two languages are provided: English and Greek. Depending on the languages selected, the user ID and password label values will be displayed.

Image 4

Figure 14.18: Strongly typed project

Note: In the globalization project you can get the project sample in “LoginScreenUsingStrongType.aspx”.

Below is the code snippet which describes the various important sections of the code. The first thing is the resource files. We have generated two resource files, one for Greek with el and a general resource file which will be used when the regional code does not match.
 

Image 5

Figure 14.19: Walkthrough for using the resources namespace

There are three important steps in the code:

  • First is set the culture information for the current thread with the new culture info object. Structure has the language code, which is currently selected in the drop down.
    C#
    Thread.CurrentThread.CurrentCulture = new CultureInfo (structure);
  • We set the same culture to the Resource class.
    C#
    Resources.Resource.Culture = Thread.CurrentThread.CurrentCulture;
  • Now we are all set to use the value.
    C#
    lblUserId.Text = Resources.Resource.lblUserIdResource1.ToString ();
    blPassword.Text = Resources.Resource.lblPasswordResource1.ToString ();

Note: You can get the same from the globalization folder in “LoginScreenUsingStrongType.aspx”. Try to add a new language and most of the fundamentals will be clear.

(A) Can you explain the fundamentals of the “GetGlobalResourceObject” and “GetLocalResourceObject” functions?

These two functions belong to the HttpContext object. Using it you can get the object reference of the resource object. For instance you can see from the below code snippet we have reference to the Global resource object and we are trying to get the value for the “lblUserIdresource1” key.

C#
lblUserId.Text=HttpContext.GetGlobalResourceObject("Resource", "lblUserIdResource1").To String();

Note: In the same globalization folder there is “LoginScreenUsingGetGlobal.aspx” which demonstrates how “GetGlobalResource” works.

One short note because “GetGlobalResourceObject” and “GetLocalResourceObject” operate from within the current HttpContext. It uses what the regional settings are set from the browser end.

(A) Can we sign a satellite assembly?

Yes you can sign a satellite assembly using the /key file switch which takes a “.snk” file as the input parameter.

al /res:MyLanguage.resources /c:de /keyfile:MyLang.snk out:MyLanguages.resources.dll

(I) Can you explain collation sequence in SQL Server?

First, let us define collation. Collation sequences are a set of rules which determine how the data is sorted and compared. Sorting rules can be defined with options with case-sensitivity, accent marks, kana character types, and character width.

Case sensitivity

If A and a, B, and b, etc. are treated the same way then it is case-insensitive. A computer treats A and a differently because it uses ASCII code to differentiate the input. The ASCII value of A is 65, while a is 97. The ASCII value of B is 66 and b is 98.

Accent sensitivity

If a and á, o, and ó are treated the same way, then it is accent-insensitive. A computer treats a and á differently because it uses ASCII code for differentiating the input. The ASCII value of a is 97 and áis 225. The ASCII value of o is 111 and ó is 243.

Kana sensitivity

When Japanese Kana characters Hiragana and Katakana are treated differently, it is called Kana sensitive.

Width sensitivity

When a single-byte character (half-width) and the same character when represented as a double-byte character (full-width) are treated differently then it is width sensitive.

(A) How do we define collation sequence for database and tables?

You can create a database with a language specific collation sequence. For instance in the below Create statement tblCustomer is created by a Latin language collation sequence.

SQL
Create database tblCustomer collate Latin1_General_BIN

You can also create tables with a particular collation sequence. Below is the Create Table syntax for the same.

SQL
Create table tblCustomer 
(
[CustomerCode] char(10) COLLATE Albanian_CI_AI_KS_WS NULL,
[EntryDate] [char] (8) COLLATE Korean_Wansung_Unicode_CS_AS_KS NOT NULL ,
[CustAbbrev] [char] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL 
)

(A) Can we change the order in a Select query with a specified collation sequence?

Yes we can specify a collate sequence in the Order By clause. That will change the sort according to the collation defined in the Order By clause.

SQL
ORDER BY 
{
order_by_expression 
[ COLLATE collation_name ] 
[ ASC | DESC ] 
} [ ,...n ] ]

(A) Can you list the best practices for globalization and localization?

Below are the best practices while developing international language support software:

  • Do not hardcode strings or user interface resources.
  • Make sure your application depends on Unicode.
  • Whenever you read or write data from various encodings, make sure you use the System.Text namespace. Many programmers assume ASCII data.
  • While testing, test with actual international data and environments.
  • Whenever you manipulate data, for instance numbers, dates, or currency, make sure that you are using culture-aware classes defined in the System.Globalization namespace. Below is the table which specifies in more detail about the functionality and the classes to be used to achieve the same.

    Image 6

    Figure 14.20: Functionality and classes used
  • If a security decision is based on the result of a string comparison or case change operation, perform a culture-insensitive operation by explicitly specifying the CultureInfo.InvariantCulture property. This practice ensures that the result is not affected by the value of CultureInfo.CurrentCulture.
  • Move all your localizable resources to separate DLLs.
  • Avoid using images and icons that contain text in your application. They are expensive to localize.
  • Allow plenty of room for the length of strings to expand in the user interface. In some languages, phrases can require 50-75 percent more space.
  • Use the System.Resources.ResourceManager class to retrieve resources based on culture.
  • Explicitly set the CurrentUICulture and CurrentCulture properties in your application. Do not rely on defaults.
  • Be aware that you can specify the following three types of encodings in ASP.NET:
    • Request Encoding specifies the encoding received from the client's browser.
    • Response Encoding specifies the encoding to send to the client browser. In most situations, this should be the same as Request Encoding.
    • File Encoding specifies the default encoding for .aspx, .asmx, and .asax file parsing.

(A) Why is the culture set to the current thread?

First, let me explain this question. If you look at the code snippet of how to set the culture info:

C#
Thread.CurrentThread.CurrentCulture = new CultureInfo(strCulture);

It uses the current thread to set it. What does that mean? Let us drill down a bit how IIS handles requests to understand this concept. When a user requests a resource from IIS like an ASPX page or any other resource, IIS services that request in its own thread. That means if 100 users have requested some resource from IIS it will serve every request in its own thread. In short, IIS will spawn 100 threads to service the 100 requests. It is very much practically possible that you can have different locales in different threads. Therefore when we set a culture we cannot set it for the whole application as it will affect all the requests. So when we set a culture we set it to a particular thread rather than to the whole application.

For further reading do watch the below interview preparation videos and step by step video series.

License

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