You can use this class to bring dynamic multilingual features to your applications
NOTE
Dynamic Language Located in the HandyControl.Tools namespace.
Using HandyControl.Tools;Features
- Design Time Preview
- Binding Support
- Dynamic language change in runtime
- Supports multiple resource files
Create resource files
First you need to create a folder, here our folder called Assets We are going to create language files in this folder. add resource files into this folder you can Right-click on folder and from the Add New Item option Select Resources file Be careful when naming it.
NOTE
The default language can be without a language code
No matter how many languages you have, you need to create a resource file for that language.
You must include a 2-digit or 5-digit language code in resource file name.
We want our program to have 2 languages, English and Persian So I create 2 resource files Pay attention to the naming method.
Strings.resxStrings.en.resxorStrings.en-US.resx
NOTE
You can change Strings to anything else
Set up the provider
We need to know where your resource files are, so you need to set up your provider
<Window x:Class="WpfAppTest.MainWindow"
xmlns:hc="https://handyorg.github.io/handycontrol"
hc:LocalizationManager.Provider="WpfAppTest;Assets.Strings">NOTE
- Note that you must first write the name of your project (In this case it is
WpfAppTest). - Then you have to separate the project name from the file location with an
;. - Finally, you must write the folder name and file name after
;(In this case, our Resource name isStrings, which is located in theAssetsfolder). - we seperate folder and file with dot
..
WARNING
if any UIElement that has a provider, we will use that provider.
<TextBlock hc:LocalizationManager.Provider="WpfAppTest;Assets.Strings" Text="{hc:Localiation TextKey}"/>If there is no provider, we find the parents of that control and check each provider in order, If a provider is found, we use it for localization.
<Grid hc:LocalizationManager.Provider="WpfAppTest;Assets.AnotherStrings">
<StackPanel hc:LocalizationManager.Provider="WpfAppTest;Assets.Strings">
<TextBlock Text="{hc:Localiation TextKey}"/>
</StackPanel>
</Grid>Note that as soon as the provider is found, we will not check on the other parents, In the example above, first Provider will be used and second (Grid) will no longer be checked.
If provider is still not found, We use the control host provider (UserControl/Window...).
<UserControl hc:LocalizationManager.Provider="WpfAppTest;Assets.AnotherStrings">
<StackPanel>
<TextBlock Text="{hc:Localiation TextKey}"/>
</StackPanel>
</Grid>If no provider is found again, we use the Application.Current.MainWindow Provider.
Design-Time Preview
After specifying the provider and specifying the keys, you can see the preview of the keys in DesignTime.
if you need to change culture in DesignTime you can use DesignCulture AttachedProperty:
<Window x:Class="WpfAppTest.MainWindow"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
hc:LocalizationManager.DesignCulture="fa">This gives you the possibility to check the correct localization directly in the WPF designer.
NOTE
- If you do not see the preview, try to Refresh VS Designer or Rebuild the project.
- Design mode is not available in Binding mode.
Xaml Localization
There are several ways to do this
Key Localization
<Button Content="{hc:Localization TextKey}"/>
<!-- OR -->
<Button Content="{hc:Localization Key=TextKey}"/>WARNING
TextKey is the key you created in the resource (resx) file
Binding Localization
<TextBlock Text="{hc:Localization KeyBinding={Binding SomeProperty}}"/>Argument Binding Localization
First Create two Key in Resx file.
Name: SomeKey Value: Hello {0}, {1}
Name: SomeKey2 Value: HandyControl
Then create a string Property
private string _SomeProperty = "Bye!";
public string SomeProperty
{
get { return _SomeProperty; }
set { _SomeProperty = value;}
}Now
<TextBlock>
<TextBlock.Text>
<hc:Localization Key="SomeKey">
<Binding Source="{hc:Localization SomeKey2}"/>
<Binding Path="SomeProperty" />
</hc:Localization>
</TextBlock.Text>
</TextBlock>
OR
Create a Key in Resx file.
Name: SomeKey Value: Hello {0}
Then create a string Property
private string _SomeProperty = "HandyControl";
public string SomeProperty
{
get { return _SomeProperty; }
set { _SomeProperty = value;}
}Now
<TextBlock>
<TextBlock.Text>
<hc:Localization Key="SomeKey">
<Binding Path="SomeProperty" />
</hc:Localization>
</TextBlock.Text>
</TextBlock>
Static Arguments Localization
First Create a SomeKey Key with Alphabet {0}, {1}, {2} value in Resx file.
Name: SomeKey Value: Alphabet {0}, {1}, {2}
Then Create an array in Xaml
<x:Array x:Key="SomeArray" Type="system:String" xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String>A</system:String>
<system:String>B</system:String>
<system:String>C</system:String>
</x:Array>Now we can use our array in our localization
<TextBlock>
<TextBlock.Text>
<hc:Localization Key="SomeKey" Arguments="{StaticResource SomeArray}" />
</TextBlock.Text>
</TextBlock>
Localize in Code-Behind
It is very easy to use in Code-Behind
Localize
Return localized value as object. for example When you have saved the FlowDirection value in the resource, you can use this method to get value as an object and cast it to FlowDirection.
var msg = LocalizationManager.Localize("Key");
// OR
var msg2 = LocalizationManager.Localize("Key", new CultureInfo("en"));
// OR
ILocalizationProvider provider = new ResxLocalizationProvider("WpfAppTest.Assets.Strings", Assembly.Load("WpfAppTest"));
var msg3 = LocalizationManager.Localize(provider, "Key", new CultureInfo("en"));LocalizeString
Return localized value as String.
string msg = LocalizationManager.LocalizeString("Key");
// OR
string msg2 = LocalizationManager.LocalizeString("Key", new CultureInfo("en"));
// OR
ILocalizationProvider provider = new ResxLocalizationProvider("WpfAppTest.Assets.Strings", Assembly.Load("WpfAppTest"));
string msg3 = LocalizationManager.LocalizeString(provider, "Key", new CultureInfo("en"));Change language in Runtime
To change the language in runtime, just write the following code and specify the language code
ConfigHelper.Instance.SetLang("fa");CultureChanged Event
This event is called whenever the culture changes So you can get the details of the culture:
LocalizationManager.Instance.CultureChanged += OnCultureChanged;
private void OnCultureChanged(object sender, FunctionEventArgs<CultureInfo> e)
{
var info = e.Info.Name;
}Available Culture
You can use this method to get the list of languages of each resource, GetAvailableCultures return Dictionary<string, IEnumerable<CultureInfo>>
foreach (var item in LocalizationManager.GetAvailableCultures())
{
foreach (var lang in item.Value)
{
Debug.WriteLine(lang.Name);
}
}AvailableResxProvider and AvailableResourceManager
if you need Providers or ResourceManagers, you can use these 2 dictionaries.
AvailableResxProviderHolds all your application providers.AvailableResourceManagerHolds all your application ResourceManager.