Get user culture, not thread culture - c#

When my application starts, it sets its own culture to CultureInfo.InvariantCulture but in some places, I want to use localized number formatting according to what the user has set in Windows. How can I do this?
System.Globalization.CultureInfo.CurrentCulture only returns the thread's culture which is no longer the user's default.
I'm hoping for a more elegant way than storing the thread's default culture before changing it or creating a new thread just to read the culture out of it.
Maybe there's a built-in .Net wrapper for the Windows function GetUserDefaultLocaleName?

System.Globalization.CultureInfo has an internal property named UserDefaultCulture which is the equivalence of the Win32 GetUserDefaultLCID() as commented in .NET Source code:
//
// This is the equivalence of the Win32 GetUserDefaultLCID()
//
internal static CultureInfo UserDefaultCulture
So you can use it to get user default culture this way:
var property = typeof(System.Globalization.CultureInfo).GetProperty("UserDefaultCulture",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var culture = (System.Globalization.CultureInfo)property.GetValue(null);
Also as another option, you can create a new thread and use its CurrentCulture property:
var culture = new System.Threading.Thread(() => { }).CurrentCulture;

Related

Windows Forms Localize resx without changing Culture

I know it's easy to localize Windows Forms App: set Localizable=True, change Language and set text in Controls for every Language. This information saves in resx-files and application will automatically select the required file. Great!
I know about disadvantages of this solution (you need to rebuild the app if there a typo, it's impossible to change language in runtime, etc), but it's not a problem for me and "resources" is the simpliest, built-in solution.
But this mechanism uses the property Culture of app's thread.
My app is the part ("plugin") of the bigger application and works in the same Thread.
The main application is multilingual too, but it doesn't use Culture to change interface's language. I can change the thread's culture globally, but it crushes the main app's interface.
So my question:
is it possible to manually set the resx-localizable resurce file that will be used? Not based on Culture, but, for example, on some variable in my app:
if (this.Language == "fr")
this.Resources.Add("Form1.fr.resx");
else
this.Resources.Add("Form1.en.resx");
Or something else.
Thank you!
My sandbox:
https://github.com/Tereami/WindowsFormsTestLanguage
The built resources file has a property ResourceManager that's used to return the desired content. This has an overload with a CultureInfo parameter. You can use it to request resources in individual languages:
var desiredCulture = new CultureInfo("en-us");
var text = MyStrings.ResourceManager.GetString(nameof(Resources.ExitMessage), desiredCulture);
If you want to set the culture globally for your resource file, you could also set it through the corresponding property:
var desiredCulture = new CultureInfo("en-us");
MyStrings.Culture = desiredCulture;
var text = MyStrings.ExitMessage;

CultureInfo InvariantCulture necessary?

I have added one localisation for my resource file. ResGeneral.resx and ResGeneral.cs.resx. My computer has czech environment so even Invariant culture uses the .cs.resx file. The projects default culture is set to Invariant.
Then I added a combo box with options loaded from the SupportedLanguages enum, which changes the selected lang index in config, so next time program is launched, the culture is changed to the selected index.
public enum SupportedLanguages
{
Invariant = 0,
English,
Czech
}
public static void ChangeLang(int lang)
{
CultureInfo cultureInfo = CultureInfo.InvariantCulture;
switch (lang)
{
case 1:
cultureInfo = new CultureInfo("en");
break;
case 2:
cultureInfo = new CultureInfo("cs");
break;
}
CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = cultureInfo;
}
How should I approach this?
Can I specify that the clean .resx (en) is to be used with invariant always?
Is there reason to even use Invariant or can I set the default to "en"? Project owner fears that some machines might not have "en" culture installed, but I haven't found any info about that. Is that possible?
Is this even a problem? So what it auto uses Czech, if a German user launches it, I dont have a .de file, it uses the clean .resx and he sees english
What do you think? Thanks for answers.

DateTime.ToString format inconsistent between Web App and Windows Service

We are experiencing weird behaviour between a web application and windows service when trying to perform a ToString() on a DateTime value.
See the example below.
DateTime parsedReportDate;
reportDate = DateTime.Now.ToString("yyyyMMdd");
reportDateWithSlash = DateTime.Now.ToString("dd/MM/yyyy");
if (DateTime.TryParse(MyDateValue, out parsedReportDate))
{
reportDate = parsedReportDate.ToString("yyyyMMdd");
reportDateWithSlash = parsedReportDate.ToString("dd/MM/yyyy");
}
--reportDateWithSlash on Web Application: 28/03/2017
--reportDateWithSlash on Windows Service: 28-03-2017
The Windows Service calls the same function as the Web Application does, so why is the formatting different then?
The formatting of dates to strings uses a CultureInfo object to know what format to use.
Each Thread has a Thread.CurrentCulture property.
You can find out what CultureInfo the current Thread is set by getting the current Thread using Thread.CurrentThread and then inspecting it's Thread.CurrentCulture property.
public class Program
{
public static void Main()
{
Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name);
}
}
https://dotnetfiddle.net/dsA3VT
Output: en-US
You can set the CultureInfo for the the Thread, or pass it with each call to ToString.
Setting Thread.CultureInfo
You can set the Thread.CultureInfo using the same property as you use to read it.
Thread.CurrentCulture = new CultureInfo("en-gb");
Unfortunately .Net Fiddle doesn't support changing thread properties.
I didn't know this, but bradbury9 pointed out that since .net 4.6 you can set the CultureInfo.CurrentCulture property as well.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("nl-NL");
Unfortunately .Net Fiddle doesn't support changing the culture this way either.
Passing CultureInfo to ToString
'DateTime.ToString' has overloads which can take an IFormatProvider, and CultureInfo impliments IFormatProvider.
DateTime.Now.ToString(new CultureInfo("en-gb"));
https://dotnetfiddle.net/qkS5HF
public class Program
{
public static void Main()
{
var dateTime = DateTime.Now;
Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name);
Console.WriteLine(dateTime.ToString(CultureInfo.InvariantCulture));
Console.WriteLine(dateTime.ToString(new CultureInfo("en-us")));
}
}
Output:
en-US
03/28/2017 09:43:49
3/28/2017 9:43:49 AM
The problem must come from having different cultures. Using the DateTime.ToString (String, IFormatProvider) overload with the CultureInfo.InvariantCulture property should solve the problem:
DateTime.Now.ToString("dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
it may be what is calling the Windows service is formatting the date. the code certainly is clear enough. Try debugging the windows service by attaching to the running process and see what it generates. If your service consumer is a web app, look at F12 developer tools and see what is getting sent back int he response stream.

CultureInfo not changing at design time

I have used resource files for localization in design time support. The localized string will be retrieved for designer action items to be added in designer of a control. Here is the code which i used to get the current culture from the resource manager in design mode.
if (resourceManager != null)
{
CultureInfo currentUICulture = CultureInfo.CurrentUICulture;
if (resourceManager.GetResourceSet(currentUICulture, true, true) != null)
{
ResourceManager result = resourceManager;
return result;
}
}
and i have changed the current culture using below code in form level.
public Form1()
{
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");
CultureInfo.CurrentCulture = new CultureInfo("fr-FR");
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
InitializeComponent();
}
My Issue - Changed culture for French is not retrieved at design time. Culture got is en-US all the time.
Does anyone know, how to change the culture to reflect at runtime in order to solve the above mentioned issue?
Regards,
Amal Raj
Consider these facts:
CultureInfo.CurrentUICulture returns current thread UI culture.
Your design-time in visual studio, is visual studio's run-time.
Constructor of your Form1 will not execute at design time. Its InitializeComponent methis will be just deserialized to initialize a an instance of its base class Form which is shown in VS designer.
Since your current thread is Visual Studio UI thread and it uses en-US in your system, so you will receive en-US in design time as current UI thread.

Cannot get current server culture

I am working on multi Lingual application in c# asp.net MVC, in which server, client or both may have different languages other than English. My development machine has English as default language, and using language bar in windows, I have set my current language to French (belgium), my client end browser language is Dutch(belgium). For every request I used to change Thread Current Culture to Dutch(client end browser language) using globalization techniques as follows.
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpCookie userCookie = Request.Cookies["Culture"];
string cultureCode = "en-US";
if (userCookie != null)
{
cultureCode = userCookie.Value;
}
CultureInfo culture = new CultureInfo(cultureCode);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
I wanted to find OS current culture, therefore, I used
CultureInfo.InstalledUICulture
to find OS current culture, which should be French(Belgium) FR-BE, but every time it is returning me en-US English(united states). I already know that problem is with windows, it always returns default windows culture instead of current Culture as explained in this question. I wanted to know, is there any way to find current OS culture which is French(Belgium) FR-BE on my server.
I believe you might want to check:
public static CultureInfo CurrentCulture { get; set; }
public static CultureInfo CurrentUICulture { get; set; }
This should contain the default OS culture when your application starts.

Categories

Resources