Silverlight 4 + RIA Services - Ready for Business: Localizing Business Application
To continue our series, let’s look at localizing our business applications. In today’s global village, it is often no longer OK to support only one language. Many real world business applications need to support multiple languages. To demonstrate the pattern, let’s look at localizing the Silverlight Business Application Template.
Update (3/28): I added a bit more explanation about setting culture in Visual Studio..
You can download the completed solution.
Here it is in English side-by-side with a localized version (notice the Hebrew is rendered Right-To-Left correctly):
Let’s start by creating a new Silverlight Business Application. Notice there is a server and a client project in the solution. The strings that are needed in both the server and client project are located in the server project and those that are only ever needed in the Silverlight client are in the client project. Let’s start with the server.
In the Resources folder we see two sets of resources. One for the Error messages and another for registration details. These are in a the ResX format which is an Xml file format that has been around for a long time.. there are many localization tools outside of VS that support this format. Here I will show the localization in VS.
One setup step before we get started. You need to explicitly tell Visual Studio what languages are supported in by the Silverlight application. Unfortunately, this is not supported by the VS Project Properties dialog, so you need to edit the Silverlight Applications csproj file directly.
Right click on the Silverlight project and unload
Right click again and select “Edit MyApp.csproj
Then find the SupportedCultures attribute and add the full list of cultures your application supports.
Then right click on the project and re-load project.
Ok, done with the setup, on to the actual localization.
The first step is to create a copy of each of these files with the [Local].resx extension. For example, I created one called “ErrorResources.he.resx”. Here is a full list of cultures codes.
Then open the file in VS and you see a nice editing experience. Simply replace the English text with the translated version.
Below is the translation experience in progress:
Repeat for the RegistrationDataResources.resx file.
Next we need to make these new *.he.resx accessible from the client. First let’s find the client resources directory. Notice the English resources are already linked in here. We need to add the Hebrew ones we just created.
Right click and add an Existing Item
Then browser to the ErrorResources.he.resx file in the web project.
Then select add as Link
Repeat for the other localized files from on the client.
In ApplicationStrings.resx and ApplicationStrings.he.resx I added one additional value to indicate flow direction
I then made two very small tweaks to the template to use this value. In each top level window, I need to set the flow direction.
in Main.xaml:
<UserControl
x:Class="LocalizedBusinessApplication.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
FlowDirection="{Binding Path=ApplicationStrings.FlowDirection, Source={StaticResource ResourceWrapper}}" >
and in View\LoginRegistrationWindow.xaml
<controls:ChildWindow
x:Class="LocalizedBusinessApplication.LoginUI.LoginRegistrationWindow"
x:Name="childWindow"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
Width="400"
Title="{Binding Path=ApplicationStrings.LoginWindowTitle, Source={StaticResource ResourceWrapper}}"
Style="{StaticResource LogRegWindowStyle}"
FlowDirection="{Binding Path=ApplicationStrings.FlowDirection, Source={StaticResource ResourceWrapper}}"
Closing="LoginWindow_Closing">
Now, we are ready to run the app.
It looks great, but it is all English.. how can we test the localization? Simply change your language in the browser.
In IE that is Tools\Internet Options
Make sure Hebrew is first. Then hit refresh on the page and…
What I showed here was how to localize a Silverlight application using the Business Application Template.
Enjoy!
Comments
Anonymous
March 22, 2010
Excellent Handson Sample. Really Very Good work.Anonymous
March 22, 2010
Hi Brad, Thanks for this Blog Post it's very helpful, Now with Silverlight 4 - Right to Left Support we can start developing silverlight application in Israel. by the way great talk at DevAcademy 4, see you on WednesdayAnonymous
March 22, 2010
Your sample works only when you use this namespace structure. Change your default namespace for the web to "MyCompany.Server" and on the client to "MyCompany.Client" and you can forget the resource on the client. Would be nice when MS provides some support for these scenarios. I solved it by changing the .Designer files and adding some compiler directives. But this is only a temporary solution.Anonymous
March 22, 2010
When is WCF Ria Services or WCF Data Services going to support DateTimeOffset? This is critical functionality missing to support SQL 2008.Anonymous
March 22, 2010
The comment has been removedAnonymous
March 23, 2010
Would you please say, how to chage language programmatically?Anonymous
March 23, 2010
Hi Brad, If I change my browse language settings (ie8) to 'he' your sample works wonderfully. However, if I copy your ApplicationStrings.he.resx to ApplicationStrings.af.resx and change my browser language to my local regional setting 'af' or 'af-za', then the localised settings just get ignored. Is there somewhere else I need to change it ?Anonymous
March 24, 2010
@Mikea -- did you do the "add as link" section of this post for the new file?Anonymous
March 24, 2010
Hi Brad, Yes, I did the 'add as link' section. As a test, I renamed each of your .he.resx files to .fr.resx and did the 'add as link' bit to include the relevant Web files in the SL project and changed my browser language to French [fr]. This also didn't work. I only get the 'default' strings. Are you able to get your project to work with somthing other than [he], maybe [fr] ?Anonymous
March 26, 2010
Brad Thanks for the ideas . We have to target Spanish here in Texas. How do you manage attribute based validations / labels, descriptions for Spanish and English at the Entity level ?Anonymous
March 27, 2010
@Mikea - Dohh -- Thanks for commenting.. I seem to have left out a very important and Non-obvious step. You have to edit the Silverlight csproj to add the cultures that are supported. I updated the post above to show how to do that and I am updating the sample to show a 2nd culture - french - as well.Anonymous
March 28, 2010
I made the changes to the csproj and now it works. Thanks!Anonymous
March 29, 2010
Hi Brad, Your recent blog postings have been very informative and timely given our project. We are having a problem with the resource file usage and the Required() property, which I reported on the forums. Possibly its just user error (often it can be) :) But I'm hoping to find a solution. http://forums.silverlight.net/forums/p/171552/387063.aspx#387063 KathleenAnonymous
March 31, 2010
The comment has been removedAnonymous
March 31, 2010
I started following the steps explained above, 1 .created a new SL project, edited project for adding culture he,fr-FR etc,
- created resurce files(ApplicationStrings.he.resx) for 'he' with three string, after that added reference to App.xaml then xmlns:res="clr-namespace:SilverlightControlApp.Resources"
- created <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary> <res:ApplicationStrings x:Key="ResourceWrapper" /> </ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources>
- later control binding is done as follows <Button Content="{Binding Path=ApplicationStrings.LoginButton, Source={StaticResource ResourceWrapper}}" Height="23" HorizontalAlignment="Left" Margin="178,140,0,0" Name="button1" VerticalAlignment="Top" Width="75" /> I am not able see the resurce string binding to control, control text is blank. Please help on this very critical!
Anonymous
April 01, 2010
I am sorry, I can't tell right off what the issue is. can you get the solution I created to work on your machine? Is the silverlight client picking up the right culture? ViewSource and see if the params are right going to the SL control.Anonymous
April 04, 2010
Yes your solution is working perfect, when I change culture in brower, labels are responding with brower culture. When we bind the control to resurce class, during designtime itself we can see the text which gets from resource file, this itself not happening. I tried lot of things for binding, even I have changed the constructor from internal to public. please let me if you need any sepcific data to identify the problem. Also I am working on 2010 RC veersion april release. Can you pls upload a simple SL app with two label in page1 and 2 buttons in another page with localization applied?Anonymous
April 05, 2010
<% string currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture.ToString(); Response.Cookies.Add(new HttpCookie("MyApp-culture", currentCulture)); %> <param name="uiculture" value="<%= System.Threading.Thread.CurrentThread.CurrentCulture %>" /> Above lines of code are not able to get the current culture from browser. Please help me to get the current culture set in the browser. I need to set the <parm /> value to crrently selected culture to culture parm in the .aspx page. Do I need to wrirte any code at client end?Anonymous
April 06, 2010
Eric, you can solve the problem with namespaces if you edit client project file and add LogicalName to the EmbeddedResource elements for each linked resource: <LogicalName>MyCompany.Server.Resources.ErrorResources.resources</LogicalName> ... <LogicalName>MyCompany.Server.Resources.ErrorResources.he.resources</LogicalName> toAnonymous
April 06, 2010
Thank you, it started working, we need set the culture as below. <%@ Page Language="C#" AutoEventWireup="true" UICulture="auto" Culture="auto" %> and set the current thread in the param section for SL as below. <param name="uiculture" value="<%= System.Threading.Thread.CurrentThread.CurrentCulture %>" /> Thank you everone once again.Anonymous
April 21, 2010
Will anyone be finishing this series now that Brad is leaving MS? It sure would be helpful as there is a major lack of good documentation of WCF RIA out there. Thanks!Anonymous
May 24, 2010
What about dataannotation validation messages ?, I can't understand how to use resx messages for clientside validation. My genererad entitties code is commented with this // Unable to generate the following attribute(s) due to the following error(s): // // - The validation attribute 'System.ComponentModel.DataAnnotations.StringLengthAttribute' declared ErrorMessageResourceName='DealMetadata_DealStatus_range_fel_1_3' which was not found on declared ErrorMessageResourceType 'RoadrunnerRIAservices.server.Resources.ErrorResources'. // [StringLengthAttribute(3, ErrorMessageResourceName = "DealMetadata_DealStatus_range_fel_1_3", ErrorMessageResourceType = typeof(RoadrunnerRIAservices.server.Resources.ErrorResources), MinimumLength = 1)] // Pls Advice.