MFC + Spanish version of Windows = Oops!

by Michael S. Kaplan, published on 2006/11/02 06:43 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/11/02/929063.aspx


Kurt's question was straightforward enough:

Hi,

Calling GetLocaleInfo on English Windows XP SP2 Professional and passing in the International Spanish LCID 3082 produces "ESN", however called on Spanish Windows XP SP2 Professional the result is "ES".

GetLocaleInfo(3082, LOCALE_SABBREVLANGNAME, szLangCode, 4);

This is a problem for MFC application debugged on Spanish Windows XP SP2, since the function _AfxLoadLangDLL in appcore.cpp causes an assertion (nResult == 3) (szLangCode == "ES"):

Code snippet from MFC's code:

nResult = ::GetLocaleInfo(lcid, LOCALE_SABBREVLANGNAME, szLangCode, 4);
if (nResult == 0)
    return NULL;
ASSERT( nResult == 4 );

Background: The above code tries to build filenames for localizes, resource only Satellite DLLs:

Localized Resources in MFC Applications: Satellite DLLs

http://msdn2.microsoft.com/en-us/library/8fkteez0.aspx
http://msdn2.microsoft.com/en-us/library/8fkteez0(vs.71).aspx

Is this a Windows XP localization bug? Or ... ?
 

Now my first thought was that SetLocaleInfo does not support LOCALE_SABBREVLANGNAME, and that the value return by LOCALE_SABBREVLANGNAME is not really a localized piece of data. So there really should be no such difference between a localized and a non-localized version of Windows here.

So I replied back to Kurt saying that this should not really be possible but I added someone to the thread who I knew would want to hear about the report, our NLS SDET Lead Gerardo Villarreal Guzman. He had another question to ask about the issue:

Kurt,

There should be no difference for SABBREVLANGNAME in XP SP2 for any language SKU. A favor to ask. Can you look in regedit HKCU\Control Panel\International and tell me the value for the sLanguage?

This is an overrideable field, so for some reason this may have been modified by an application.

Kind Regards,

Gerardo
 

What Kurt found was that this sLanguage value was indeed set to "ES", and that it was changing the results returned by that GetLocaleInfo call with the LOCALE_ABBREVLANGNAME flag.

I separately looked at the localized Spanish version of the HIVEDEF.INF file that setup uses to write several portions of the registry and it indeed set this value to "ES" and this was the case in both XP and Server 2003 in every version that has been released. This was causing this problem with MFC.

Damn.

So there is a lot of little problems that conspired to cause this to be an issue for MFC running on Spanish localized versions of Windows:

  1. There is the fact that this field is overridable in the registry but is clearly not allowed in the function that we try to really insist that people use to update the user locale data fields that can be overridden.
  2. There is the fact that this field is overridable at all, though there is probably some hidden reason long long ago in the before time related to the need to change the two-letter code in the Language Bar that no one I talked to remembered ever hearing about. 
  3. There is the problem of these non-localized fields which are actually stored in the locale data being duplicated on a per-language basis to populate the registry (rather than having code call GetLocaleInfo() to retrieve these values for the population). In addition to the particular issue in Spanish there are several languages whose values managed to fall out of sync with the locale data, which is an object lesson on why it is a bad idea to duplicate data. This is a problem that has been addressed in Vista, for all languages.
  4. There is the problem with the localizers whose data fell out of sync or whose data was never correct (as I suspect as the case for this "two character three-letter-code value!), though to be honest this whole architecture is unwieldy and was placing an unfair and unnecessary burden on localization -- so I am glad this flaw is gone in Vista.
  5. There is the fact that MFC uses this three letter string for its language resource lookups -- given all of the odd and arbitrary rules about where they come from (as I pointed out in this post and this one), it seems like a really bad choice, especially since this particular dependency was not something that people who own the NLS data were specifically aware of.
  6. There is also the problem where MFC is not passing LOCALE_NOUSEROVERRIDE to avoid getting the user override here -- which would have kept them from getting into trouble here when the other issues insisted on coming up.

I wonder how many Spanish speaking MFC developers and how many Spanish speaking customers running MFC apps had problems here. And how many worked around it with the slightly different name of their language resource DLLs? and whether the problem also happened prior to XP?

Plenty of fault to go around here, with each individual issue working as a part of the larger problem. Some very cooperative bugs, these were!

 

This post brought to you by  ñ (U+00f1, a.k.a. LATIN SMALL LETTER N WITH TILDE)


# Mihai on 2 Nov 2006 12:50 PM:

<<I wonder how many Spanish speaking MFC developers and how many Spanish speaking customers running MFC apps had problems here.>>

I would guess not too many, because it is mostly unknown.

The feature was introduced in MFC 7.0 (VS .NET 2003) and I have not seen it documented until much later, for VS 2005. I have discovered it in 7.0 by checking the MFC sources for some other reason.

And I was not too happy about the implementation, because of the 3 char code (Win and Office MUI already decided for LCID), not happy because there was no programmatic way to control the language (it was the system UI and that was it), and not happy because it created yet another system for DLLs only, instead of making public the MUI API that can also support other localizable files (help, readme, samples, etc.)

Good part: Vista makes the MUI API public (and a lib is provided for back-port to XP).

We can only hope that the next version of MFC will use the recommended way.

And maybe even (one day) even have VS UI support for resource-only-dlls for native applications (like the one for .NET applications).

# Jesper Holmberg [MSFT] on 3 Nov 2006 5:22 PM:

I just checked the XP SP2 slp hivedef for all languages, and it seems that only Spanish happens to have a two-letter value in INTL_SLANGUAGE.

I then went back a digged a little further, and as far as I can tell, this issue was introduced way back when the file was first added to Windows - during the Windows 2000 localization. Hivedef used to be really problematic for localization (at least for us in Ireland), becase we didn't fully understand the file and due to tools issues, we localized this in notepad. Back in 98-99, localization errors in this file (and similar files, e.g. update.inf) caused a lot of BVT or build breaks (often due to bad data in the file, or syntax errors), and so the loc team developed a bit of fear and superstition about these files.

The file has been updated several times since W2k RTM, often in Service Packs and definitely in XP and Server 2003. Even though the tools improved, our battle scars remained and we have always tried not to touch those resources unnecessarily. Since the loc team has not heard about the issue until now, hivedef was never fixed. Maybe now that code has been written assuming the value should be "ES" it's too late, dunno... we'll keep it on the radar for Windows XP SP3 and Windows Server 2003 SP2 though.


Please consider a donation to keep this archive running, maintained and free of advertising.
Donate €20 or more to receive an offline copy of the whole archive including all images.

go to newer or older post, or back to index or month or day