2
votes

I have an MFC project that contains one .rc file for US English, and one .rc file for Swiss German. The two .rc files are identical except for 1) a single string that I am using for my tests, and 2) the .rc files use different LANGUAGE statements at the top:

LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US    >>> for US English
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_SWISS   >>> for Swiss German

I am including the two .rc files from a single main .rc file. The main .rc file is compiled, the language-specific .rc files are set to "exclude from build".

I believe I have setup everything correctly, because I can use a snippet like the following to successfully load a string resource from the Swiss German language resource file:

WORD swissGermanLanguageID =
    MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS);
WORD swissGermanLCID =
    MAKELCID(swissGermanLanguageID, SORT_DEFAULT);
CString teststring;
teststring.LoadString(AfxGetResourceHandle(), IDS_TESTSTRING, swissGermanLCID);

The problem is: When I omit the language ID, such as in the following snippet, MFC always loads the resource from the US English resources, no matter what I try:

CString teststring;
teststring.LoadString(IDS_TESTSTRING);

Things that I have tried/checked:

  • I have triple-checked that my locale is set to Swiss German in the Windows control panel.
  • When I remove all STRINGTABLE entries from the US English resource file the default LoadString successfully loads the Swiss German test string. My conclusion is that if present the US English resources have precedence over the Swiss German resource.
  • I have unsuccessfully tried to set the thread locale to Swiss German (snippet at the end of this post). MFC still insists on loading the US English string.
  • I have scoured the project for any piece of code that is language-related, but there's nothing. The project is a simple MFC application that I created via the Project Wizard from Visual Studio 2013.
  • I also tried various settings for the "Culture" option in the "Resources" section of the project properties. Currently I am explicitly setting /l 0x0807 which corresponds to Swiss German.
  • In a final attempt I have tried splitting the Swiss German resources into a separate satellite DLL - obviously that works perfectly, I assume because MFC invokes AfxSetResourceHandle() behind the scene.

OK, so finally, here's the question: How does MFC determine the default language ID that it uses when it loads resources? And even better: How can I change that default language ID?


Here's the snippet I mentioned above that I'm using to set the thread locale:

WORD swissGermanLanguageID =
    MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS);
WORD swissGermanLCID =
    MAKELCID(swissGermanLanguageID, SORT_DEFAULT);
SetThreadLocale(swissGermanLCID);
1
What language is your OS?zdf
@ZDF The OS is German, Visual Studio is English. The problem persists when I launch the test app from outside Visual Studio.herzbube

1 Answers

2
votes
  • Please check which resources are actually packed into your executable. You can use something like Explorer's Suite or other resource editor.
  • On Windows Vista and newer resource loading order is determined by the list of preferred languages that you can obtain using GetThreadPreferredUILanguages family of functions (there are a separate list for user, for process and for thread that get combined to perform resource lookup). Potentially it may be altered by MFC runtime, but I'm not sure about it. On your system this list will probably contain 4 entries: [de-CH, de, en-US, en].
  • Splitting resources into separate mui dlls might be a good idea, though it should work perfectly fine when everything is packed into a single executable.