0

How can I add multilanguage support to a C++ program? I want to let the user to choose between 2 languages when opening the app. What's the simplest way without any external libraries?

JaMiT
  • 14,422
  • 4
  • 15
  • 31
ellefgh
  • 3
  • 2
  • 2
    Realistically, i18n on a C++ program is a big job. External libraries are probably required to do it right, and we're not in the business of recommending any here. – Fred Larson Nov 29 '21 at 21:17
  • 2
    The C++ standard does not provide an answer to that question. Without using any external libraries, you can write your own localization toolset. – Eljay Nov 29 '21 at 21:18
  • On Windows you can use resource-strings -> https://stackoverflow.com/questions/6276284/how-to-call-a-string-resource-in-c/6276343 – Den-Jason Nov 29 '21 at 21:30
  • This might help if you're using Linux/Mac -> https://stackoverflow.com/questions/11789615/how-to-support-multiple-language-in-a-linux-c-c-program/11792093 – Den-Jason Nov 29 '21 at 21:31
  • You could make a dictionary where it's key is an enum representing a word, then the values could be a structure containing the language and actual string in that language. Example: (pseudo code) dictionary: - WORD1_ENUM => structure[LANGUAGE1_ENUM, WORD_IN_LANGUAGE1], structure[LANGUAGE2_ENUM, WORD_IN_LANGUAGE2] – David Hožič Nov 29 '21 at 21:37
  • How extensible a system do you want? Do you want something that will have to be overhauled if you decide to support a third language? What about the number of translations that need to be made? Images as well as text? (Is that the reason for the "graphics" tag?) Are you thinking short term or long term? Keep in mind that "simplest" does not imply "simple". – JaMiT Nov 30 '21 at 02:17
  • In C++, it's not possible to write any interactive program without external libraries... – 9ilsdx 9rvj 0lo Nov 30 '21 at 10:57
  • For VCL I use my own tool I wrote years back... It reads source code of my project. Make a list of all translatable stuff (captions, hints, message ...) from that creates `*.h` file that loads this from a language ini file, and also creates such ini with values taken from the source. Then I created another tool that takes such created ini in english and translates it to different language using dictionary. Unknown stuff is marked by *** before original english wording so I can easily correct it manually latter ... this way I can add multilingual support to any of my project in few minutes – Spektre Dec 01 '21 at 09:23
  • so I only add menu with found language files and when i select any it just run the function from created h file that changes the language on runtime without the need to restart app ... The first tool also creates ini for actual state of all my visual components and load/save it on app start/exit so it remembers my settings without any effort. So you can try to build something similar for language/environment you use. Its really just a matter of reading text file and locating important words like class, TButton, ... etc – Spektre Dec 01 '21 at 09:25
  • Most multilingual SW build on MSVC++ I saw uses some external tool that creates language DLL file for each language and it loads on app star so you need restart on each change of language. This is preferred if you do not want anyone is messing up the wording ... – Spektre Dec 01 '21 at 09:30

1 Answers1

2

Replying to my comment, "You could make a dictionary where it's key is an enum representing a word, then the values could be an array of structures containing the language and actual string in that language. Example: (pseudo code) dictionary: - WORD1_ENUM => structure[LANGUAGE1_ENUM, WORD_IN_LANGUAGE1], structure[LANGUAGE2_ENUM, WORD_IN_LANGUAGE2]", you could make a dictionary that retrieves your world based on the selected language.

#include <initializer_list>
#include <string>
#include <vector>
#include <iostream>


enum STRINGS
{
    HELLO_WORLD,
    GOODBYE_WORLD
};

#define SELECTED_LANGUAGE SLOVENIAN
#define NOT_FOUND_STR  "Not Found"
enum LANGUAGE
{
    ENGLISH,
    SLOVENIAN
};


struct DICTIONARY_VAL
{
    LANGUAGE lang;
    std::string text;
};

struct DICTIONARY_BLOCK_t{
    STRINGS key;
    std::vector<DICTIONARY_VAL> values;
};


class DICTIONARY_t
{
private:
    std::vector<DICTIONARY_BLOCK_t> data;
public:
    DICTIONARY_t (std::initializer_list<DICTIONARY_BLOCK_t> var)
    {
        for (DICTIONARY_BLOCK_t val : var)
        {
            data.push_back(val);
        }
    }

    std::string get_value(STRINGS key, LANGUAGE lang)
    {
        std::string l_ret = NOT_FOUND_STR;
        for (uint32_t i = 0; i < data.size() ; i++)
        {
            if (data[i].key == key)
            {
                for (uint32_t j = 0; j < data[i].values.size(); j++)
                {
                    if (data[i].values[j].lang == lang)
                    {
                        l_ret = data[i].values[j].text;
                        break;
                    }
                }
                break;
            }
        }
        return l_ret;
    }

};

DICTIONARY_t dict = 
{
    {HELLO_WORLD,   { {ENGLISH, "Hello World"},   {SLOVENIAN, "Zivjo svet"     }  }},
    {GOODBYE_WORLD, { {ENGLISH, "Goodbye World"}, {SLOVENIAN, "Nasvidenje svet"}  }}
};



int main()
{
    LANGUAGE selected_language;
    std::cout << "Select your lanugage\n0.) ENGLISH\n1.) Slovenian" << std::endl;
    int tmp;
    std::cin >> tmp;
    selected_language = (LANGUAGE) tmp;

    
    std::cout << dict.get_value(HELLO_WORLD, selected_language) << std::endl;


    return 0;
}
David Hožič
  • 235
  • 2
  • 7
  • This is a method used in many of the embedded systems that I have worked on. The present system I'm working has over 30 phrases and over 15 languages to support. – Thomas Matthews Nov 29 '21 at 22:56