I want to change the windows culture settings programmatically since when using my program I need to parse the dot "." as the decimal number and windows has by default set the ",". So I'm looking for this.
I already tried by changing the current app culture but when parsing data from db it still gets in trouble because it uses windows configuration.
I'll emphasize, do it better.
This can be pretty easily solved, and a quick example:
public static decimal GetInvariantDecimal(string internationDecimalString)
{
var looksUnAmerican = Regex.IsMatch(internationDecimalString, #"(\d+,\d{2}\b)|(\d+\.\d+,\d{0,2})|(\d+\.\d{3})");
Console.WriteLine(looksUnAmerican);
return looksUnAmerican ?
Decimal.Parse(internationDecimalString, NumberStyles.Currency, CultureInfo.GetCultureInfo("tr-TR")) :
Decimal.Parse(internationDecimalString, CultureInfo.InvariantCulture);
}
public static void Main()
{
var american = "123.55";
var international = "234,55";
Console.WriteLine(GetInvariantDecimal(american));
Console.WriteLine(GetInvariantDecimal(international));
}
It will give you a standard decimal for the correct environment, and you would use this every time you work with the string from the database. (of course, it doesn't currently handle something like "1,234.01"...
But output:
123.55
234.55
And one more bit, changing the users machines culture will likely cause all sorts of bugs in who knows what...
Related
Windows Server 2012 seems to have several issues regarding CultureInfo. The information about decimal digits for currencies in culture es-CL (that's Chile) is incorrect, it says 2 digits but here in Chile we don't use decimals in our currency.
Do anyone knows about a patch or maybe a way to override this setting? Modifying the Windows Locale options does not work for me, because I need this working on a MVC 5 site.
Any help, will be greatly appreciated.
PS: I never had this trouble with my dev-machine (I've use from Win7 to 10), so I'm guessing this issue only exists on Windows Server 2012
Gabriel check this configuration and try it.
https://i.stack.imgur.com/C0A4d.png
First of all, let me tell you this is not what I need, but I will leave it here in case someone else needs a patch for this.
One alternative is to "patch" the source code in order to override the amount of decimal digits used in currencies (you can override all properties you want). To do this you have to Create a Specific Culture using as base the one you want to override:
culture = CultureInfo.CreateSpecificCulture("es-CL");
culture.NumberFormat.CurrencyDecimalDigits = 0;
And then assign this "culture" variable to the "Current Thread":
Thread.CurrentThread.CurrentCulture = culture;
Finally, if you are using MVC as me, you can add this code into an "ActionFilterAttribute" in order to make all calls use this settings:
public class LocalizationFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CultureInfo culture = CultureInfo.CreateSpecificCulture("es-CL");
culture.NumberFormat.CurrencyDecimalDigits = 0;
Thread.CurrentThread.CurrentCulture = culture;
}
}
And don't forget to register your Filter, in your Global.asax include the following line:
GlobalFilters.Filters.Add(new LocalizationFilter());
If I have a CultureInfo instance, is there any simple way — built-in, through a framework or via the OS — to obtain a matching "flag" icon matching that culture? This would avoid having to create a separate lookup.
I couldn't find a member function to do the job in the documentation for CultureInfo, but perhaps there is some other not-too-taxing approach that involves other .NET classes that I haven't found.
No. There is no simple, built-in way, through the .NET framework or the Windows operating system, to obtain a matching "flag" icon for a given CultureInfo instance.
Extending Alex's answer. Once you have the ISO code, you can use this simple library to produce an ImageSource of the flag (from the famfamfam set) from the two character string:
https://github.com/drewnoakes/famfamfam-flags-wpf
It's not built in, but it is easy to use.
Images end up looking like this:
As #Peter Duniho said, there is no built-in way in the .NET Framework. Furthermore, CultureInfo represent locales, while flags represent countries, and there are many situations where the two do not perfectly match. You may incur in diplomatic problems if you come across some users.
Anyway, if you want something simple, you may want to use famfamfam's flag icons, which have been conveniently named after the ISO 3166-alpha1 2 letter country code, and then convert your CultureInfo to a RegionInfo given the locale, and finally get the two letter ISO region name:
var r = new RegionInfo(yourCultureInfo.LCID);
var flagName = r.TwoLetterISORegionName + ".gif";
finally, if such a file exists, then display it. Please note that you may use the PNG versions, and that different languages may map to the same country (I'm thinking of Switzerland, where they speak 4 official languages).
Guess what! It’s now possible to do this in C# and is supported by most platforms including Windows 11 devices! You can just use the emojis and you don’t need a flag icon pack!
On Windows 10 it only works on Firefox browsers for now. But it does work with iOS, MacOS & Android apps
public string GetFlag(string country)
{
var regions = CultureInfo.GetCultures (CultureTypes. SpecificCultures).Select(x => new RegionInfo(x.LCID));
var englishRegion = regions.FirstOrDefault(region => region.EnglishName.Contains(country));
if (englishRegion == null) return "🏳";
var countryAbbrev = englishRegion.TwoLetterISORegionName;
return IsoCountryCodeToFlagEmoji(countryAbbrev);
}
public string IsoCountryCodeToFlagEmoji(string countryCode) => string.Concat(countryCode.ToUpper().Select(x => char.ConvertFromUtf32(x + 0x1F1A5)));
https://itnext.io/convert-country-name-to-flag-emoji-in-c-the-net-ecosystem-115f714d3ef9
I feel like this is something I've done a thousand times so not sure why it is being so difficult now. I've created a method that simply returns Today's date for the user based on their UTC offset. But instead of returning a string resembling a date, it is returning this garbage
"䙭/䙭/Ἰ뻱䙭"
Here is the code.
public string getToday(Context context)
{
var settings = PreferenceManager.GetDefaultSharedPreferences(context);
var offset = settings.GetInt("offset", -5);
var now = DateTime.UtcNow.AddHours(offset);
return now.ToShortDateString();
}
When I step into the code using a breakpoint, offset and now both seem correct. now contains valid date parts all appearing to be accurate. Something about converting now to a string seems to go horribly wrong. Also tried:
return now.ToString("MM/dd/yyyy");
Same result. Weird part is the below code in another activity works without issue
var offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
var now = DateTime.UtcNow.AddHours(offset);
now.ToString("MM-dd-yyyy")
Sounds to me like a localization issue. Make sure you're actually in English, be it en-US or similar.
I assume that your device is set to a Chinese/Japanese/Korean culture. If you always want to return US dates, use:
return now.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture);
Edit: Given the rest of your comments, I’m starting to suspect that this might be caused by corruption, or by a bug in the MonoDroid implementation. You could try working around it by constructing the date manually (although this admittedly doesn’t address the cause of your issue):
return string.Format("{0:00}/{1:00}/{2:0000}", now.Month, now.Day, now.Year);
Assume I have a String Field in my WinApp like below :
public string UsingTheApplicationFrom =
"Not Yet";
Now , I wanna to change the value of the field forever, in first running of my application. e.g : UsingTheApplicationFrom = "Friday, January 21, 2011";
Is it possible in C# WinApp ?
Could you please guide me?
Edit:
I don't wanna use Database or file or Registry or something else.
You are looking for "a type of security for my application that only the first system (that runs the application for the first time) could use my application". I think you mean that each copy of the software you sell may only be installed on one computer at a time.
You have two problems to solve:
How to generate a unique identifier for the computer
How to store the identifier value
You have several options to use for a unique identifier, none of which are great. Be prepared for support requests from customers when they change their computer hardware, when their computer breaks, or when they want to move the software from one computer to another. A decent-looking method to compute a unique identifier is this article (mirror link since the code project article is not available).
I would recommend just storing this identifier as a string in the app.config file (using Properties.Settings, start at this link for more information). It will be visible in plain text, but how would an unlicensed user know what value to change it to for their machine when it looks like "4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9"? If it doesn't match direct them to your website/telephone for support.
You still have the problem of deciding when to set this value -- I would advocate for setting it as part of an installer instead of saving it the first time the program is run, since then you still have a problem to determine when the program is first run. The installer might need some sort of registration code and a method to communicate with a central licensing server. (Yes, this does get complicated -- how determined do you think people might be to hack your licensing?)
I am taking a guess, but by "always" I think he means "forever". You could easily create a key in the App.config of your application and populate it on the first run.
<add key="UsingTheApplicationForm" value="Not Yet"/>
On first run, update it to -
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["UsingTheApplicationForm"].Value = DateTime.Now.ToShortDateString();
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");
On second run check if the key value is equal to "Not Yet". If it is not, it means that this is not the first run.
I think maybe you want to use DateTime, and particularly, DateTime.Now - as with comments to the question however, I'm not properly sure.
So, something like:
UsingTheApplicationForm = String.Format("{0:dddd, MMMM d, yyyy}", DateTime.Now);
The 'always' part is very confusing though, I'm just going to buy into my own translation, where always = each startup.
I would also conjecture that, given the property/variable name of UsingTheApplicationForm, this value is an indicative field, rather than a descriptive one; for this reason, may just using DateTime.Now without any formatting, or even just a boolean (depends what fits your situation) fit the bill?
Edit:
For information on using this method, or any of the others, along with persisting this data for the next run, see the following question and answers...
Editing app.config in execution time using the same App
I like this way:
http://windowsclient.net/blogs/suryahg/archive/2008/08/11/persist-winforms-application-settings.aspx
There's no way to do it with nothing more than a string object, but you can create a simple object that does it:
public class ApplicationInfo
{
private ApplicationStartTime()
{
this.StartTime = new DateTime().Now;
}
public DateTime StartTime
{
get; private set;
}
public Create()
{
return new ApplicationStartTime();
}
}
I haven't compiled that, so there may be a minor syntax error or two. You would invoke it like so:
var applicationInfo = ApplicationInfo.Create();
Debug.WriteLine(applicationInfo.StartTime.ToString());
In your program.cs or main entry point for the program declare a public static datetime.
when the program is first run you can set the date time and access it in future.
public static Datetime m_StartDate = DateTime.now;
public static void Main(args)
{
m_StartDate = DateTime.Now;
}
then in your other forms (assuming you added the code to Program.cs)
txtStartTime.Text = Program.m_StartDate.toString();
I'm using English Visual Studio 2008 on English Windows 7, but I'm based in the Netherlands. A lot of my programs need to read and write floating point numbers. Compared to English, the Dutch notation of numbers switches the meaning of dots and comma's (i.e. 1.001 in Dutch is a thousand and one, and 1,001 is 1 + 1/1000). I will never ever ever have to write (or read) numbers in Dutch format, but for some reason, every program I compile defaults to it, so every ToString() is wrong. This gets me every time. I know I can put this at the start of every thread:
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
Or replace every instance of ToString() with:
String.Format(CultureInfo.InvariantCulture, "{0:0.####},{1:0.####}", x)
But sometimes I just want to compile something to see how it works, and not make any changes. Also, I'm bound to forget about this sometimes. Is there no way to just tell C#, .NET and/or Visual Studio to just always make all my projects/programs use the English number format?
It's not a matter of compilation - it's a matter of what happens at execution time. Unless you explicitly specify a culture, the current culture (at execution time) will be used. There's no way of changing this behaviour that I'm aware of, which leaves you the options of:
Explicitly stating the culture to use
Explicitly changing the current culture
Note that even if you change the current culture of the current thread, that may not affect things like the thread pool. Personally I think it's better to always use the culture explicitly.
You could always write your own extension methods to (say) call the original version but passing in CultureInfo.InvariantCulture. For example:
public static string ToInvariantString(this IFormattable source, string format)
{
return source.Format(format, CultureInfo.InvariantCulture);
}
Getting that right everywhere could be a pain, admittedly... and to avoid boxing you'd actually want a slightly different signature:
public static string ToInvariantString<T>(this T source, string format)
where T : IFormattable
{
return source.Format(format, CultureInfo.InvariantCulture);
}
You can add a line that sets CurrentCulture to Program.cs in your project templates.
Try: Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;