views:

533

answers:

2

I'm running into a problem that seems to have no sensible / tractable solution that I am happy with. Silverlight and Internationalisation - a quagmire in the making.

I have a set of resource files that contain translated strings.

In the simple case, I can declare the language resource etc and bind the content / text of a value within the strongly typed resource. Thats fine - plenty of examples of that posted around.

A less simple case is that the strings can have a parameter, so I need to inject a value into the string for the display of it, which in itself can be a data binding.

The more complex scenario is a string with multiple parameters.

You can argue that the VM should provide this ability, but I am unhappy at that since it breaks the divide between the UX Designer and the Developer, requiring the developer to implement a property / method on the VM to support every string the UI requires.

For example : The designer decides after user feedback to add a custom tooltip with more information on it. The tooltip is done declaratively and combines a better explanation with values from the datacontext. The explanation is stored in the resources and the values used come from either an existing data context or an element to element binding.

If I have to run every string through the VM then the addition of something like this requires VM changes. Equally if the source of the parameters will be from other elements, then the VM is not necessarily in the position to provide the formatted string.

How have people got round / approached this issue?

A.

A: 

This question is more complex than I can answer fully, but if you want bindings to consider a specific localization you should set the Language property of your UI Container (maybe your top level UserControl class). After that all bindings should use your requested localization. Check out this article, which concerns WPF but uses techniques that appear to be applicable to Silverlight: http://www.west-wind.com/weblog/posts/796725.aspx

James Cadd
A: 

I don't know exactly what you want to do but you've got several solutions.

  • Create a new string in your VM and make it INotifyPropertyChanged-able

    public string MyTranslatedString 
    { 
       get 
         { 
            return string.Format("{0} Someone", LocalizedResource.Hello;
         }
     };
    

And then listen for localization change events (from your application)

  • Create several text blocks and bind the localized items:

    <TextBlock HorizontalAlignment="Stretch" Foreground="Black" Text="{Binding Path=Resource.CurrentlyLoggedInAs, Source={StaticResource LocalizedStrings }}" VerticalAlignment="Center" Margin="0,0,5,0" />
    <TextBlock HorizontalAlignment="Stretch" Foreground="Black" Text="{Binding Path=Username}" VerticalAlignment="Center" Margin="0,0,5,0" />
    <Button Commands:Click.Command="{Binding Path=LogOutCommand}" Commands:Click.CommandParameter="" Content="{Binding Path=Resource.LogOut, Source={StaticResource LocalizedStrings }}" />
    

You need to add, in your main app:

<Application.Resources>
    <local:LocalizedStrings 
        xmlns:local="clr-namespace:Localization.Silverlight;assembly=Localization.Silverlight"
        x:Key="LocalizedStrings" />
</Application.Resources>

These are the easiest approaches I came up with but I'm quite happy to have something providing me with something simpler.

R4cOON
That solution puts it all back in the VM which is the original problem and what I wish to avoid. Whist a VM should be aware that it is going to be consumed by a view, to have every string from every view consuming the VM coming out of the VM would be unworkable, and any element to element binding that did not come from the VM not being able to be used.e.g. A text block saying "The current Value is {0}" and the placeholder coming from a slider on the view. the VM may have no knowledge of the slider since it is a pure UX piece that is not persisted (let's say the current zoom level.)
Andrew
I tried your solution but I also have a ResourceDictionary into my <Application.Resources> having my default style sheet. Because of that I am getting an error "The type "ResourceDictionary" is inside a ResourceDictionary and does not have a key." Do you know what I could do to fix that problem, because when I put a key I am not able to use the style accross the apps. I am using the steps described on http://msdn.microsoft.com/en-us/library/dd882554(VS.96).aspx
Nordes
Styles have to be included as a dictionary.For me it means the resources section looks like that:<Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Themes/ThemeColours.xaml" /> </ResourceDictionary.MergedDictionaries> <local:LocalizedStrings xmlns:local="clr-namespace:WfW.Localization.Silverlight;assembly=WfW.Localization.Silverlight" x:Key="LocalizedStrings" /> </ResourceDictionary> </Application.Resources>
R4cOON