Change system language for one/active window in WPF - c#

Is there a posibility to change system language only for one window in WPF?
I know about InputLanguageManager but I assume that it changes language in whole system.

InputLanguageManager does exactly what you are asking for. It changes the keyboard layout for the current application.
The keyboard layout is kept by the OS for each running application. Eg. if you open Notepad and switch to Russian, the open IE and switch to English, when you activate the Notepad application, your keyboard locale will still be Russian.
The following line changes the keyboard locale just for the current application:
InputLanguageManager.Current.CurrentInputLanguage = new CultureInfo("el-GR");
The system language (or rather, the system locale) and the keyboard layout are completely different concepts. The keyboard layout is the layout of your keyboard.
There are three different locales used in a .NET application:
The UI locale is the locale used to display messages and select localized UI strings and layouts. You can change a thread's UI locale by setting its Thread.CurrentUICulture property. Its initial value is governed by the OS's display language in regional settings
The thread's locale is used to parse strings and convert dates and numerics to string. You can change it by setting the Thread.CurrentCulture property. Its original value is governed by the OS's regional settings Format property
The system locale is used by non-Unicode applications or when writing to ASCII files and the console.
You can also take advantage of WPF data binding and use InputLanguage as an attached property. In your XAML you can add the InputLanguageManager.InputLanguage property to an element's declaration like this:
<TextBox InputLanguageManager.InputLanguage="en-US"></TextBox>
You can then bind the property to a property in your code-behind or you ViewModel. Eg.
<TextBox InputLanguageManager.InputLanguage="{Binding MyLanguageInfo}"></TextBox>
Setting this property to a specific value will cause the keyboard of the UI element to change:
MyLanguageInfo = new CultureInfo("en-US");
or
MyLanguageInfo = new CultureInfo("el-GR");
You can go further with this and bind the InputLanguage property other elements, eg. a listbox of language options

For Keyboard Layout Changing are you InputLanguageManager on the right way.
InputLanguageManager.SetInputLanguage(this,CultureInfo.CreateSpecificCulture("ru"));
With the first Parameter of the SetInputLanguage() methode you set the DependencyObject which is the target of your Keyboard Layout.

Related

Can I have my form update, in designer, with strings from my resource files?

I'm getting into globalization and localization. I'm aware that I can set the localizable property of my form to true and that I'm able to edit the form for that specific culture. That's great. My question is am I able to, at the designer, load my resx values into their assigned winforms? My goal is to edit the size of my winform assets around the translated languages. This is, obviously, easier if I can see the translations in the designer. Attached is the code that change the text of my buttons at runtime, but my goal is have this take place during the design phase.
buttonTelescopeUp.Text = Resource.TeleUp;
buttonTelescopeDown.Text = Resource.TeleDown;
buttonTelescopeLeft.Text = Resource.TeleLeft;
buttonTelescopeRight.Text = Resource.TeleRight;
Form at runtime
Formin design

Understanding what property changes does Localization = True track in resx files

I have a problem of understanding with localization, hope you can help.
I create a winform app:
add a button
set the form Localizable property to True
set the form Language to Spanish
change the button's Text to "Vamos" and BackColor to "Green".
set the form Language to English
change the button's Text to "Go" and BackColor to "Yellow".
When I swap between Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("es"); and Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en"); the button Text DOES change from "Vamos" to “Go” but the BackColor is always set to “Yellow”.
My deduction is that Localizable = True tracks [control].Text property changes, and other changes such as [control].Location and [control].Size, but it does NOT track [control].BackColor or many other control property changes in the respective resx files.
Is this a bug? Is there a reference document to understand what IS and ISN'T being tracked? I can understand that BackColor is not something that is typically related to a language change but on that basis, size and location shouldn’t be either...so I am not clear on the rationale applied here...
Because of this limitation I am having to make certain localization changes via resx files and others manually via my on logic, feels a bit messy.
Thanks for your help.
[tested in VS 2012 and 2017 with equal behaviour]
A property is considered as localizable if it's decorated with Localizable(true) attribute. For example BackColor property is not localizable, but Text property is localizable.
When the designer generates code for your form, when you have enabled localization for the form, properties which are decorated with the Localizable(true) will be serialized to the resource file of the form. For the rest of the properties, their values will be serialized in code.
For more information and links to how to create multi-language windows forma application, take a look at:
How to make multi language app in winforms

How to know when user changed date, time or number formats in Clock and Region system settings in C#?

I need to subscribe to an hypothetical event that should be triggered whenever the user changes date, time, or number formats in Clock and Region settings. Below is the picture of how this settings window look in Windows 10 (I suppose that in older Win versions is pretty much the same stuff):
I have to achieve this in order to call ClearCachedData method on my CurrentCulture.
What I have tried is to subscribe to UserPreferenceChanged event following the solution in this question. Nevertheless the event never fires...
I am using WPF although I believe this should not be relevant, although I mention it in case it is...
Further details
My application has a data grid with numeric value editors (I am using Devexpress's controls although this is may be not relevant), so, suppose I have this cell holding a value of 1.5, this will be like so due to the fact that I have set my numeric formats to an English (US) culture. Now, I go to these settings (while having my app running), and change my numeric formats to German(Germany). Then I want to update the displayed value to 1,5. This feature is already supported on Devexpress's controls and WPF in general, I just need to call ClearCachedData and update my layout.
An already existing application that I know for sure does this is Excel (I am sure there must be a lot more), try yourself to set a float value (1.5 e.g.), and with the window opened go to change your numeric formats with a Germany region: the cell updates its displayed value to 1,6.

WPF Design Time Application Culture

We are developing a localized English/Arabic application, and I need to set the System.Threading.Thread.CurrentThread.CurrentUiCulture to either of both cultures during design time to a different value than the value set at run time.
How can I accomplish this?
Thanks in advance.
Set the xml:lang attribute.
This attribute describes the culture of a specific element and its child elements. The value of this property changes the behavior of several features in WPF. For example, it changes the behavior of hyphenation, spell checking, number substitution, complex script shaping, and font fallback. See Globalization for WPF for more information about setting the xml:lang Handling in XAML.
http://msdn.microsoft.com/en-us/library/ms788718.aspx
Check this out http://geekswithblogs.net/lbugnion/archive/2009/09/05/detecting-design-time-mode-in-wpf-and-silverlight.aspx, you can then set the Language accordingly with something like
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name)));
The WPF Localization Extension allows you to set design time language (and it has other features, like allowing you to change languages at runtime through WPF with no code-behind etc.).
Check it out here: http://wpflocalizeextension.codeplex.com/

Some questions about multi language

Recently, I decided to add 4 languages to my application.
I read about how to do it and I succeed.
But there are two problems/questions I would like to ask.
First question: Is there a better way to change the text of each control instead
private System.Resources.ResourceManager rm;
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("fr");
rm = new System.Resources.ResourceManager(typeof(MainForm));
and then for each control to write this line:
aboutToolStripMenuItem.Text = rm.GetString("aboutToolStripMenuItem.Text");
addTaskToolStripMenuItem.Text = rm.GetString("addTaskToolStripMenuItem.Text");
addTaskToolStripMenuItem1.Text = rm.GetString("addTaskToolStripMenuItem1.Text");
...
Second Question: lets say the text of label1 is "test" and in other language its "testest" then the size of the label will change, which is ok. but If I got label2 that his location is near label1, label1 might be on the top of label2. How can I move the label1 compare with label2 so no matter how long the text in label1 will be, label2's location will be relative to label1. I dont want to use calculations in the program, I want to know if there's other way like property in one of the controls.
EDIT:
after long thinking, I decided to use XML for my multilanguage. this way I can let the people translate it and upload it for me plus I can use it on runtime instead or reload the programs.
About the relative pos of controls I will use FlowLayoutPanel or TableLayoutPanel I will check further which is better.
Satellite assemblies is what you are looking for.
Q1: In VS, set your form's Localizable property to true. Then select the language property accordingly and type your translations in the designer. That way, you simply need to set the thread culture at start-up and .NET will load the correct language for you. No need to add extra code.
Q2: Again, after you selected the language in the designer, just move the controls around: Their new location/size is part of the translation and will be handled automatically by .NET.
It's not a very good idea change the GUI to a different culture while it's running, it's better to say something like you need to restart the application to see changes.
Although if you need to do it, you need to reload all the resources from the new culture (more or less the same than the InitializeComponen does), not only the text, because the location, size and so on, may be changed too. Also you need to change the thread culture in order to the errors, message and the new controls have the correct culture too (to show them in the correct language too).
You can set your application culture with:
CultureInfo appCulture = CultureInfo.CreateSpecificCulture("fr");
Thread.CurrentThread.CurrentCulture = appCulture;
Thread.CurrentThread.CurrentUICulture = appCulture;
You need an specific culture to use it on formating and parsing.
In answer to your first question:
If you really want to follow that scheme maybe using Reflection or automatic code generation is an alternative for easier management. I usually write my own GetString method that takes a default english string as an argument (used if no resource can be loaded dynamically for the current language). But I am not sure if it is the best solution either...
In answer to your second question:
In Winforms use a TableLayoutPanel or FlowLayoutPanel or another layout component to relatively position the controls. It is possible to specify if the Label fits to its content (AutoSize) for example or if it shall Dock and if yes with what Alignment. There is nearly no use case that would require a tedious self management or computation.
Link: http://msdn.microsoft.com/en-us/library/z9w7ek2f(v=VS.100).aspx

Categories

Resources