In any .NET application development project which deals with multiple regions and cultures, it is important to understand and put forth a process to deal with localization. This article focuses on localization and usage of resource files for localization. In particular, the idea is to emphasize how an application can be localized in a project during the build (or development phase) and post build phases by the packaging team. This is important because the approach to localization should be loosely coupled, and should provide flexibility to localize during the build or packaging phase.
This article assumes that you are familiar with the concept of resource files in Visual Studio and why resource files are used for storing resources. However, for the convenience of the reader, some important concepts about resources in .NET applications are highlighted below:
- A resource is any data that is logically deployed with an application. A resource might be displayed in an application as error messages or as part of the GUI. Resources can contain data in a number of forms, including strings, images, and persisted objects.
- Storing data in a resource file allows you to change the data without recompiling your entire application.
- In a .NET application, localized resources are stored in individual files based on the respective locales, and loaded during runtime as per the UI Culture setting.
- This loading of a particular resource happens based on a hierarchical order, wherein at the topmost sits the fallback resources for the default culture.
- Below this comes the respective resource files for various other cultures as the case may be. Figure 1 explains this concept pictorially. "fr" happens to be the default fallback culture for all regions dealing with French, and "en" happens to be the default fallback for all regions dealing with English.
Figure 1: Loading order for resources look-up
In the sample code accompanying this article, a distributed development approach is adopted wherein the developer of an executable file (.exe) may be different from the other developers who develop the modules which this executable consumes.
Localization during build phase (or development phase)
If localization requirements are known during the build phase, then the following process can be followed by the project team:
- Developer creates a resx file for the default locale(s) for the application; say, en-GB. Please note that when we mention the culture as just "en", it is a culture without a region. And when we mention en-GB, then it is "English with Great Britain", culture with region. What this signifies is that during runtime, when the application is trying to load resources, it obtains the culture from the thread"s
System.Threading.Thread.CurrentThread.CurrentUICulture), which if not set in the application, is picked up from the Operating System's settings for region/display/language. Please note that you would have to install the respective language packs in Windows if you wish to change the UI Culture for the Operating System.
- The developer now needs a language translator to provide translations for various strings and other resources in the default resource file so that a new resource file can be created and added to the Visual Studio solution. For this, a developer can use Open Source software like RESX2Word, or evaluate and purchase a relevant third party product, which aids the translator to provide translations in a convenient editor.
Figure 2: resx2word.exe command-line usage
The RESX2Word mentioned above can convert a resx file into a Word document as shown below:
Figure 3: ResX2Word generated Word document
Note: You can safely ignore any image file related sections in the generated Word document. Image files should be handled separately as explained in later sections.
- This Word document can then be conveniently emailed to the translator. The translator has to provide translations for the non-grayed text. The users can read additional instructions from the generated Word document as shown above.
- After the language translator provides the translations, the developer can again use RESX2Word and convert the Word document back to a resx file and add the resx file to a Visual Studio project and proceed with the development as usual.
- The C# project structure should now be as below:
Figure 4: Project structure
Note: If you observe the .NET solution structure in Figure 2, "HelloWorld_Application" is the main application executable and the "HelloWorld" project is a (let's say) module which is referred by the "HelloWorld_Application" along with a utility project library called util.
These translated resx files, when built, would emit the respective satellite assemblies in the respective folders:
Figure 5: Language folder (fr-FR) and satellite assembly (HelloWorld.resources.dll)
At this stage, you can run the executable and select the relevant culture from the form and view the results accordingly:
Figure 6: Form from the Hello World application (on launch)
Figure 7: Form from the HelloWorld_Application application once "French Belgium" is selected
Note: The culture here (as displayed in the textbox) is en-US, and the UI Culture is "fr-BE". And resources in the application are loaded based on the UI Culture.
- Please note that once "HelloWorld_Application.exe" is launched, it shows the current culture settings in the text box in the right based on Operating System settings. And this changes based on what is selected by the user.
- On clicking "Submit!", a hello message is displayed in the respective language and the background image changes based on the resource loading process explained earlier (refer to Figure 1).
Localization by packaging team (post development phase)
Let us assume that once the binaries are released to the packaging team, the packaging team wants to change some strings and images for the "fr-FR" culture. The packaging-team would have to ask for the "fr-FR.resx" file in addition to the binaries for the resource which they would want to change. In this case, this would be "HelloWorld.fr-FR.resx". This file should be opened using Visual Studio, and edited as required by the packaging team for customer customization.
Figure 8: "HelloWorld.fr-FR.resx" file opened with Visual Studio
Once edited as required, the ".resx" file now needs to be separately converted to a satellite assembly. Please note that satellite assemblies contain resource files. They do not contain any application code. You create an application with one default assembly (which is the main assembly, which is HelloWorld_Application.exe in our case) and several satellite assemblies (which are "fr-FR folder" HelloWorld.resources.dll, "en-GB folder" HelloWorld.resources.dll and so on). You can create one satellite assembly for each culture that the application supports. Because the satellite assemblies are not part of the main assembly, you can easily replace or update resources corresponding to a specific culture without replacing the application's main assembly. And this is exactly what we have intend to do and what the sample does.
Note: for creating the satellite assembly from a resx file, you would have to use the resgen.exe and al.exe utilities from Windows SDK. Refer to MSDN for more details. For the current sample, you can use "Convert.bat" from the zip file by placing that in the same directory as the ".resx" file, which is a changed one (as shown below), and executing it for generating the satellite assembly.
Figure 9: convert.bat
Note: Convert.bat contains the consolidated scripts for the creation of the ".resources" file from ".resx" and the creation of the satellite assembly file by embedding the ".resources" in the satellite assembly. Finally, the satellite assembly is placed in the directory created with the culture name. This process of localization, once binaries are created, can be tested by downloading "Localization with binaries.zip". It contains all the binaries, the resx file, and the Convert.bat.
The concept of resource files in .NET is not new. Using resource files for all kinds of resources provides a standard way of dealing with all of them - be it images, icons, strings, or audio resources. It provides ease of maintenance as resources can be embedded without having the need to be referred using relative paths. Finally, it provides a loose coupling by virtue of the satellite assembly concept; wherein these resources can be customized and edited by various teams which form part of a delivery team for a project, be it the development team or any stage post binaries delivery by the development team.