2
votes

I have a really little application made with MFC with german menus. Now I was asked to make an english version too. But the goal is to not use additional language DLLs. There should only be two .exe files (german and english) at the end. Do you know any step by step manual how to add a second resource file for the english dialogues (if needed) and how to use them in my C++ code? My idea is to use a preprocessor directive:

#ifdef APPLANG=EN
    m_wndRibbonBar.LoadFromResource(IDR_RIBBON_EN);
#else if
    m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
#endif

Is it a good idea to do it this way? And what are the right steps to simply copy the existing resource files and modify them to English?

I have tried several things like making a new resource file and copy the original german menu to the new file. But than I get several errors like "Enter a legal resource ID".

1
Oww... no, don't do that.... have a look here, it will give you some idea: stackoverflow.com/questions/47441124/…Stefan
But, question; although you can do it all in the same application; why do you specifically state not to use any dll's?Stefan
#ifdef APPLANG=EN is not a valid preprocessor, nor is #else if. You can try #ifdef APPLANG_EN ... and #elif APPLANG_DE and set the value for IDR_RIBBON_TARGET instead of the whole line codeBarmak Shemirani
I have a multi-lingual executable, where all resources are embedded in the .exe file (no resource DLLs). The system automatically loads the right language resources according to the current user locale (with fallback to English). For each language I have a .rc2 file that starts with LANGUAGE <LANGID>, <SUBLANGID>. These are all #include'd in one main .rc2 file. The .rc2 files are used so the Visual Studio resource editor won't create a mess. Make sure to store the .rc2 files as Unicode (UTF-16 LE).zett42
@TomTom I will, as soon as I find some time.zett42

1 Answers

5
votes

You can embed multiple language resources in a single .exe file without having to use resource DLLs. There is no support for this use case by the Visual Studio resource editor, so resource scripts must be edited manually, using a text editor.

To define the resources, use .rc2 files which the Visual Studio resource editor won't try to modify. Make sure to store the .rc2 files with Unicode (UTF-16 LE) encoding and always end them with a line break, otherwise the resource compiler will fail.

Steps

  1. A project created through the MFC application wizard already includes an empty .rc2 file, which we can use as our "main" .rc2 file. Otherwise follow the documentation or create a new MFC application using the wizard to dissect how the .rc2 file is included.
  2. In the main .rc2 file add an #include for each language-specific .rc2 file:

    #include "lang_en.rc2"
    #include "lang_de.rc2"
    
    // Restore default language for resources included after current file
    LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
    
  3. Create the language-specific .rc2 files. Each file must start with LANGUAGE <LANGID>, <SUBLANGID> to indicate the language of the following resources:

    lang_en.rc2

    LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
    STRINGTABLE
    BEGIN
        IDS_STRING1 "Stack Overflow"
        IDS_STRING2 "Stack Overflow is a privately held website, the flagship site of the Stack Exchange Network, created in 2008 by Jeff Atwood and Joel Spolsky."
    END
    

    lang_de.rc2

    LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
    STRINGTABLE
    BEGIN
        IDS_STRING1 "Stapelüberlauf"
        IDS_STRING2 "Stack Overflow (englisch für Stapelüberlauf) ist eine Internetplattform, auf der angemeldete Benutzer Fragen zum Thema Softwareentwicklung stellen können."
    END
    
  4. Build the executable and examine it in a resource editor to see if the resources are actually included for multiple languages. Instead of using a resource editor, you can also open the .exe file in Visual Studio to examine its resources. For instance, the demo .exe I build for this answer, looks like this, when opened in Visual Studio:

    Multi language string table

In the code you can load resources as usual, Windows will automatically load the language resource that best matches the current user locale. If it doesn't find a match, it falls back to English.

If you want to explicitly load a resource for a given language, you can do this by using the resource functions that have a language parameter, e. g. FindResourceEx().

Including standard MFC resources

Without further ado, standard MFC resources will be included only in the "main" language that is configured in the resource properties of the project.

In the projects where I have used this approach, I had no need for the standard MFC resources. The following is just an untested idea how it could possibly be done.

In each language-specific .rc2 file that is not the "main" language, add #includes for the MFC standard resources after the LANGUAGE line, e. g.:

LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL

#ifdef __AFXRES_RC__
    #undef __AFXRES_RC__    // To be able to include multiple language versions of afxres.rc
#endif
#include "l.deu\afxres.rc"  // Standard MFC resources

STRINGTABLE
BEGIN
    IDS_STRING1 "Stapelüberlauf"
    IDS_STRING2 "Stack Overflow (englisch für Stapelüberlauf) ist eine Internetplattform, auf der angemeldete Benutzer Fragen zum Thema Softwareentwicklung stellen können."
END

The #undef is there to circumvent the include guard of the standard MFC resource file, which normally prevents multiple includes. In our case this is OK, because the resources will end up in different language resource sections of the executable.