The Resource Fallback Process


The ResourceManager class has built-in support for resource fallback. This means that when you attempt to access a resource that doesn't exist for the given culture, the ResourceManager attempts to "fall back" to a less specific culture. The less specific culture is the Parent of the culture, so recall from Figure 3.3 that a specific culture falls back to a neutral culture, which falls back to the invariant culture. You can think of this as inheritance for resources. This behavior ensures that you do not duplicate resources and that as your application's resources get more specific, you need to detail only the differences from the "parent," just as you would with class inheritance.

Consider how this works with string resources. Let's add another string resource to Form1Resources.resx in our main assembly (also called the fallback assembly). The Name is "ColorQuestion" and the Value is "What is your favorite color?". Add a similar string resource to Form1Resources.fr.resx with the Value "Quelle est votre couleur préférée?". Now consider that not all versions of English are the same. The spelling of English in the United States often differs from the spelling of the same words in the United Kingdom, Canada, and Australia: Color is the one that everyone seems to remember. So "What is your favorite color?" will not go down well in the United Kingdom because two of the words are spelled "incorrectly." Add a similar string resource to Form1Resources.en-GB.resx (where "en-GB" is "English (United Kingdom)") with the Value "What is your favourite colour?". Figure 3.7 shows the relationship between the resources.

Figure 3.7. String Resources in Fallback and Satellite Assemblies


So let's consider what will happen when the CurrentUICulture is set to various cultures and ResourceManager.GetString is called to get the "ColorQuestion" string. If CurrentUICulture is French, ResourceManager.GetString looks for the string in the fr\WindowsApplication.resources.dll satellite assembly. It finds the string immediately and returns it, and that is the end of the process. If CurrentUICulture is French in France ("fr-FR"), ResourceManager.GetString looks for fr-FR\WindowsApplication1.resources.dll and fails to find it. It then falls back to the Parent of fr-FR culture, which is neutral French, and finds the string there. The benefit of this approach is that if the CurrentUICulture is French in Canada ("fr-CA"), the same steps would happen, with the same result. In this way, we can deploy the neutral French satellite assembly and have the French language covered, regardless of where it is used.

Now consider what happens to English. If the CurrentUICulture is English in the United Kingdom ("en-GB"), ResourceManager.GetString looks for the string in en-GB\WindowsApplication1.resources.dll. It finds it, and the people in the United Kingdom get a string that gives them a warm and loved feeling. If the CurrentUICulture is English in the United States ("en-US"), ResourceManager. GetString looks for enUS\WindowsApplication1.resources.dll and doesn't find it. It falls back to neutral English ("en") and looks for en\WindowsApplication1.resources.dllbut it doesn't find that, either. It falls back to the parent of "English", which is the invariant culture. It looks for the resource in the main assembly and finds it there. Similarly, if the CurrentUICulture is German, for example, ResourceManager.GetString falls back all the way to the main assembly and returns the original English (United States) string. Only if the string is not present in the main fallback assembly is an exception thrown; this makes sense because to ask for a string that doesn't exist is clearly a programmer error.

It should be noted that because of the way in which the .NET Framework probes for assemblies, if you have installed your satellite assemblies in the Global Assembly Cache (GAC), they will be found there first before the application's folders are probed.


The fallback process enables you to create only those resources that are different from their parent. In the case of strings, it is highly likely that almost every string in every language will be different from the original English, but that regional variations are much fewer and farther between. After all, the majority of U.S. English is the same as U.K. English. The fallback process behaves the same way for other resources such as bitmaps, but the number of differences is likely to be fewer. A wise approach to using bitmaps in your application is to strive to create bitmaps that are as culturally neutral as possible. If you can create a bitmap that does not include words, does not use colors to convey meaning, and does not rely upon culturally-specific references (such as the U.S. mailbox), the bitmap will have a broader appeal. If you follow this approach, the main assembly will naturally have every bitmap required by the application. However, unlike string resources that almost always need to be translated to other languages, it is unlikely that the satellite assemblies will contain many differences.

NeutralResourcesLanguageAttribute and UltimateResourceFallbackLocation

As wonderful and helpful as the fallback process might sound, the previous explanation might provoke the question, "If the CurrentUICulture is en-US, won't every call to ResourceManager.GetString take longer than necessary because it is looking first for the en-US resource (and failing to find it) and second for the en resource (and failing to find it) before finally trying the main assembly?" The answer is, yes, it will take longer. For this reason, we have System.Resources.Neutral-ResourcesLanguageAttribute. The NeutralResourcesLanguage attribute enables you to declare the culture of the main assembly. The purpose of this is to save unnecessary searching for resource assemblies. You use it like this:

 [assembly: NeutralResourcesLanguageAttribute("en-US")] 


This line can go anywhere (for example, at the top of Form1.cs), but it is best placed with other similar assembly attributes in AssemblyInfo.cs. With this attribute in place when CurrentUICulture is en-US, ResourceManager.GetString looks in the main assembly immediately without performing unnecessary lookups in the en-US or en folders. In Visual Studio 2005, you can set this same attribute in the Assembly Information dialog (click the Assembly Information... button in the Application tab of the project's properties).

The .NET Framework 2.0 introduces an overloaded NeutralResources LanguageAttribute constructor that accepts an additional parameter, which is an UltimateResourceFallbackLocation. This enumeration has two members, shown in Table 3.2.

Table 3.2. UltimateResourceFallbackLocation Enumeration

Member

Description

MainAssembly (default)

Resources are located in the main assembly

Satellite

Resources are located in a satellite assembly


You can use this enumeration to specify that the fallback resources are not in the main assembly but are instead in a satellite assembly:

 [assembly: NeutralResourcesLanguageAttribute("en-US",   UltimateResourceFallbackLocation.Satellite)] 


In this scenario, your main assembly contains no resources, and all resources are placed in satellite assemblies. In our example, there would be no Form1Resources. resx file; instead, there would be a Form1Resources.en-US.resx file from which the en-US\WindowsApplication1.resources.dll assembly gets generated. Before adopting this approach, you might consider that Visual Studio does not have any facility for not generating a default resource. For example, Visual Studio always generates Form1.resx for Form1, and this resource is placed in the main assembly. You would then have to create a second similar resource for en-US, making the resource in the main assembly redundant. (Unfortunately, Visual Studio 2005's Assembly Information dialog does not allow you to set the UltimateResourceFallbackLocation, so you must set this value manually in AssemblyInfo.cs). Of course, the command-line tools don't have this preconception, so you can create your own build script to build the main assembly without the redundant resources. In this scenario, you would let Visual Studio 2005 create redundant resources, and the final build process would simply ignore them. The only minor downside is that you should keep the redundant resources in synch with the fallback resources so that there is no difference between the Visual Studiodeveloped application and the final build application.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net