Trying to make my wpf appliaction localized, I followed this CodeProject tutorial.
I created my localized resource files (e.g., Resource.resx, Resource.en-US.resx) and bind these on a label element in the xaml
<Label Foreground="{StaticResource ApplicationForgroundColor}" FontSize="21"
Content="{x:Static strings:Resources.title}"/>
In a LocalizedService I set the CultureInfo
on some change events
class LocalizationService
{
public static void SetLanguage(string locale)
{
if (string.IsNullOrEmpty(locale)) locale = "en-US";
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(locale);
}
}
This solution compiles and shows the correct resource value, but because of the static binding, I could not change the locale on runtime.
When I change the content binding to a DynamicResource
as follow shown there is no resource value shown.
Content="{DynamicResource strings:Resources.title}"
How could I bind text values to a localized resource file and change it dynamically on runtime?
There is an other approach of Code Infinity here which also used a wrapper for dynamically binding on resource files.
Here the INotifyPropertyChanged
event informs your ui elements of a new binded resource file when the locale was changed.
You start to implement a BindingExtenstion:
public class LocalizationExtension : Binding
{
public LocalizationExtension(string name) : base("[" + name + "]")
{
this.Mode = BindingMode.OneWay;
this.Source = TranslationSource.Instance;
}
}
Then you need to implement the connection between a ResourceManager
and the CultureInfo
which is implemented as a singleton to enable synchronized access. It defines the Source for the binded element and also fires the INotifyPropertyChanged` event on localization changes:
public class TranslationSource : INotifyPropertyChanged
{
private static readonly TranslationSource instance = new TranslationSource();
public static TranslationSource Instance
{
get { return instance; }
}
private readonly ResourceManager resManager = Resources.Strings.Resources.ResourceManager;
private CultureInfo currentCulture = null;
public string this[string key]
{
get { return this.resManager.GetString(key, this.currentCulture); }
}
public CultureInfo CurrentCulture
{
get { return this.currentCulture; }
set
{
if (this.currentCulture != value)
{
this.currentCulture = value;
var @event = this.PropertyChanged;
if (@event != null)
{
@event.Invoke(this, new PropertyChangedEventArgs(string.Empty));
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Note that your localized resource files (e.g., Resource.resx, Resource.en-US.resx) are in the folder <Project>/Resources/Strings/Resources/
otherwise you need to update this part of the code.
Now you can use this new binding:
<Label Foreground="{StaticResource ApplicationForgroundColor}" FontSize="21"
Content="{util:Localization title}"/>
To change the locale in runtime you need to set:
public static void SetLanguage(string locale)
{
if (string.IsNullOrEmpty(locale)) locale = "en-US";
TranslationSource.Instance.CurrentCulture = new System.Globalization.CultureInfo(locale);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With