A simple and effective way to localize application resources is to write a custom MarkupExtension that provides a localized value. The extension takes a parameter in the constructor that is the unique resource key. When the DepdendencyProperty asks for the value. The markup extension looks up the value from the resource dictionary of your choice. This gives you the flexibility to use what you like as resource storage.
The usage of the markup extension is very simple. Just replace the string you want to localize by {l:Translate resourceKey}.
[MarkupExtensionReturnType(typeof(string))]
public class TranslateExtension : MarkupExtension
{
private string key;
private DependencyObject targetObject;
private DependencyProperty targetProperty;
public TranslateExtension(string key)
{
this.key = key;
Translator.CultureChanged += new EventHandler(Translator_CultureChanged);
}
void Translator_CultureChanged(object sender, EventArgs e)
{
if (targetObject != null && targetProperty != null)
{
targetObject.SetValue(targetProperty,
Resources.ResourceManager.GetObject(key));
}
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var targetHelper = (IProvideValueTarget)serviceProvider.
GetService(typeof(IProvideValueTarget));
targetObject = targetHelper.TargetObject as DependencyObject;
targetProperty = targetHelper.TargetProperty as DependencyProperty;
return Resources.ResourceManager.GetObject(key);
}
}
public static class Translator
{
internal static event EventHandler CultureChanged;
public static CultureInfo Culture
{
get
{
return Thread.CurrentThread.CurrentUICulture;
}
set
{
Thread.CurrentThread.CurrentUICulture = value;
if (CultureChanged != null)
{
CultureChanged(null, EventArgs.Empty);
}
}
}
}
Since there is no possibility to get notified, when the language of a thread changes, I created a static class called "Translator". Instead of switching the language directly on the Thread, I do it on the Translator. All TranslationExtensions register themself to the CultureChanged event of the Translator and re-set the localized value in the new language when the culture changes. That's all the trick.
 |
| Patrick | |
|
| Commented on 9.January 2009 |
Hi! I just compiled this on C# 2008, and altough the extensions works great at runtime, I\\\'m unable to see the XAML design window (The type \\\'Translate\\\' was not found.)
Did I do something wrong? Or is the a site affects, because the designer hasn\\\'t prepared for XAML extensions yet?
Thanks in advance.
|
|
|
 |
| Christian Moser | |
|
| Commented on 20.January 2009 |
Hi Patrick, did you add the XmlnsDefinition attribute to the assembly that contains the Translation class? Otherwhise you need to include the namespace and use the prefix.
I think another problem could be if the extension and the xaml file you use it is in the same assembly, then you have to use a clr-namespace and a prefix. I hope this helps.
Greetings
Christian
|
|
|
 |
| Sevenate | |
|
| Commented on 28.February 2009 |
| Excellent solution! Thank you, Christian.
|
|
|
 |
| Andres Olivares | |
|
| Commented on 6.March 2009 |
Hello Christian,
I have similar implementation for a localization implementation I was working on. I was wondering if you ran into the same issue I experienced. If the Translator_CultureChanged handler is raised and it is executed for a localization set on the setter of a style for an element, the execution of
targetObject.SetValue(targetProperty, Resources.ResourceManager.GetObject(key));
would fail because your targetObject never registered as a DependencyObject. Try this if you have enncountered this yet.
|
|
|
 |
| Hi Christian | |
|
| Commented on 20.March 2009 |
Would it be possible for you to post a download of the above VS2008 WPF Project please? I tried out what you have explained, but I seem to be going wrong somewhere, and I would be obliged if you could provid the Project, so that I can compare my files and see where I have gone wrong.
Thanks in advance,
Manoj Kumar Sharma
|
|
|
 |
| vvidov | |
|
| Commented on 23.March 2009 |
Hi
how I can use it with Microsoft.Windows.Controls.Ribbon
10x
vvidov
|
|
|
 |
| vvidov | |
|
| Commented on 24.March 2009 |
Hi
how I can use it with Microsoft.Windows.Controls.Ribbon
10x
vvidov
|
|
|
 |
| Christian Moser | |
|
| Commented on 15.April 2009 |
| Hi, I uploaded a sample solution that contains an updated version of the markup extension.
|
|
|
 |
| Simon | |
|
| Commented on 12.May 2009 |
| How would you make this work for a ContextMenu?
|
|
|
 |
| Christian Moser | |
|
| Commented on 12.May 2009 |
Hi Simon,
you can use it in any WPF elements - also for ContextMenus. Just get the Header of a MenuItem from the TranslateExtension.
|
|
|
 |
| John | |
|
| Commented on 12.May 2009 |
| I cannot download your sample project. Using IE7.
|
|
|
 |
| Simon | |
|
| Commented on 14.May 2009 |
| The problem with e.g. context menu is that datacontext is not flowed or something like that, and thus I have been unable to get it to work.
|
|
|
 |
| Greg | |
|
| Commented on 14.May 2009 |
Exactly what I was looking for. End to locbaml woes.
The sample seems to be wired directly into Localize. Not what you have in the article above, making it much more developer friendly.
Great job, Christian. Thanks
|
|
|
 |
| Boris | |
|
| Commented on 20.May 2009 |
| Correct me if I'm wrong but this will give you a nice memeory leak...
|
|
|
 |
| Christian Moser | |
|
| Commented on 20.May 2009 |
Hi Boris,
you are right. You talk about the event registration in the markup extension? I have to find a solution for this. Probably a weak event can solve the issue.
|
|
|
 |
| Chris Sullivan | |
|
| Commented on 27.July 2009 |
| Good solution, one of the better one's I've seen mainly for it's simplicity. Also like the fact the "resource" is held as a seperate project which makes it a more realistic solution. Thanks for taking the time and effort to create the solution and share with others.
|
|
|
 |
| SeriousM | |
|
| Commented on 17.August 2009 |
Hello!
This is a nice approach that i have developed some months ago (4. May 08).
Have a look at this please: http://wpflocalizeextension.codeplex.com
|
|
|
 |
| Stephen | |
|
| Commented on 14.September 2009 |
| Hi Christian, I have a question. I have downloaded the example app. When I ran it the Hebrew text was squares, but when viewing the resx I see the Hebrew text. This seed strange. Cah you clue me in on what might be going on here? Thanks. Nice site by the way. Thanks for that as well.
|
|
|
 |
| Alex | |
|
| Commented on 16.September 2009 |
| Is it only me or doing the simplest thing with wpf suposses to turn the down the whole world !? Those things were simpler before !!
|
|
|
 |
| Vytas | |
|
| Commented on 21.October 2009 |
What is "Localize" in 'Title="{Localize ...'
That's the only thing I can not understand and I can't apply this example to my application. Besides, the article is Totaly different from the example, but I think you know that...
|
|
|
 |
| Raul | |
|
| Commented on 13.November 2009 |
Hi Christian,
I downloaded your project and it works fine, but when i added another culture SupportedCultures it doesn't work. I have also made the respective resource files in 'LocalizationResources'. Any idea what I might be doing wrong?
|
|
|
 |
| MGA | |
|
| Commented on 23.November 2009 |
| This is the best sample for localization! Thanks so much!
|
|
|
 |
| Spock | |
|
| Commented on 24.November 2009 |
I cannot figure out how the localize markup extension is being called by
What is "Localize" in 'Title="{Localize ...'
It works in the example, but not being able to call the extension in my app is frustrating. Can Christian or someone else clarify, please? Gred, how is the sample wired into Localize? Thanks and live long and prosper
|
|
|
 |
| Prabu P | |
|
| Commented on 14.December 2009 |
Hello Christian
Excellent solution for WPF localization using Resources. Keep posting such nice articles and happy coding :)
|
|
|
 |
| Prabu P | |
|
| Commented on 14.December 2009 |
Hi Spock,
"What is "Localize" in 'Title="{Localize ...' "
"Localize" represents "LocalizeExtension" class name. You may or maynot use "Extension" keyword in Markup representation.
|
|
|