What would be a good aproach to localize a MVVM based WPF allication that can change its language at runtime? Of course I could create a string property in the ViewModel for each and every string that is displayed somewhere in the View but that seems rather tedious to me. Is there a common approach/best practice for this?
WPF has a lot of support for localization. Perhaps you can leverage that? Unfortunately I think that changing the user interface language at run-time is somewhat difficult and you probably need to come up with your own scheme.
Also, as the view-model is UI agnostic I don't think storing user interface strings in the view-model is a good solution. These belong to the view.
Instead of having user interface strings in your view model, you can store them in the assembly's resources and access them directly from XAML, using x:Static
:
<TextBlock Text="{x:Static props:Resources.MyLabel}"/>
The props
namespace should refer to your assembly's Properties
namespace:
xmlns:props="clr-namespace:My.Assembly.Properties"
Here's a couple of articles that could be of interest:
Here's an excellent article about WPF localization. It deals with the Microsoft-supported localization technique, and a few alternative ones
I wouldn't recommend the "official" solution for localization... it's really a PITA to use, it modifies you XAML (adds x:Uid attributes to every element that can be localized), and there are no good tools from MS to make it an easy solution. Good old resx localization is much easier to use, and integrates quite well with WPF with just a few tricks (namely, markup extensions and/or attached properties). Also, you can easily change the interface language at runtime thanks to the binding system.
You can use a Custom Markup Extension to lookup localized values and update them when the UI Culture changes.
Here's an example of how this might work:
<Label x:Name="lblResxHelloWorldMarkupExtension1Value"
Content="{res:Res Id=HelloWorld,Default=Hello#}"
Margin="{res:Res Id=HelloWorldMargin,Default=10}"
Width="{res:Res Id=HelloWorldWidth,
ResourceSet=WpfClickOnce.MyFormRes, Default=50}" />
This example is taken from the excellent WPF Localization Guidance authored by Rick Strahl and Michele Leroux Bustamante here: http://wpflocalization.codeplex.com/. Download the guide from this site where this technique is described in detail in document form and with a sample application.
Another nice advantage of this approach is that it works in the designer.