(Matt, never believe I don't hear you when you are saying things. This one is for you!)

Inside of Microsoft, there is a huge database of location data. That database is used to support products like MapPoint, Passport, Windows, and others with important information that each can use when they provide data about locations -- countries, regions, provinces, states, cities, and so on. How important it is varies from product to product (of course). But on Windows it is particularly dissed, and that ought to change.

In Windows, the primary key of this database is the GEOID, and many of the core GEOID values can be found in the Table of Geographic Locations.

(Lest you think I was talking out of my hat when I was talking about a huge shared database, compare the values in that table with those in MapPoint's GeoMapRegion values table!)

We have a program manager who started with us a while back and who has owned our Regional Options control panel applet for most of that time. One of the first things he noticed about Regional Options were that it was not driven by region, but by locale (which is itself primarily driven by language and secondarily by region as a tiebreaker any time the language alone would not give sufficient information). He was struck by how flawed that was as a concept, and has been trying to get us to think a bit beyond our current model. The model that gives the regional differences less importance than they deserve.

Although it is in my fundamental nature as a developer to disagree with him as a program manager (insert grin here), I will try to rise above that nature as a technical lead and admit that he is 100% correct. It does not make a lot of sense.

(teams throughout Microsoft start to get nervous)

However, the fundamental support of the locale model has been a central means of international support in almost every product at Microsoft. And there is no good way to reverse that and make everyone rewrite their functionality.

(teams throughout Microsoft breathe sighs of relief)

But this is no excuse for bad decisions in functionality!

APIs like GetUserGeoID are the most intuitive and obvious way to find out where someone is located. It is the answer a user gives in Regional and Language Options when asked for their location. The text in that dialog claims that the setting is used "To help services provide you with local information, such as news and weather." But how can we make those words true if applications Internet Explorer make their fundemental decision about the setting that controls the support of regional content on the default user locale (an LCID) rather than the geographical region (a GEOID)? As I said the other day when I asked "What is my locale? Well, which locale do you mean?" the default user locale is meant to impart the user's choice in format and collation preferences, NOT their location. So IE should be using the GEO settings for that!

Some will freak out at this point -- what would such a change to do users?

Well, let us say that we made the two settings act as being tied together by default, so that if you changed the locale that by default the GEOID would be changed with it.

This is easy since there is an under-documented LCType for GetLocaleInfo that retieves the GEOID that is asociated with a locale1 -- LOCALE_IGEOID (the value is 0x0000005B and the functionality has been since Windows XP). Any time the user explicitly changes the location after seeing the description in RED above, wouldn't the user be expecting IE to follow such a request?

Such a solution would solve the real problem for almost all users, and perhaps other folks for whom region is important (Windows Media Player, Passport, and news services for starters) would be able to start using the GEOID preference of the user as a starting point. Even the time zone settings would get an effective first guess with such a system (even if tweaking as required to obtain the best answers).

Because GEOIDs kind of rock. They provide a lot of potentially interesting information, as the SYSGEOTYPE enumeration defines:

  • GEO_NATION - GEOID of a nation. This value is stored in a long integer.
  • GEO_LATITUDE - The latitude of the GEOID. This value is stored in a floating point number.
  • GEO_LONGITUDE - The longitude of the GEOID. This value is stored in a floating point number.
  • GEO_ISO2 - The ISO 2-letter country/region code. This value is stored in a string.
  • GEO_ISO3 - The ISO 3-letter country/region code. This value is stored in a string.
  • GEO_RFC1766 - An RFC1766-style string derived from the locale and GEOID (for nations only).
  • GEO_LCID - A locale ID (LCID) derived from the language and the GeoID (for nations only).
  • GEO_FRIENDLYNAME - The friendly name of the nation. Example: Germany. This value is stored in a string.
  • GEO_OFFICIALNAME - The official name of the nation. Example: Federal Republic of Germany. This value is stored in a string.
  • GEO_TIMEZONES - The time zones associated with the GEOID. These values are stored in an array of IDs.
  • GEO_OFFICIALLANGUAGES - The official languages of the nation at the GEOID. These values are stored in an array of LCIDs.

Shouldn't we all consider using the result of GetUserGeoID when the question is "where am I?" rather than any of the various locale settings?

I think it really is enough of this "I don't want to make a a change because what if no one else does?" problems -- let's break the logjam and do the right thing, and work to make sure it is a better situation for everyone!

(Though with that said I will go in to work and still be just as cautious about any attempt at a suggestion to undo the current archeciture, beyond the (suggested above) step of having LOCAL_USER_DEFAULT drive the GetUserGeoID value!)

 

1 - There is also a RegionInfo.GeoID property that has been added to the Whidbey release of the .NET Framework, for a lot of the same reasons that inspired that LCType. The actual regions that fill the RegionInfo collection are locale-based, but at least now you can tie them together a little more than previously. Getting GEO information as listed in the SYSGEOTYPE enumeration is still not possible using the .NET Framework, though. Maybe something for next time....

 

This post brought to you by "" (U+2708, a.k.a. AIRPLANE)