- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Localisation is like date handling. Dunning-Kruger rejects reimplement them.
Admin
I made a similar mistake about 15 years ago working on an internal company application. I saw the convenience of using a static variable in C#, but didn't realize it was the same for all users. Each time a new user signed in, the column settings and screen colors would change FOR ALL USERS to that user's preferences.
A static variable is not a good place to store user settings :-)
Admin
1030 (and 1033] are neither cryptic nor meaningless... https://www.science.co.il/language/Locale-codes.php
Now go EA (presuming running on Pentium...)
Admin
I am not sure if I got the irony here - is the LCID really uncommon outside of the .NET world? It's a constant (not magic) number that defines the windows language code. See https://learn.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo.lcid?view=net-7.0 for an overview.
Admin
Just WTF? :D
Admin
Global variables, sometimes you need them. But NOT for user-specific values.
Developer: "But it worked on my machine!"
Admin
Comment held for moderation.
Admin
The LCIDs are not meaningless numbers, they are Windows locale IDs. https://ss64.com/locale.html
Admin
Haha, 7 comments, 6 hold for moderation :-)
.net started out with pretty rich globalization features from the start and asp.net build on top of them, so obviously all of the nonsense is not required since again .net exists - there's no real excuse here but just simply incompetence.
And why would anyone use a struct instead of a class as a container for a bunch of constants? This all is rather weird and screams developers first kindergarten project to me :-)
Addendum 2023-10-24 08:27: How it's done correctly 2023 edition: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization/select-language-culture?view=aspnetcore-7.0
Admin
Structs are treated as value instead of as reference types. And there is some performance overhead with the latter. So if used correctly structs can be more performant. This is especially important if all you want to do is pass around a lot of data using them.
Admin
Structs also have a performance overhead which is why their use is recommended only in some scenarios (https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct). Don't ask me why Unity's Burst Engine makes my eyes bleed.
Admin
App worked nicely for Danish users only, before business said they wanted the user data localis(z)ed. Then dev applied some logic to that, and it was ever only tested for Danish users (otherwise it would have failed testing).
Yes, it's a terrible bug / oversight, but testing should have picked this up.
Admin
Const are always getting inlined; there's zero overhead, beside of the the more slightly more complex meta data, there ain't not difference.
Addendum 2023-10-24 09:21: Oh and yes, the correct type for the object in the article is obviously a internal/public static class ;-)
Admin
LCID is not a meaningless identifier and 1033 is not a meaningless cryptic integer. Microsoft defined both. I won't post the link right now because it'll get my comment held for moderation, but googling LCID 1033 will easily find the definition of both.
Admin
Yes, this is correct. If the struct is bigger than 16 bytes, it's actually more efficient to use reference types if the instance is just passed a few times to methods by value. That was just recently again confirmed by the .net language team in one of the pull review streams.
Admin
In this case the struct is just a stringy enum. It's not instantiated, so the whole struct vs. class thing doesn't really matter when all you care about is the name. Besides, records are better :P
Admin
I'm not a C# person, but find it hard to believe there are no system-defined constants and that you're supposed to just use magic numbers in the code.
Why can you do something like: [pre] Session["LCID"] = System.Globalization.CultureInfo.LCID::da-DK; [/pre] ???
Admin
Anyone who's ever gone digging around in the program files of Microsoft applications like Visual Studio will have come across folders named "1033". I eventually figured out it is the id of the English locale.
Admin
It absolutely is cryptic. What is 1033? I can't tell looking at the code, so it's pretty cryptic. A better way would be to have a constant variable, something like LOCALE_ID_EN_US = 1033, or even LCID_EN_US = 1033.
You're certainly correct that it's not meaningless though.
Admin
For all those defending "1033" as being "not a magic number". OK, I recognised that as en-US right away. But "1030" - is that the right value for "da-DK"? I'd have to go look that up online - after first finding the appropriate website that has a usable list. Not hard, but I shouldn't have to spend a couple of minutes in a web browser just to work out what you're actually setting the value to.
It is much better for this usage, as for any other magic numbers, to have a constant defined in one place (if there isn't already one in the API somewhere). It is immediately obvious and readable what it's supposed to be, and there is exactly one place where you need to make sure it has been implemented correctly.
Admin
I hope and pray (to any higher being that might exist, be listening and care) that today’s commenters are mostly trolling…
“1033 is neither cryptic nor meaningless”
“Googling LCID 1033 will get the definition of both…”
“It’s a constant (not magic) number”
As ever, TRWTF is in the comments…
Admin
In .net (since the beginning) you don't use the LCID directly anymore, in fact you should only use the CultureInfo from Thread.CurrentCulture.CurrentCulture and Thread.CurrentCulture.CurrentUICulture (https://learn.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo?view=net-7.0#Current). The difference between those two is server vs client settings.
In ASP.net they culture gets set using the appropriate middleware (as mentioned above with link) that will parse the accept-language header correctly (which is actually pretty complex if implemented correctly because you can request multiple locals with specific priorities (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language). Keep in kind that ASP.net guarantees that all asyncronous requests are actually running on the same physical thread and therefore they get correctly bundled together, so it's async safe to use those properties.
So yeah, playing around with LCID and CultureInfo is a nice callback thing to the good old 80s/90s, it's bad practice these days and completely pointless in .net since ever (aka more than two decades). But I get it, globalization is not easy and most devs ignore it until they run into issues like not using UTC and suddenly due to daylight savings there's an hour missing in the yearly business report.
Admin
Yeah, I disagree with that. It's one of the things that's really missing in PHP, for example (there are some 3rd party workarounds at least like apcu or redis, but they come with their own drawbacks). Application-scoped variables are a godsend when you want to do any sort of local in-process caching or pooling. Obviously you shouldn't abuse them, but they are a very useful tool for certain jobs.