Best Practices For Silverlight Localization? - silverlight

Does anyone have any best practices or experience of localization in Silverlight. MSDN recommends binding the resource to the XAML, but the result is pretty messy:
<TextBlock Text="{Binding Path=Resource1.HelloText, Source={StaticResource LocalizedStrings }}"/>
A page of that is going to make the XAML unreadable!
Any shortcuts?

I asked a similar but more complex question a while back (silverlight paramterised resource values for internationalisation)
The example given on MSDN is really insufficient for serious localization, it assumes every string is entirely present and has no parameters, the reality is you will have values you wish to embed within the string but need placeholder to mark the location of that variable in the string so a translator can move the marker as they translate.
You can achieve a more advanced mechanism by implementing multi-binding yourself into silverlight - Colin Eberhardt did a nice implementation (silverlight multibindings how to attached mutiple bindings to a single property) - adjusted a bit and combined with a MultiValue Converter you can perform multiple bindings, allowing the first binding to be to the language file, and subsequent bindings to be to the parameters to be embedded.
It's quite a pain but the localization story is just noticably lacking - even chatting at the PDC09 over silverlight 3 / 4 there is really not a great route at present in place - if WPF multibinding makes it across to SL4 that makes it slightly easier, but I havn't seen a good alternative implementation as yet except for people outputting all the strings from the ViewModel - which seems wrong form the 'designers' perspective.

I agree that Microsoft recommendation for Silverlight (and WPF and Windows Phone) localization is very rudimentary. It has several issues. Most important are
It is hard to edit main maintain two separate files: XAML and RESX
Your loose great part of string content when you move it from XAML to RESX
XAML becomes much harder to read and maintain
The reason for this is that Microsoft tools such as Visual Studio, does not provide any way to localize XAML. An easy solition here is the localize XAML and include the localized XAML along with localized RESX into satellite assembly files.
<TextBlock Text="Hello World"/>
is much easier to view, edit and maintain than
<TextBlock Text="{Binding Path=Resource1.HelloText, Source={StaticResource LocalizedString }}"/>
+
<data name="LocalizedString" xml:space="preserve">
<value>Hello World</value>
</data>
What you need to do is to keep hard coding string into XAML and localize the XAML itself. This gets very difficult without a good tool. This is why I recommend you to use a localization tool that can locize XAML. This alone is not enought because if you have localized XAML you still need to compile them into satellite asembly file and finally include the satellite inside your XAP file.
You need to have a tool that can localize RESX and XAML and also compile localized satellite assembly files. There are somes tool that can do that (for example Sisulizer).
If you want to use only Visual Studio then you have to stick with the best practices by Microsoft.

Related

Localizing text in XAML

From the outset of our project we've been storing strings in a resource file 'MyResources.resx', which was done to support the possibility of localizing the software in the future.
We've been using the following syntax for referencing the strings:
<TextBlock Text="{x:Static MyResources.Hello}" />
Is that correct, or should we be using the following:
<TextBlock Text="{Binding Source={x:Static MyResources.Hello}}" />
I've only recently come across the second syntax so I'm a bit concerned that what we've been using wouldn't actually change the text at runtime!
Also, is it okay to have the resx file in the main project, or should it reside in a project of its own? From the little I've seen about the localization process, it seems to involve generating a new DLL - is this a "full build" of the whole project, or does it (somehow) just extract the translated resx file(s) into the DLL?
For static localization, where you do not need to dynamically switch languages at runtime, your first example is the most straightforward solution. x:Static has relatively little overhead. It's nice and lightweight.
The second syntax won't make a difference in your case: the resource properties you are binding to do not raise change notifications, so the UI would not reflect any changes if you change MyResources.Culture at runtime. In either case, only newly created UI elements would reflect the new language.
If you do need to switch languages dynamically, neither of these approaches will suffice. There are some resources out there that can help you, but if you can get by with what you have, it'll make your life a lot easier. There's also a middle ground: you could create a custom MarkupExtension that takes in a text resource ID and provides localized text. Initially, it could simply delve into your resx resources, but you could potentially refactor it into a more dynamic solution later on (if and when you decide you need it).
From the little I've seen about the localization process, it seems to involve generating a new DLL - is this a "full build" of the whole project, or does it (somehow) just extract the translated resx file(s) into the DLL?
I believe what you're referring to is a satellite assembly. As I recall, satellite assemblies contain localized resources for a specific culture, but nothing more. You would bundle them with your main application or library, and the resource infrastructure will select which assembly to probe for resources based on the runtime CultureInfo.

How to provide language support on WPF XAML based UI

I would like to provide language support on a WPF Application. To provide support for dynamic contents, I can make use of a language support file.
However, how should I go about doing this for Static texts, such as those found on XAML.
For example:
<TextBlock
FontSize="20"
FontWeight="Bold"
TextAlignment="Center" FontFamily="Helvetica">
Start Process
</TextBlock>
in the code above, the text "Start Process" is static, but how would I integrate different language support for that text.
Using genercal globalization and localization (language specific support) in WPF apps ... https://msdn.microsoft.com/en-us/library/aa292205(v=vs.71).aspx
Using locale specific resource files in .net .... http://www.c-sharpcorner.com/UploadFile/ankithakur/Globalization_Localization_in_DotNet_CSharp07032006023510AM/Globalization_Localization_in_DotNet_CSharp.aspx
Using x:Static attribute in XAML to achieve binding of resource (.resx) texts ... http://robertoschiabel.wordpress.com/2010/01/31/wpf-add-localization-via-resx-files/
LocBaml is a tool, microsodt has provided explicitly for fast language support for WPF.
This tools adds Uids for every xaml tag and helps you to enlist those tags in CSV files (with some common properties).
These CSV files then can be easily used to provide translations in different languages.
There are certain disadvantages with this approach. Like, you will not get dynamic language switching with this. Sometimes, maintaining CSV files can be cubersome.
Please refer this Link
Well, Angel's advice is on target, especially the last link for using x:Static. There is also a nice really article and code sample that uses this technique here
What I like even better, currently, is a markup extension. A good example of one is here).
Localization is actually a fairly complicated affair even though it seems like you just want to say "Start Process" in Russian! I suggest you stick with the first Code Project article, and only that one, until it makes sense.
Than taking in the second article will be easier.
Last piece of advice I have is to not waste your time with LocBaml.
Cheers,
Berryl

Localizing MVVM based WPF applications

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?
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 pain 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.
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"
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.
If you are almost interested on this topic you can have a look at my library that I'm developing on codeplex.
LocalizationLibrary: http://localizationlibrary.codeplex.com/
Here's a couple of articles that could be of interest:
Localizing WPF Applications using Locbaml
WPF Runtime Localization
Simple WPF Localization

What approaches are available to dummy design-time data in WPF?

I am working without expression blend and just using the XAML editor in vs2010. The wisdom of this aside, I am increasingly seeing a need for design-time data binding. For simple cases, the FallbackValue property works very nicely (Textboxes and TextBlocks, etc). But especially when dealing with ItemsControl and the like, one really needs sample data to be visible in the designer so that you can adjust and tweak controls and data templates without having to run the executable.
I know that ObjectDataProvider allows for binding to a type, and thus can provide design-time data for visualizing, but then there is some juggling to allow for the real, run-time data to bind without wasting resources by loading loading both the design time, dummied data and the runtime bindings.
Really what I am wanting is the ability to have, say, "John", "Paul", "George", and "Ringo" show up in the XAML designer as stylable items in my ItemsControl, but have real data show up when the application runs.
I also know that Blend allows for some fancy attributes that define design time binding data that are effectively ignored by WPF in run-time conditions.
So my questions are:
1. How might I leverage design-time bindings of collections and non-trivial data in the visual studio XAML designer and then swap to runtime bindings smoothly?
2. How have others solved this design-time vs. runtime data problem? In my case, i cannot very easily use the same data for both (as one would be able to with, say, a database query).
3. Are their alternatives to expression blend that i could use for data-integrated XAML design? (I know there are some alternatives, but I specifically want something I can use and see bound sample data, etc?)
Using VS2010 you can use Design-Time attributes (works for both SL and WPF). I usually have a mock data-source anyway so it's just a matter of:
Adding the namespace declaration
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Adding the mock data context to window/control resources
<UserControl.Resources>
<ViewModels:MockXViewModel x:Key="DesignViewModel"/>
</UserControl.Resources>
Setting design-time data context
<Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...
Works well enough.
As an amalgam of Goran's accepted answer and Rene's excellent comment.
Add the namespace declaration.
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Reference your design time data context from code.
<Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...
I use this approach for generating design time data with .NET 4.5 and Visual Studio 2013.
I have just one ViewModel.
The view model has a property IsInDesignMode which tells whether design mode is active or not (see class ViewModelBase).
Then you can set up your design time data (like filling an items control) in the view models constructor.
Besides, I would not load real data in the view models constructor, this may lead to issues at runtime, but setting up data for design time should not be a problem.
public abstract class ViewModelBase
{
public bool IsInDesignMode
{
get
{
return DesignerProperties.GetIsInDesignMode(new DependencyObject());
}
}
}
public class ExampleViewModel : ViewModelBase
{
public ExampleViewModel()
{
if (IsInDesignMode == true)
{
LoadDesignTimeData();
}
}
private void LoadDesignTimeData()
{
// Load design time data here
}
}
Karl Shifflett describes an approach that ought to work equally well for VS2008 and VS2010:
Viewing Design Time Data in Visual Studio 2008 Cider Designer in WPF and Silverlight Projects
Laurent Bugnion has a similar approach that focuses on Expression Blend. It might work for VS2010, but I haven't confirmed this yet.
Simulating data in design mode in Microsoft Expression Blend
Maybe the new design-time features of Visual Studio 2010 and Expression Blend 4 are an option for you.
How it works is shown in the BookLibrary sample application of the WPF Application Framework (WAF). Please download the .NET4 version.
Similar to the top rated answer, but better in my opinion: You can create a static property to return an instance of design data and reference it directly from XAML like so:
<d:UserControl.DataContext>
<Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>
This avoids the need to use UserControl.Resources. Your static property can function as a factory allowing you to construct non-trivial data types - for example if you do not have a default ctor, you can call a factory or container here to inject in appropriate dependencies.
Using Visual Studio 2017 I have been trying to follow all of the guides and questions such as this and I was still facing a <ItemsControl> which simply did not execute the code I had inside the constructor of a DesignFooViewModel which inherits from FooViewModel. I confirmed the "did not execute" part following this "handy" MSDN guide (spoiler: MessageBox debugging). While this is not directly related to the original question, I hope it will save others a lot of time.
Turns out I was doing nothing wrong. The issue was that my application needs to be built for x64. As the Visual Studio is still in 2018 a 32-bit process and apparently cannot spin a 64-bit host process for the designer part it cannot use my x64 classes. The really bad thing is that there are no errors to be found in any log I could think of.
So if you stumble upon this question because you are seeing bogus data in with your design time view model (for example: <TextBlock Text="{Binding Name}"/> shows up Name no matter you set the property to) the cause is likely to be your x64 build. If you are unable to change your build configuration to anycpu or x86 because of dependencies, consider creating a new project which is fully anycpu and does not have the dependencies (or any dependencies). So you end up splitting most or all but the initialization parts of the code away from your "WPF App" project into a "C# class library" project.
For the codebase I am working on I think this will force healthy separation of concerns at the cost of some code duplication which is probably net positive thing.
I liked jbe's suggestion, specifically to look at how they do it in the WAF framework sample apps - they use separate mock/sample view models in a DesignData folder and then have a line like this in the XAML:
mc:Ignorable="d"
d:DataContext="{d:DesignInstance dd:MockHomeViewModel, IsDesignTimeCreatable=True}"
(where dd points to the .DesignData namespace where MockHomeViewModel lives)
It's nice and simple (which I like!) and you can inherit from the real VMs and just provide dummy data. It keeps things separate as you don't need to pollute your real VMs with any design time only code. I appreciate things might look quite different for a large project utilising IOCs etc but for small projects it works well.
But as joonas pointed out, it seems not to work with x64 builds in VS2017 and this still seems to be the case with VS2019 (I'm using V2019 16.6 Community edition). It's not fiddly to get working to start off with but can cause some head scratching when after making a change (or as is usually the case, several changes!) it suddenly stops working.
For anybody trying it, I would recommend creating a new simple WPF project (say one view, one view model, one mock vm) and play around with it; get it working and then break it. I found sometimes, no amount of solution cleans and rebuilds would fix it, the only thing that worked was closing VS down and restarting, and suddenly my design time data came back!

How do you manage huge and barely maintainable XAML files?

I'm having real difficulties with XAML files in Silverlight since they get very big very fast when using Blend. It just becomes a wall of text after only a handful of controls are added and animated.
I'm hoping a better vesion of Blend will come out soon, so that our designers will never even have to see XAML. For now, though, that is not a solution - XAML still needs to be managed manually and it is a depressing task.
Has anyone found a solution to this? How do you keep your XAML files in order? How do you understand them when they get big?
Edit: I am especially interested in Silverlight solutions, since the most obvious WPF solution - splitting things up into resource dictionaries - is not supported in Silverlight.
It does require a little bit of work to maintain XAML files, but basically, what you need to do is split them up in resource files (XAML Resource Dictionaries) using a scheme that makes sense to you.
For example we use a scheme where we have a folder structure like this:
Resources (contains XAML Files that represent the user controls and pages)
Stencils (XAML files with Shapes)
Styles ( XAML Files with styles)
Brushes ( ... )
Shared
Templates ( ... )
Your structure might vary but, separating all resources in different files really makes maintenance more easy in the long run.
I have been using Silverlight 2 since January when it was in private release, and we ran into this problem, all our XAML was in one big file. What we did as best practices was to break up the user interface into separate user controls based on visual categorization (header, footer, navigation controls etc..) Originally we tried to use nested canvases (grids had not been added to the framework yet) and this turned into a maintenance nightmare later.
In Blend you can actually select a Canvas/grid etc... from the Objects and Timeline window, right click on it, and you are given the option "Make Control.." This made for speedy re factoring and modularizing our main XAML file. We then used Events to allow the user controls to communicate between each other.
Hope this helps, and good luck!
I'm a Creative Developer and work in Blend extensively.
I published a few thoughts last year on keeping XAML clean.
Silverlight currently does not support MergedResourceDictionaries so it's hard to break out the XAML into separate ResourceDictionary files as I suggested in another post.
Paul Stovell also has some interesting guidelines for XAML.

Resources