I'm developing a shopping cart, and part of the functionality is to select your currency.
I have a drop down list, and when the selected index changes I've written some code to find the culture code (such as en-GB or en-US) and then change the culture of the current session. In addition, using the exchange rates given it changes the price...
I currently have en-GB as the default culture. When someone selects the en-US culture from the drop down everything works fine. The currency changes (all currency labels are set with ToString("C")) and the exchange rate changes.
When I use the drop down list to select en-GB again, the exchange rate changes (so I know the code is working), and after debugging I can see that the culture session has changed from en-US to en-GB, but the currency still displays as $ and not £.
I really can't understand why this is happening. The code is very simple, I'm overriding the page_Load event for each page to display the correct currency based on culture:
protected override void OnLoad(EventArgs e)
{
if (Session["Culture"] != null)
{
string culture = Session["Culture"].ToString();
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Session["Culture"].ToString());
}
base.OnLoad(e);
}
Why does it not change the currency back to £ when I'm changing the session culture from en-US to en-GB?
Because you are checking if (Session["Culture"] != null), which restricts you to set the culture second time as Session["Culture"] will not be null.
I got it, because it was coming from a database entry that for some reason was a char(10) datatype, I forgot to trim the text. This resulted in the culture not being found by the Framework and defaulting back to en-US as it couldn't find 'en-GB '.
Related
For background, we are in the process of upgrading to Windows Server 2012 R2, and testing revealed that some date input textboxes on our ASP.NET site aren't working as intended. The textboxes have a CompareValidator defined for them to check if one date is later than the other.
<asp:CompareValidator ID="CompareValidator3" runat="server" ControlToCompare="txtStartDate"
ControlToValidate="txtEndDate" ErrorMessage="..." Operator="GreaterThan" Type="Date"
Display="Dynamic"></asp:CompareValidator>
This CompareValidator is failing all the time now, on Windows Server 2012, whereas the old site hosted on Windows Server 2008 did not have this problem. I have done some digging and I think the most likely culprit is the change in default date format for the Canada region in Windows Server 2012. In the generated code for the page, the DOM element for the validator has a property "dateorder" that's always being set to "ymd". This value is "dmy" on the old site.
...
cutoffyear: "2029"
dataset: DOMStringMap
dateorder: "ymd"
dir: ""
display: "Dynamic"
...
Because our inputs take date strings like "01/01/2015", the "ymd" pattern is not matched and the validator returns false. I have changed the date format settings everywhere that I can think of, and even tried changing the IIS site's .NET Globalization settings to use another culture (en-GB), and nothing has worked. I'm really curious as to where this "ymd" setting comes from, and how to change it. Any help is greatly appreciated. Thanks!
"dateorder" comes from BaseCompareValidator which essentially reads CultureInfo.CurrentCulture
DateTimeFormatInfo dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
string pattern = dateTimeFormat.ShortDatePattern;
string dateorder = (pattern.StartsWith ("y", true, Helpers.InvariantCulture) ? "ymd" : (pattern.StartsWith ("m", true, Helpers.InvariantCulture) ? "mdy" : "dmy"));
Now the gotcha as pointed here, is that Regional Settings is per-user and you might want to check the account the Application Pool was running under.
Maybe somebody changed the date format in the Windows OS on the old computer? But how about trying to force it within your application...my idea is to do it in the Global.asax file (you may have to add that file to the root of the application if it is not already there). Then, something like this:
using System.Globalization;
using System.Threading;
protected void Application_BeginRequest(Object sender, EventArgs e)
{
CultureInfo myCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
myCulture.DateTimeFormat.ShortDatePattern = "dd-MM-yyyy";
myCulture.DateTimeFormat.DateSeparator = "-";
Thread.CurrentThread.CurrentCulture = myCulture;
}
Have you try to change sort date from control panel regional setting. Dateorder and cutoffyear etc attribute are used by validation JavaScript generated by .net for validator control to function on browser. Value of these comes from server settings. IIS only picks as per server config and generats HTML.
I am working a multi-lang site. I want to get and set culture and uiculture with culturename without countryname. If browser is english or lang is English choosen, it will return en not en-US or en-GB. Because I use one localresources file per language and I have to send language code to sql procedure as a parameter.
Thread.CurrentThread.CurrentCulture
Thread.CurrentThread.CurrentCulture.Name
Thread.CurrentThread.CurrentUICulture
All of them returns en-GB,de-DE,de-AT etc... I just want first part and use this ones.
http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28VS.71%29.aspx
There are the name in the link but browser does note return it, I just want and use the simple part.
How can I do that?
It is solved (:
edit:
Now, How can I read browser's culture and if I don't have it, how can I set the culture that I have.
eg: I have en,de,ru and the visitor's browser sen me fr, I want it is shown en ?
Have a look at the TwoLetterISOLanguageName-property. It should return the identifier you are looking for. For example:
var cult = new System.Globalization.CultureInfo("en-US").TwoLetterISOLanguageName;
Returns "en" so that you can send it to the stored procedures.
I am using ASP.NET to provide some variables for the data that has to be added to a SQL database.
Code I am using:
I am using DateTime.Now to select the current time.
How I use it:
I have two pages, one is a page to insert the posts of the users. Other page is used for ajax purpose, to add some text comments to the posts.
In both page I use the same code.
But the code is executing different values. You can have a look here:
In the post the time is saved as "9/1/2013" which means 1st September, 2013! In comment it is saved as Sep 1 2013, which means the same.
My question: how does the code know that the request is an ajax one or the post one. The post page code is wrapped in if(IsPost) { however the comment is an ajax call.
What is the reason behind this?
I found what the issue was.
I had set the column DataType to nvarchar(50) in the database table. After editing it to DataType DateTime I was able to get the same result. So the issue was not the Culture or DateTime. It was the DataType of the column in SQL Server Database.
Assuming that your AJAX call is not changing the format string of your DateTimes, I would assume the threads which process those 2 different requests are operating under different cultures, which would explain why they're being displayed differently (not sure why though, check your settings perhaps). Try the following and you'll see how culture can effect DateTime output:
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Console.WriteLine (DateTime.Now.ToString());
Thread.CurrentThread.CurrentCulture = new CultureInfo("gu-IN");
Console.WriteLine (DateTime.Now.ToString());
Here's some additional information on CultureInfo.
Code knows from Current thread's Culture information. You should use DateTime.Now.ToString("yyyy-MMM-dd") or any other formate according to your needs to be sure of output.
I'm building an ASP.NET web application, and all of my strings are stored in a resource file. I'd like to add a second language to my application, and ideally, I'd like to auto-detect the user's browser language (or windows language) and default to that, instead of making them choose something besides English. Currently, I'm handling all the resource population manually, so adding a second resource file and language is trivial from my point of view, if I had an easy way to automatically figure out what language to display.
Has anybody done this, or do you have any thoughts about how I might retrieve that value? Since ASP.NET is server-based, I don't seem to have any access to specific browser settings.
RESOLUTION: Here's what I ended up doing. I used a "For Each" to go through "HttpContext.Current.Request.UserLanguages" and search for one I support. I'm actually just checking the left two characters, since we don't support any dialects yet - just English and Spanish. Thanks for all the help!
Try this in the web.config:
<globalization culture="auto" uiCulture="auto" />
This will cause ASP.NET to auto-detect the client's culture from the request header. You can also set this on a per-page basis via the Page attribute.
This article (linked to archive.org as original link is now dead) might be helpful with auto detecting the browser's language setting.
[EDIT] Yes. The quoted article does not use ASP.NET. This article does.
Request.UserLanguages in ASP.NET 4 parses this as a string array.
Good info: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
This is a great question, as localization in ASP.NET is overlooked by many developers.
ASP.NET should automatically pick up on the user's browser settings and force the CultureInfo.CurrentCulture to the user's browser language. You can force the issue with a line in Page_OnInit() like:
Thread.CurrentThread.CurrentCulture = new CultureInfo(HttpContext.Current.Request.UserLanguages[0]);
How can you test this? Enter the languages panel on our browser and change settings.
The client generally sets Accept-Language in the HTTP request header with a quantitatively scored list of preferred language, conventionally (but not necessarily) in order of most favored to least favored. You can parse that, but as Maxam has noted, ASP.NET does have a mechanism for doing that on your behalf.
/// <summary>
/// Sets a user's Locale based on the browser's Locale setting. If no setting
/// is provided the default Locale is used.
/// </summary>
public static void SetUserLocale(string CurrencySymbol, bool SetUiCulture)
{
HttpRequest Request = HttpContext.Current.Request;
if (Request.UserLanguages == null)
return;
string Lang = Request.UserLanguages[0];
if (Lang != null)
{
// *** Problems with Turkish Locale and upper/lower case
// *** DataRow/DataTable indexes
if (Lang.StartsWith("tr"))
return;
if (Lang.Length < 3)
Lang = Lang + "-" + Lang.ToUpper();
try
{
System.Globalization.CultureInfo Culture = new System.Globalization.CultureInfo(Lang);
if (CurrencySymbol != null && CurrencySymbol != "")
Culture.NumberFormat.CurrencySymbol = CurrencySymbol;
System.Threading.Thread.CurrentThread.CurrentCulture = Culture;
if (SetUiCulture)
System.Threading.Thread.CurrentThread.CurrentUICulture = Culture;
}
catch
{ ;}
}
}
The source of this article is here:
How to detect browser language
In an ASP.NET application I'm setting the culture to lv-LV. All is fine, but the default short date format seems to be "yyyy.mm.dd". The client wants it to be "dd.mm.yyyy" (which is actually the LV standard). Where does ASP.NET get the date/time settings for a specific culture? How can they be changed for a single culture, without affecting other cultures (the application is supposed to be localizable)?
I once had a similar problem and solved it with:
DateTimeFormatInfo dtfi = (DateTimeFormatInfo)Thread.CurrentThread.CurrentCulture.DateTimeFormat.Clone();
dtfi.ShortDatePattern = "dd.MM.yyyy";
dtfi.DateSeparator = ".";
Thread.CurrentThread.CurrentCulture.DateTimeFormat = dtfi ;
Thread.CurrentThread.CurrentUICulture.DateTimeFormat = dtfi;
That way you get to keep every other regional setting except the date format.
This code actually ran on OnLoad in our Page base class. I'm not so sure that is the best way.
.Net gets the date/time settings for a specific culture from the DateTimeFormatInfo class. You can set the DateTimeFormat property of a CultureInfo with a DateTimeFormatInfo that you have modified. If that culture is the current culture, then you can set it on the CurrentCulture. Either way, this only affects the CultureInfo that you have created and won't affect any other culture. (Any call to CultureInfo.GetCultureInfo("lv-LV") will not pick up those changes either since that is a read-only copy.) You don't necessarily have to pass that CultureInfo to any DateTime formatting methods (ToString, ParseExact) - you can pass the explicit pattern or the DateTimeFormatInfo.
CultureInfo lvLV = new CultureInfo("lv-LV");
DateTimeFormatInfo lvLVdtfi = (DateTimeFormatInfo) lvLV.DateTimeFormat.Clone();
lvLVdtfi.ShortDatePattern = "dd.MM.yyyy";
lvLV.DateTimeFormat = lvLVdtfi;
DateTime.Now.ToString("d", lvLV); // short date pattern from modified lv-LV CultureInfo
DateTime.Now.ToString("d", lvLVdtfi); // short date pattern from modified DateTimeFormatInfo
DateTime.Now.ToString("dd.MM.yyyy"); // explicit short date pattern
If lv-LV is the current Windows culture, then you can set a user override (use intl.cpl the Regional and Language Options control panel and customize the format) and the framework will pick this up.