|
Introduction
The .NET framework provides support for localization. Localization deals with customizing data and resources for specific culture or locale or language. Supporting localization is important for an application if the application is required to be customizable based on the respective culture.
Here I am going to talk about two ways of implementing and accessing resources that you can use and access from the current running assembly. The resource files should be added and administered from outside the scope of the running assembly and should not form a part of the assembly.
This approach is helpful because the resource file is generated outside the building process of an application. It provides flexibility in terms of externally creating the language-specific resource, and adding it to the executing assembly without compiling the current project.
The Approach
The two approaches are:
- Creating a satellite assembly for culture specific resource file and using it in the executing assembly
- Creating a file based resource manager which enables accessing and reading a resource file from a location outside the assembly manifest
Let us now see these two approaches in detail.
-
Creating a satellite assembly for culture specific resource file and using it in the executing assembly
The .NET framework uses the hub and spoke model for packaging and deploying resources. The hub is the main assembly that contains the executable code, and the resource for a single culture. This culture, called as neutral or default is the fallback culture for the application. Each spoke connects to a satellite assembly that contains the resource for a single culture, but does not contain any executable code.
Steps for creating a satellite assembly to include the resource file in your application:
- Create a default resource file at the root level of the application.
Let’s say, MyApplication is the application name and MyResource.resx is the default resource. MyResource.resx is called a default resource because this is the resource file that .NET runtime will look for, if there are no language-specific resource files available.
To create the above mentioned resource file using Visual Studio .NET, highlight a project and add a new item of type "assembly resource". Name the assembly resource as MyResource.resx. This will create a resource file with .resx extension.
- Create satellite assembly outside the project manifest.
I will explain how to create a satellite assembly for UK English culture (culture name:en-GB), in the following steps:
- Create a resource file and name this resource file as MyResource.en-GB.resx.
Run resource generator utility on this resource file by using the Visual Studio .NET command prompt. The command for generating a .resources file is: Resgen MyResource.en-GB.resx
This will create a binary version of the above resource file named, MyResource.en-GB.resources.
- Run the AL (Assembly Linker) utility to generate a satellite assembly from the resource file generated in the previous step (Step a). The command for generating a satellite assembly looks like as below:
Al.exe
/t:lib
/embed: MyResource.en-GB.resources,
MyApplication.MyResource.en-GB.resources
/culture:en-GB
/out:MyApplication.resources.dll
The explanation of the above command line is as below:
/t:lib: indicates that you intend to create a .dll.
/embed:MyResource.en-GB.resources,MyApplication. MyResource.en-GB.resources: Embeds and renames the resource to a name that matches the naming structure of Visual Studio IDE.
/culture:en-GB: Indicates the intended culture
/out:MyApplication.resources.dll: Indicates the name of the output DLL. The resultant DLL (MyApplication.resources.dll) should have the same naming convention to locate it.
- Place the created satellite assembly in the en-GB folder inside the bin directory of your application directory.
The directory structure should look like as below: \MyApplication\bin\en-GB\MyApplication.resources.dll
Note that you may need to create the en-GB folder inside the bin directory. You can create as many satellite assemblies as you like and place them in the bin folder of your application, under respective culture-specific directories.
Now that we have created a satellite assembly and copied it in the bin folder of the project root directory, we are ready to use this assembly to read the resource text from the resource file.
Following namespaces will be required for the code snippet written below: using System.Reflection;
using System.Resources;
using System.Globalization;
To read from the resource file, we need to create an instance of the ResourceManager with the default resource name and current executing assembly, as shown below: ResourceManager resmgr = new ResourceManager("MyApplication.MyResource ",
Assembly.GetExecutingAssembly());
Note that MyApplication is the name of the application and MyResource is the base name of the resource file.
To read a value from resource file, GetString method of the ResourceManager is used, as shown below: string msg = resmgr.GetString(messageId,ci);
Where,
messageId is the name of the key for the intended value in the resource file.
ci is the CultureInfo indicating the intended culture specific resource.
Let's assume we need to read the UK specific (en-GB) resource file for which we have created a satellite assembly and placed it in the appropriate directory. The CultureInfo can be instantiated as below: CultureInfo ci = new CultureInfo("en-GB");
If the runtime fails to load or locate this culture specific resource, it will read the intended resource text from the default resource (MyResource.resx) as discussed in Step 1 above.
-
Creating a file based resource manager which enables accessing and reading from a resource file from a location outside the assembly manifest
This approach is helpful when we need to keep the resource files at a separate location, isolated from the project manifest, and still want access to the culture specific resources from the current assembly.
Steps to include resource file in your application from outside the project manifest:
- Create a default resource file using Visual Studio .NET IDE.
Let’s say, MyResource.resx is the default resource name. MyResource.resx is called a default resource because it is this resource file that .NET runtime will look for, if there are no language-specific resource files available.
To create above mentioned resource file using Visual Studio .NET, highlight a project, and add a new item of type “assembly resource”. Name the assembly resource as MyResource.resx. This will create a resource file with .resx extension.
Similarly, create the resource file for intended culture. Let’s say, you need to create a resource file for UK English culture (culture Name: en-GB). Create this resource using Visual Studio .NET IDE and name it as MyResource.en-GB.resx.
In the same way you can create other culture specific resource files with same naming convention.
- Create .resources file from .resx file created in Step 1 above.
Run RESGEN utility on this resource file by using Visual Studio .NET command prompt. The command for creating .resources file is as below: Resgen MyResource.resx
This will create a binary format of the resource file named MyResource.resources
Similarly, create .resources for all culture-specific .resx files.
For e.g. Resgen MyResource.en-GB.resx will result in MyResource.en-GB.resources file.
Important: It is very important to follow correct naming convention for creating resource files, as it forms the base for the runtime to locate the correct resource file. These resource files have a specific naming structure as: <resource file basename>.<culture>.resources
- Keep all .resources files at the same location, e.g. C:\Program Files\ResourceSet
The path for MyResource.resources will be: "C:\Program Files\ResourceSet\MyResource.resources"
Similarly the path for MyResource.en-GB.resources will also be: "C:\Program Files\ResourceSet\MyResource.en-GB.resources"
Following namespaces will be required for the code snippet written below: using System.Resources;
using System.Globalization;
To read the key values from the resource files created in the above step, we need to use CreateFileBasedResourceManager method of the ResourceManager, as shown below: ResourceManager resourceMgr =
ResourceManager.CreateFileBasedResourceManager(resourceName,
resourcePath,null);
Where,
resourceName is the base name of resource file. In this case, it is MyResource
resourcePath is the path of the resource repository from where culture specific resource files are to be picked. In this case, it is C:\Program Files\ResourceSet
null indicates that the default runtime ResourceSet is used.
To read a value from resource file, we will use GetString method of the ResourceManager as below: string msg = resourceMgr.GetString(messageId,ci);
Where,
messageId is the name of the key for the intended value in the resource file
ci is the CultureInfo indicating the intended culture specific resource.
Let us assume we need to read the UK specific (en-GB) resource file for which we have created a resource file named MyResource.en-GB.resources. The CultureInfo can be instantiated as below: CultureInfo ci = new CultureInfo("en-GB");
If the runtime fails to load or locate this culture specific resource, it will read the intended resource text from the default resource (MyResource.resources) as discussed in Step 1 and 2 above.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 61 (Total in Forum: 61) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
I tried linking satellite assembly using the first way, but it doesn't work . The second way is pretty straight forward and it works fine. I am using VS2005. I am able to make the dll using Al.exe. Is this approach working for anyone else??
Cheers!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi. I follow the B solution steps, but I put the resource files on another project inside the same solution. The system works fine, but I got the following error when I compile the resources project:
C:\Projetos\vs2k5\MDI\Idiomas\MDI.Designer.cs(38,25): error CS0234: The type or namespace name 'ComponentModel' does not exist in the namespace 'System' (are you missing an assembly reference?) C:\Projetos\vs2k5\MDI\Idiomas\MDI.Designer.cs(53,25): error CS0234: The type or namespace name 'ComponentModel' does not exist in the namespace 'System' (are you missing an assembly reference?) C:\Projetos\vs2k5\MDI\Idiomas\MDI.Designer.cs(22,21): error CS0234: The type or namespace name 'CodeDom' does not exist in the namespace 'System' (are you missing an assembly reference?)
Thats the code:
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
Using VC2005
Thanks
Valmir Cinquini Notepad MVP
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I kept getting AL1047 linker errors until I changed the linkder line to:
Al.exe /t:lib /embed:MyResource.en-GB.resources /culture:en-GB /out:MyApplication.resources.dll
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello,
I've created a satellite assembly using approach A but it's not working. I have no error but the strings that are to be read from the resource are coming up empty. I don't know what I am doing wrong.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hello Prakash, I have tried both the options you have mentioned here in article. Second works fine but is not recommended by Microsoft. The error I get while using Satellite assembly: "Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "Resource.resources" was correctly embedded or linked into assembly "App_Web_prvhcn9b" at compile time, or that all the satellite assemblies required are loadable and fully signed."
I am very frustated now and not able to proceed in my work as I have already spent my 1 week now on solving this issue. Please help in this matter urgently.
Regards, Ruchi Shivnani
modified on Wednesday, April 9, 2008 2:57 AM
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
Using resource files we can maintain different versions of languages/strings. how to convert the data grid data(reading from database) which is entered in english and show it to the end user in different cultures, if i have a dropdown of culture names.
|
| Sign In·View Thread·PermaLink | 2.33/5 (3 votes) |
|
|
|
 |
|
|
I've been using StringDB .net for a while, and it has a handy Translate() function. By using this you can translate your default strings to the languages in your language pack. You can get it from www.swbox.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi all
I developed website in asp.net using c# in English and Arabic languages using localization and resource file, application run good in both language. But the problem that appearance of controls like textboxs or labels become bad after changing language I don't know why.waiting ur help.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi, A very good article. I have tried both options. The second one is working fine. However in case of the first one it is always returning the values from the default resx (MyResource.resx) file, even though I have created a satellite assembly for en-GB. Please help...
Regards, Prashanth
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Hi,
I am hoping someone can help me...
I have a combo box dropdown style on a form that I want to localise. I am trying to find the code to load the resource file.
For instance the code for a label called Component List is: this.label1.Text = res.GetString("Component List");
How do I do this for a combo box with a collection: blue red yellow
Any help is greatly appreciated. Thanks in advance 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is more of a combo box question than a resource question.
One way to handle it would to have a single resource string, delimited by some character such as semicolon. In this case, your resource string would be "blue;red;yellow"
When loading your form, you'd init the combo box, with something like
string[] colors = res.GetString("ColorList").Split(new char[] { ';' }); foreach (string color in colors) yourCombo.Items.Add(color);
They key takeaway here, I would think, would be to encode your list as a single string entry.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi! In the /embed option of the al.exe utility no spaces are allowed between the first and the second path. Otherwise, the AL utility will throw an error.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I was just wondering what the default culture is for the resource file? Is it always en-us unless you change this somewhere?
Thanks, gav
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
It's called the fallback resource. They do not have a culture / language associated with them.
You have * Culture specific en-US (language, culture) * Culture invariant en (language only) * Default / fallback resource (the ones that get compiled with the application).
Let's say you've en-US as your default (OS dfault). Your application [read CLR] will try to locate resources in the order above mentioned.
|
| Sign In·View Thread·PermaLink | 4.00/5 (1 vote) |
|
|
|
 |
|
|
I followed the instructions and created a file called MyApplication.MyResource.resx I did a resgen and created the dll \MyApplication>Al.exe /t:lib /embed:MyResource.en-US.Resources,MyApplication.MyResource.en-US.resources /culture:en-US /o ut:MyApplication.resources.dll
The program was not able to find the resource string and when I looked into the file with ildasm I found that the .dll was empty.. What am I doing wrong?
Howard Davis h_n_davis@hotmail.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, I'm having problems with the resource file. I built the resource file with the resourceId and the value,but I dont know if it's correct, because if I put the resouceID of the form the labels assume that value when their resouceId = null but if not, their values are not read. I want to know exactly how to fill the resource file.
Thank you.
kitrin
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
i have a visual studio project and binary version of the resource file (myresource.en-GB.resources) in c:\res\res directory.
i'm using this command to generate the satellite assembly:
al.exe /t:lib /embed:res.myresource.en-gb.resources, myresource.en-gb.resources /culture:en-gb /out:resources.dll
and i get this error: ALINK: error AL1047: Error importing file 'c:\res\res\myresource.en-gb.resources, - 0x8013110e
whats wrong?? please help
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Look at Point 2b) in this article: If it is a C# project the naming has to be
< MyApplication(Namespace) >.< Name of MyResource >.< culture >.resources and the out also explicitly needs to be < MyApplication (Namespace) >.resources.dll otherwise you have no name for the file as resources is a keyword only.
-- modified at 19:15 Wednesday 25th April, 2007
JonnyPoet
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|