Satellite assemblies are a special kind of assembly that allows you to store resources for multiple languages in an easy-to-access format. You can create a satellite assembly, which is basically just a resource-only assembly, to contain resources for one specific language. This provides you with a lot of flexibility because you could create your application with support for a single language, and then deploy additional languages as satellite assemblies without having to recompile any of your main application code.
Creating applications with localization and globalization in mind is becoming a far more common task. In fact, it is becoming the norm for many application developers. With the use of satellite assemblies, it becomes even easier as you can hire contracted translators to supply you with XML files containing translations that you can then use to build a satellite assembly.
The .NET Framework uses a hub-and-spoke model for locating multilingual resources. If a resource is not available for the locale-specific culture in which the user resides (or claims to reside), the CLR will look for locale-neutral resources for the user's language. Finally, if none of those can be found, the CLR will use the default resources found in the main assembly. An illustration of the hub-and-spoke model for resource localization is shown in Figure 12.4.
Figure 12.4. Resource location model.
As you can see from Figure 12.4, the resource location starts at the most specific possible: the combination of language and locale. Then, if there is no match found, the locale is dropped and an attempt is made to find general resources for a specific language. If that attempt fails, the resources will be used directly from the main assembly in the default language of the application, which is often English.
When you add a resources file to your application, by default you just use a regular filename, such as MyStrings.resx. However, to supply resources (including images, icons, files, and so on) for a different culture, all you have to do is append the locale ID to the end of the filename, such as MyStrings.fr.resx and MyStrings.fr-CA.resx, and so on. Your application will still only create one strongly typed wrapper class called MyStrings, but instead of serving up the default content only, it will automatically detect the culture of the thread making the request for the resource and hand out the appropriate value. This removes the burden of conditional programming from you and makes it easier to support multiple languages.
The code in Listing 12.4 shows what it looks like to print out a value (the phrase for "the weekend") in multiple cultures by setting the current UI culture.
Listing 12.4. Displaying Localized Strings