I have a DropDown Menu "DDLanguage" where the user choses the Language for the application, and this ovveride methode thats sets the according Culture. So far so good.
protected override void InitializeCulture()
{
String language = Request.Form["DDLanguage"];
if (!string.IsNullOrEmpty(language))
{
if (language == "auto")
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(HttpContext.Current.Request.UserLanguages[0].Trim());
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(HttpContext.Current.Request.UserLanguages[0].Trim());
}
else
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
}
}
}
I then introduced a Querystring Parameter to pass the selected Language to the page on one of the required reload events. This causes some conflict between the language being given by the query string on one side and the dropdown on the other. I want the Querystring to be mandatory only for the first pageload, but afterwards it should not be considered anymore, as it is then overruled by the choice of the DropDown Menu.
The code I wrote to handle this was:
String language = Request.Form["DDLanguage"];
String languageChanged = Request.Form["LabelLanguage"];
if (!string.IsNullOrEmpty(Request.QueryString["Lang"]) && string.IsNullOrEmpty(languageChanged))
{
language = Request.QueryString["Lang"];
}
where LabelLanguage stores the selection of the DropDown Menu and is empty until a first choice is made.
Unfortunately that doesn't work and the culture is only set by the query Parameter. Any suggestion is appeciated. Thanks, Martin
The logic that I applied was correct, but
String languageChanged = Request.Form["LabelLanguage"];
would not return a value. I now know that I can't process data of a Label, as it is not rendered to a html element containing a value. Instead I use a asp:HiddenField that is rendered in a way its value can be requested by that command.
Related
I have a DropDown (using MahApps if that is important) that I'd like to use to switch the language "on the fly" in my program.
Language Class
namespace SAM
{
public class Language
{
public string Title { get; set; }
public string Culture { get; set; }
}
}
Change Language
private void DropLanguage_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
Language lang = DropLanguage.SelectedItem as Language;
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang.Culture);
}
I have all my strings as resources in Resources.resx (default) and Resources.en.resx (english)
3 issues I don't understand
When selecting "englisch" from the dropdown, the language does not change immediately but when I click sth. else, e.g. "close" (it asks "sure?"), the language has changed.
Strings that are directly in the .xaml file like <TextBlock Text="{x:Static p:Resources.Config_HeaderBar_Find_Speaker}" /> do not get updated at all.
Bonus: How would I switch back to the default language, as new CultureInfo(lang.Culture); expects one parameter and for the default I have Culture = null (as the Resources.resx has nothing in it's name). Changing the file to Resources.default.resx messes with my code a lot...
I tried to solve similar problem. The simplest solution for me was to move all Window content to UserControl and creating interface for window with method refreshLanguage(). Then I call from model:
private void SetLanguage(string cultureName)
{
var cul = new System.Globalization.CultureInfo(cultureName);
Properties.Resources.Culture = cul;
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = cul;
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = cul;
System.Threading.Thread.CurrentThread.CurrentUICulture = cul;
System.Threading.Thread.CurrentThread.CurrentCulture = cul;
InitializeHamburgerMenu();
MainWindowView.RegreshLanguage();
RaisePropertyChanged("Title");
}
And RefreshLanguage in Window looks like:
public void RegreshLanguage()
{
GlobalUserControl content = new GlobalUserControl("Views/SettingsPage.xaml");
ContentPresenter_GlobalUserControl.Content = content;
}
In my case, UserControl provides navigation, so I passed last navigated URI as parameter. So, if you need to preserve state you can pass it as parameter to new UserControl. Recreating usercontrol cause all strings to reload without window recreation. Maybe good idea would be to call GC.Collect(); here, but depends on your scenario.
About default neutral culture. For me works to call SetLanguage("").
There are 2 things
Thread.CurrentThread.CurrentCulture
and
Thread.CurrentThread.CurrentUICulture
In order to set these valuse use the static method
CultureInfo.GetCultureInfo(String langCode)
where some examples of the parameter langCode are the following strings
"de-DE"
"en-US"
etc.
more info at
https://msdn.microsoft.com/en-us/library/yck8b540(v=vs.110).aspx
So, overall these lines of code sould work for change in German Language:
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
Is it possible to implement different language into UWP application from code behind using multilingual toolkit & not by setting the desired language from the settings but instead from the dropdown list of language within the application
You don't actually need the Multilingual App Toolkit to modify the language of your app. By default, the app will configure itself based on the settings on the machine, but you can override that by setting the CurrentCulture and/or CurrentUICulture.
Say for instance you had a Combobox that contained "English", "Spanish" and "French"... and your desired behavior is to switch your language to whichever value the user selects. All you'd need to do is hook up the SelectionChanged event. Here's what the code might look like:
private void ChangeLanguage(object sender, SelectionChangedEventArgs e)
{
var newlySelected = e.AddedItems[0] as ComboBoxItem;
string newLanguage = newlySelected.Content.ToString();
switch (newLanguage)
{
case "English":
{
CultureInfo.CurrentCulture = new CultureInfo("en");
CultureInfo.CurrentUICulture = new CultureInfo("en");
break;
}
case "Spanish":
{
CultureInfo.CurrentCulture = new CultureInfo("es");
CultureInfo.CurrentUICulture = new CultureInfo("es");
break;
}
case "French":
{
CultureInfo.CurrentCulture = new CultureInfo("fr");
CultureInfo.CurrentUICulture = new CultureInfo("fr");
break;
}
default:
{
throw new NotImplementedException("Unidentified Language");
}
}
}
Naturally, I'd encourage you to do all the appropriate error checking (Make sure that the cast to ComboBoxItem works, etc...).
Also, remember that you need to set CurrentCulture if you want things like Dates and Times to show in the appropriate locale and use CurrentUICulture if you want to modify which resources your ResourceLoader uses to populate the UI.
Hopefully this should get you up and running!
--Dante
I've been developing a c# app. (It runs OK, there's not problem).
But Now, my boss need it work on English, Spanish and other languages.
I saw some tutorials about how to change languages in my app on different web pages (like this, and this)
My problem is:
I don't have defined any item, I mean, I don't have text boxes, labels or buttons. I just have a form:
While my app is running, it reads a .txt file: If there's a "button" line in the .txt, my app will add a button to my form, if there's a "label" line, it will add a new label.
So, I can't use the .resx file as the tutorials said.
It doesn't work.
I donĀ“t know if I'm doing it wrong or it simply doesn't work
Any idea?
I don't know what to do
I read the. txt file (line by line) and I assign the properties like this
public static Label[] LAB = new Label[2560];
public static int indice_LABEL = 0;
if (TipoElemento == "LABEL")
{
LAB[indice_LABEL] = new Label();
LAB[indice_LABEL].Name = asigna.nombreElemento;
LAB[indice_LABEL].Left = Convert.ToInt32(asigna.left);//LEFT
LAB[indice_LABEL].Top = Convert.ToInt32(asigna.top);//TOP
LAB[indice_LABEL].Width = Convert.ToInt32(asigna.width);
LAB[indice_LABEL].Height = Convert.ToInt32(asigna.height);
//and all I need
...
...
Formulario.PanelGE.Controls.Add(Herramientas.LAB[Herramientas.indice_LABEL]);
Herramientas.indice_LABEL++;
}
If you need to stick with this format, the best solution would be to have 1 file with all the control definitions (name, dimensions, position etc) and another with the text to display to the user
Then when you create each control, instead of assigning it a caption you use the ResourceManager, linked to your 'captions' files (1 for each language) to retrieve the correct string to display
For example:
Language Text File
This will be a simple text file, resource.en-US.txt
Inside, you will need to add simple key>value pairs:
label1=Hello world!
To make another language, simply create another file, resource.fr-FR.txt, and add:
label1=Bonjour le monde!
Application Code
// Resource path
private string strResourcesPath= Application.StartupPath + "/Resources";
// String to store current culture which is common in all the forms
// This is the default startup value
private string strCulture= "en-US";
// ResourceManager which retrieves the strings
// from the resource files
private static ResourceManager rm;
// This allows you to access the ResourceManager from any form
public static ResourceManager RM
{
get
{
return rm ;
}
}
private void GlobalizeApp()
{
SetCulture();
SetResource();
SetUIChanges();
}
private void SetCulture()
{
// This will change the current culture
// This way you can update it without restarting your app (eg via combobox)
CultureInfo objCI = new CultureInfo(strCulture);
Thread.CurrentThread.CurrentCulture = objCI;
Thread.CurrentThread.CurrentUICulture = objCI;
}
private void SetResource()
{
// This sets the correct language file to use
rm = ResourceManager.CreateFileBasedResourceManager
("resource", strResourcesPath, null);
}
private void SetUIChanges()
{
// This is where you update all of the captions
// eg:
label1.Text=rm.GetString("label1");
}
Then all you need to do is change the private string strCulture= "en-US" to "fr-FR" (eg in a combo box), and call the GlobalizeApp() method, and the text in label1 will change from Hello world to Bonjour le monde!
Simple (I hope :) )
Check out this link for a great walkthrough
I'd like to programmatically set the culture of my User Control which defines several Labels, Buttons and Textboxes ...
Usually, for aspx-pages you override the InitializeCulture-Method and set Culture and UICulture to achieve this, alas ASCX-Controls do not have this Method, so how exactly would I do this?
I've set up the local resources mycontrol.ascx.de-DE.resx, mycontrol.ascx.resx and mycontrol.ascx.en-GB.resx but only the values of the default file (mycontrol.ascx.resx) are used.
Thanks in advance.
Dennis
The current culture is thread-wide: Page.Culture and Page.UICulture actually set Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture under the hood.
If the user control is defined in your page markup, I don't think there's anything you can do. If you load it with LoadControl(), you can temporarily override the current thread's culture before the call and restore it afterward, but it would be quite awkward:
protected void Page_Load(object sender, EventArgs e)
{
// Some code...
CultureInfo oldCulture = Thread.CurrentThread.CurrentCulture;
CultureInfo oldUICulture = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentCulture = yourNewCulture;
Thread.CurrentThread.CurrentUICulture = yourNewUICulture;
try {
Controls.Add(LoadControl("yourUserControl.ascx"));
} finally {
Thread.CurrentThread.CurrentCulture = oldCulture;
Thread.CurrentThread.CurrentUICulture = oldUICulture;
}
// Some other code...
}
I also spent hours on this problem and finally got This solution.
You only have to override the FrameworkInitialize() instead of initilizeculture(),
eg:
protected override void FrameworkInitialize()
{
String selectedLanguage = LanguageID;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(selectedLanguage);
base.FrameworkInitialize();
}
Jus Put this code inside your ascx.cs file, This override function does not need to be called.
I used the following code to change the language for asp.net mvc in my project page
public ActionResult ChangeCulture (Culture lang, string returnUrl)
{
if (returnUrl.Length> = 3)
{
returnUrl = returnUrl.Substring (3);
}
return redirect ("/" + lang.ToString () + returnUrl);
}
also I used usercontrol (ascx) on the same page.when I changed language with actionlink is changed viewpage language but user control pageload event isn't capture changing so viewpage's language changes but usercontrol's language doesn't change
Using reflector I found the following code in the System.Web.UI.WebControls.Parameter class:
internal void UpdateValue(HttpContext context, Control control)
{
object obj2 = this.ViewState["ParameterValue"];
object obj3 = this.Evaluate(context, control);
this.ViewState["ParameterValue"] = obj3;
if (((obj3 == null) && (obj2 != null)) ||
((obj3 != null) && !obj3.Equals(obj2)))
{
this.OnParameterChanged();
}
}
The line
this.OnParameterChanged();
is what triggers the ParametersChanged-event in the end, as I understand (through this._owner.CallOnParametersChanged() in OnParameterChanged).
Now my question is: what happens if EnableViewState is set to false (e.g. on the whole page)? And as an addendum: I am using ControlParameters pointing at the SelectedValue of a DropDownList.
I assume this would mean:
obj2 would either be the value that has been set earlier in the same request (i.e. UpdateValue has been called before) or null if no other value has been set yet.
As a DropDownLists SelectedValue cannot be null obj3 will never be null.
OnParametersChanged will always be invoked the first time UpdateValues is called in any request.
But if the same entries are loaded into the DropDownList during a PostBack ASP.NET retains the selection in the list across the PostBack even if ViewState is disabled (I can only guess how that works but it does...).
This comes down to the following: if ViewState is disabled and the same values are being loaded into the DropDownList on every request and the user had chosen entry X "long ago" and triggered a PostBack by other means than changing the selection in the DropDownList ASP.NET would fire a ParametersChanged-event on the ParameterCollecion (because of #3 in the list above) although in my understanding the parameter did not change its value.
Am I wrong or does this mean I cannot (should not) disable ViewState if this behaviour is causing trouble?
UPDATE (not directly related to the question)
Just to get rid of the question how the DropDownList preserves the selected value through a post back if viewstate is disabled: by its implementation of IPostBackDataHandler...
Reflector reveals (in DropDownList):
protected virtual bool LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
string[] values = postCollection.GetValues(postDataKey);
this.EnsureDataBound();
if (values != null)
{
base.ValidateEvent(postDataKey, values[0]);
int selectedIndex = this.Items.FindByValueInternal(values[0], false);
if (this.SelectedIndex != selectedIndex)
{
base.SetPostDataSelection(selectedIndex);
return true;
}
}
return false;
}
So it essentially retrieves the value of the selected item in the POSTed data and if it can find an item with this key in the list of items the DropDownList contains it sets it as selected.
You are correct: you cannot disable viewstate if you want the ASP.NET web control 'changed' events and behaviors to work.
The basic mechanism they use to determine whether there has been a change is to compare the value serialized in viewstate to the equivalent posted value (if any). TextBox.TextChanged (for example) spells this out clearly in its class documentation:
A TextBox control must persist some
values between posts to the server for
this event to work correctly. Be sure
that view state is enabled for this
control.