Client / Server Localization – Introduction

This is the introduction posts about dynamic client / server localization which describes the problem domain. In one of my current projects, we are building a client / server application that uses windows communication foundation requests and responses and event driven data, which is fired over the distributed event broker. Some of the data is dynamically rendered on the client but needs to be translated into several languages. For information which is already known at compile time localization is really straight forward with WPF. But what about data which is not known at compile time of the client?

To see the difference between localizible data which is known at compile time and dynamic data we need to look how static data can be localized in WPF. We use the WPF Localization Extension. We just have to reference the localization extension and then we can define localizible data in the XAML like:

<Window x:Class="Product.Name.SomeView"
        xmlns:l="http://schemas.root-project.org/xaml/presentation">
	<StackPanel Margin="10">
        <Label Content="{l:LocText Product.Name:Main:Label_UserName}" />
		<Button Content="{l:LocText Product.Name:Main:Button_Cancel}" />
	</StackPanel>
</Window>

All we then have to do is to create a corresponding resource file Main.resx and its language equivalents (for example Main.de-ch.resx) which contains a key Label_UserName and a key Button_Cancel. The resource files get compiled into satellite assemblies and will be deployed with the client application. Whenever the user switches the language of the user interface the label and the button will contain localized information according to the selected language or text from the fallback resource (usually from the main resource file). So far so good. Let’s look into more advanced use cases.

Imagine we have the following WCF service which is used by the client:

public interface IOrderService
{
	IEnumerable<ValidationResult> ValidateOrder(Order order);
}

[DataContract]
public class ValidationResult
{
	public ValidationResult(string message) {
		this.Message = message;
	}

	[DataMember]
	string Message { get; private set; }
}

public class OrderService : IOrderService
{
	public IEnumerable<ValidationResult> ValidateOrder(Order order) {
		return new[] { new ValidationResult("Unable to process order. Customer creditworthiness validation is pending!") };
	}
}

The server might have some business rules which are only known on the server side. The client needs to dynamically render validation results in case an order is not valid. We want to have the flexibility to extend the business validation rules without changing the client application. The sample above would always give back a validation result with an English message text. If the client language would be another than English this would have no influence onto the validation message.

What if the validation takes a lot of time and we want to inform the client about the validation process with an event over the distributed event broker.

public interface IOrderService
{
	void ValidateOrder(Order order);
}

public class ValidatedEventArgs : EventArgs
{
	public ValidatedEventArgs(IEnumerable<ValidationResult> results) {
		this.Results = results;
	}

	public IEnumerable<ValidationResult> Results { get; private set; }
}

[DataContract]
public class ValidationResult
{
	public ValidationResult(string message) {
		this.Message = message;
	}

	[DataMember]
	string Message { get; private set; }
}

public class OrderService : IOrderService
{
	[EventPublication("distributed://OrderValidated", HandlerRestriction.Asynchronous)]
	public event EventHandler<ValidatedEventArgs> Validated = delegate { };

	public void ValidateOrder(Order order) {
		// start some asynchronous background task
		// immediately return to the client
		// when background task is finished, execute
		// this.OnValidated(new[] { new ValidationResult("Unable to process order. Customer creditworthiness validation is pending!") });
	}

	private void OnValidated(IEnumerable<ValidationResult> results) {
	     this.Validated(this, new ValidatedEventArgs(results));
	}
}

With this approach the client would also only retrieve untranslated validation results. In the next series of posts we are going into the nuts and bolts how a dynamic client / server validation can be achieved.

About the author

Daniel Marbach

1 comment

By Daniel Marbach

Recent Posts