Skip to main content

Localization and Globalization

Using Localization from Code

ASP.NET provides all the Localization you need by just adding .RESX files to your Web App in the right location but sometimes you want to invoke the Localization yourself. To do this you'll use the System.Resources.ResourceManager class. This allows you to get resources by simply supplying the name of the resource and the Culture but to setup the resource itself is a bit trickier (in Visual Studio 2005) as some of the files required have been removed from Visual Studio's Templates. Because of this you'll need to use some tools to create the Resource (and optionally the Assembly to store it know as Resource Assemblies or Satellite Assemblies).
There are 3 steps to creating resources for use with ResourceManager:
1. Write a text file or .RESX file to hold your resources.
2. Compile the resources in step 1 into a .RESOURCES file.
3. Compile the .RESOURCES file in step 2 into a Satellite Assembly.
4. Locate the Satellite Assembly from step 3 into a location which is recognised by the Localisation mechanism.

1. If your resources are all strings then the easiest thing to do is add them to a .TXT file. If your resources are more than strings e.g. images then you should probably use a .RESX file. .RESX files are the usual location for resources. These are added to your Class Library Project in VS by selecting the project and clicking the Add File and then choosing Resource File.
If you wish to use a .TXT file then here's how you enter the resources:
myFirstResource = here is my first resources value
mySecondResource = here is my second resources value

👉
Note that the .TXT file must be saved with UTF-8 support, you'll probably find this in your text editor save options somethere, notepad has it, this is required to support some culture specific characters like accents.

2. The .TXT file or .RESX file is not enough for the ResourceManager, this .RESX file has to be converted to a .RESOURCES file before it can be used, this can be done with the tool, ResGen.exe,
resgen strings.en.txt strings.resources
resgen strings.es.txt strings.es.resources.
for more see http://msdn.microsoft.com/en-us/library/xbx3z216(VS.80).aspx

If you wish to use these bare .RESOURCES files then you can by following this http://msdn.microsoft.com/en-us/library/khyt7e7y.aspx but note that there are issues with Concurrent access on IIS so you may want to embed the resource in an Assembly (next step).

3. This .RESOURCES file can then be embedded in your DLL for later use by the ResourceManager but I found some little caveats here which cost me at least 1 day to figure out. This caveat is that the naming of the .RESOURCES files is also used as well as the DLL.
What I found it that for other cultures the .RESOURCES file must be named with that Culture as it does get used e.g.
The Default culture is English (en), the other culture used is Spanish (es).

You create 2 .TXT files to store the resources
strings.txt and strings.es.txt.

You then generate 2 .RESOURCES files from these with, it is these files that must have the correct naming i.e. the Spanish version must have the ".es" in the name before the extension.
resgen strings.en.txt strings.resources
resgen strings.es.txt strings.es.resources.

Now you use a Linker tool call AL.exe to embed each resource into it's own dll, note that you supply the culture here at the command line and also you must name the DLLS for the Cultures other than the default to have the ".resources" before the extentsion:
al /embed:strings.resources /culture:en /out:strings.dll
al /embed:strings.es.resources /culture:es /out:strings.resources.dll

You now copy only the .dll into the correct directories i.e. if it's aWebsite the root directory is the "bin" directory and it it's a standalone app then just copy into the same dir as the .exe.
Place the default assembly. strings.dll into the root and them create a subdirectory "es" and place the Spanish DLL in there
e.g.
/bin/strings.dll
/bin/es/strings.resources.dll

for more see http://msdn.microsoft.com/en-us/library/21a15yht(VS.71).aspx

4. If you use the bare .RESOURCES file then you can use the method described here http://msdn.microsoft.com/en-us/library/khyt7e7y.aspx. All you need to do is name the files uniquely using the pattern described, e.g. strings.es.resources for Spanish. The use the ResourceManager _rm = ResourceManager.CreateFileBasedResourceManager("strings",Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "Resources" ), null);
CultureInfo cInfo = new CultureInfo(culture);
string result = _rm.GetString(resourceStringName, cInfo);

If you use an Assembly to store your Resources then you cannot use the CreateFileBasedResourceManager instead you must use the ResourceManager's constructor.
Assembly stringsAssembly = Assembly.Load("strings");//the default assemblies name see step 3.
ResourceManager rm = new ResourceManager("strings", stringsAssembly );//"Strings" is the resource name of the default Culture i.e. strings.resource that you embedded earlier in the DLL.
string result = _rm.GetString("myFirstResource", new CultureInfo("es"));//get me the resource from the Spanish Culture DLL.

Comments

Jems Nichole said…
The information that you provided was thorough and helpful. I will have to share your article with others
TechWhirl
Unknown said…
If you're interested in .resx translation management tools, you should have a look at the software localization platform POEditor, because it has a very nice and flexible interface that you can use to translate strings collaboratively.

Popular posts from this blog

dotNET - Debugging

Debugging with .NET MSIL assemblies Visual Studio and debugging the CLR are different, I'll talk about both. MSIL Assemblies Assemblies compiled with .NET tools such as the CLR compiler are compiled into a file which contains MSIL (Microsoft Intermediate Language). At runtime the contents of the assembly are loaded into the CLR and ran as machine code. When you compile an assembly in debug a PDB file is generated alongside the DLL or EXE you've just created. The link between these 2 files is that the PDB contains the line numbers of the methods and classes as well as the file names of the original source code that created the assembly. When you launch the debugger in Visual Studio the assembly is loaded into the Debugger (similar to the CLR) along with the PDB file. The debugger now uses your PDB file contents to match the running code found in the assembly to locations in source files (hopefully in your present project). CLR CLR Inside Out (msdn magazine) .NET Framework Tools:...

Installer CustomAction, Debugging the CustomAction, InstallState

Custom Action The Custom Action is added to the Setup Project, select the Project node and hit the Custom Action button. This allows you add an Action to a particular phase in the Installation. But first you must create the Custom Action. To Add a Custom Action you must first have a Custom Action created, this is usually in the form of a Installer Class, this should be created in a seperate project, the Installer Class is actually one of the File Templates in the C# Projects. So it's File->New Project and select Visual C# Projects. Then add a Class Library, this will prompt you for the Class Library Types , select "Installer Class". Walkthrough - Creating Custom Action (msdn). Also here's a more comprehensive document on Setup/Installer implementations, it delves into the Registry etc Getting Started with Setup Projects (SimpleTalk). Visual Studio Setup Projects and Custom Actions (Simple Talk). Create your Installer Class and then add it as a Custom Action to the ...

dotNET - Use app.config ApplicationSettings and UserSettings

When using Settings in an Assembly or .exe you can use the Settings Designer to generate a config file using Settings. The Settings Designer provides a wrapper class which allows you to provide defaults and access the config data using Properties. But what if you're not working inside that Assembly or .exe? this presents a problem. If your loading the Assembly externally and want to access that Assembly's .config file you'll probably wish to use something in the System.Configuration namespace... unfortunately it's not of much use if you've created the .config file from the Settings Designer in Visual Studio!! This is because the Designer creates Sections and ApplicationSettings and UserSettings, the System.Configuration namespace does not provide a method to access these (it has a method to access AppSettings which are a different thing. Below I've written a workaround which locates the app.config and accesses the ApplicationSettings and UserSettings using XML i...