In my last post I described the problem domain behind client / server localization. In this post I’m going to tackle how dynamic translation can be achieved in a client / server environment. The basic idea is to use compiled resources from the server side and transport it over the wire to the client. When talking about “resources” we want to use a mechanism which is really close to the way localization generally works under .NET. To understand this we need to have a look into the resource manager.
The .NET Resource manager under System.Resources has the following responsibilities:
- It looks up culture-specific resources
- Provides resource fallbacks when a localized resource does not exists
- Supports resource serialization
The ResourceManager can either retrieve resources from binary resource (.resources) files laying on the disk or from resource files which are embedded in an so called satellite assembly. Satellite assemblies are special assemblies (they only contain resources) which are compiled and deployed together with the corresponding main assembly but can be individually versioned. Usually you have one satellite assembly per language you support in your application. Using satellite assemblies for dynamic client / server localization doesn’t make sense because the client doesn’t use the same deployment units (aka assemblies) as the server application. Luckily the ResourceManager allows use to declare file based resource managers from binary resource files by using the static method CreateFileBasedResourceManager. This declares a ResourceManager which doesn’t depend on any particular assembly.
Binary resource files must follow a certain convention. Each binary resource file must have a basename. For example we could define a basename “MyResources”. In this case the default resource file on the disk must be called “MyResources.resources”. The language dependent resource files must be called “MyResources.[de/fr-Be..].resources”. So imagine we have the following resource structure on the server side:
someserverpath/MyResources.resources someserverpath/MyResources.de.resources someserverpath/MyResources.de-ch.resources ...
The only thing we have to do to start with dynamic localization is we need to somehow transfer all the *.resources files from the server to the client. The client needs to place all the downloaded files into a similar structure as found on the server, for example:
someclientpath/MyResources.resources someclientpath/MyResources.de.resources someclientpath/MyResources.de-ch.resources ...
After we have downloaded and placed all *.resources files on the client side we need to instantiate a resource manager for each basename. In the example above this can be achieved with the following line of code:
var myResourcesRM = ResourceManager.CreateFileBasedResourceManager("MyResources", "someclientpath/");
As soon as we want to translate something on the client we only need to call
So far so good. In the next post I’m going to show how we can get resources from the server to the client and how to handle multiple resource managers and basenames. Stay tuned.