Search code examples
delphilocalizationdelphi-7

Delphi 7 application not loading STRINGTABLE resources on Windows 10


Been away from Delphi development for some time. Recently an old client contacted me with issues using an older Delphi 7 application on Windows 10 (x86 and x64). The application generally works fine, but internationalisation is not loading the correct string.

Here's the basic scenario.

  1. An ASCII file named "String.rc" is generated from a translation spreadsheet:
Language LANG_ENGLISH, SUBLANG_ENGLISH_UK
STRINGTABLE
BEGIN
    cszTestString "English is good"
END

Language LANG_DUTCH, SUBLANG_DUTCH
STRINGTABLE
BEGIN
    cszTestString "En Nederlands is lekker"
END
  1. A separate file called "String_IDs.pas" is generated to give an integer value to cszTestString:
unit String_IDs;
interface
const
    cszTestString = 1234;
  1. "Strings.rc" is compiled using the Windows 10 SDK rc.exe to generate "Strings.res".

  2. The .pas and resource files are compiled into the Delphi application by including the following in the project .dpr file:

    uses
        String_IDs in 'source\String_IDs.pas';

    {$R 'source\Strings.res'}
  1. In code, set the locale to English or Dutch using:
    appLocale := (SUBLANG_ENGLISH_UK shl 10) or LANG_ENGLISH; // 2057
    if (isDutch) then
        appLocale := (SUBLANG_DUTCH shl 10) or LANG_DUTCH; // 1043
  1. Set the threadlocale using:
    SetThreadLocale(appLocale);
  1. Test loading the string resource in three different ways:
    // A: Using LoadStr
    stringA := LoadStr(cszTestString);

    // B: Using LoadString
    if (LoadString(0, cszTestString, szBuffer, Length(szBuffer)) > 0) then
        stringB := szBuffer;
    
    // C: Using LoadString in a different format
    try
    pstrBuffer := AllocMem(MAX_PATH);
    if (LoadString(0, cszTestString, pstrBuffer, MAX_PATH) > 0) then
        stringC := StrPas(pstrBuffer);
    finally
        FreeMem(pstrBuffer, MAX_PATH);
    end;
  1. This was tested in a Windows XP (x86) VM. Everything works perfectly. In English, all three are "English is good". And in Dutch, all are "En Nederlands is lekker".

  2. But I tested in Windows 10 (x86 and x64) VMs and the text is always "English is good". Have tried changing compatibility settings but without success.

Is there some other Windows API to use on Windows 10, or perhaps special compatibility settings for this older application?


Solution

  • As mentioned in my comment on Windows Vista and newer you should be using SetThreadUILanguage instead of SetThreadLocale to handle localised resources when they are stored inside the same resource file, provided they are tagged with specific language identifier.

    Also based on SetThreadLocale and SetThreadUILanguage for Localization on Windows XP and Vista article it is not advisable of using SetThreadUILanguage as it might not have the desired effect on Windows XP. You should keep using SetThreadLocale on Windows XP

    In order to learn how to check for Windows version the application is executed I recommend you read Getting the Windows version?