I am working on a game that is coded in C++ and I would like to make it possible to change language at runtime. Currently, the language is chosen at compile time by includin
You cannot do it with #include
, that's compile time only. More specifically, that's pre-processor only, which happens before compilation.
To get run-time variation, you'll have to move your translations to a text file (something like xml perhaps, but plain text works too) and set up a system that loads the file at startup to populate the strings in the code that need translation.
This also means all your strings will be dynamically sized at start-up, so the initialization period for the code will increase. But that's the cost of flexibility sometimes.
Perhaps the easiest way I've thought of is:
struct language {
virtual str::string greeting() =0;
virtual str::string greeting(const std::string& name) =0;
virtual str::string goodbye() =0;
virtual ~language() {}
};
struct English_language {
virtual str::string greeting() {return "Hello";}
virtual str::string greeting(const std::string& name) {return "Hello "+name;}
virtual str::string goodbye() {return "Goodbye";}
} English;
struct German_language {
virtual str::string greeting() {return "Hallo";}
virtual str::string greeting(const std::string& name) {return name+" Hallo";}
virtual str::string goodbye() {return "Auf Wiedersehen";}
} German;
language* CurLanguage = &English;
int main() {
std::cout << CurLanguage->greeting("Steve") << '\n';
CurLanguage = &German;
std::cout << CurLanguage->goodbye() << '\n';
}
[EDIT] I rewrote it from scratch, since I realized pure virtual functions are a way to error at compile time if you miss a sentence, making maintenance much simpler. This version also has the ability to handle variables (dates, names, times, numbers, etc) neatly. This concept is based off what we use at my job, for over 2900 phrases/sentences in ~20 languages.
You can not change #include's at runtime due to them being evaluated during compile time only.
What you can do instead, is have "language sheets". You can build a system that you reference during runtime, or you can have several text documents (such as .xml files) that you read and store when you want to change languages. Doing it this way also allows your application to be extended upon by users of the software in the future, as it will not be hardcoded.
If you design it in such a way, you could keep all your "language sheets" in one folder, then have your program check that folder for all available language sheets. This will allow users to also add languages to your program.
What you will basically need to do is create a string table, which can be done as part of a hardcoded method, or as part of a more dynamic method (mentioned as the language sheets).
Pre-processing (#include, #ifdef, #define, etc) actually happens BEFORE compilation. You can think of pre-processing as text replacement, the output of which is the source code fed to the compiler. #defines and such occupy a separate namespace from variables in your program, and by the time your program is compiled, all of that is set in stone. In other words, what you are asking for is NOT possible.
To better understand this, look at your compiler options and look for an option that lets you keep the pre-processed output.
What you need to do instead is change how your string handling works. Instead of changing out the strings at compile time, you need to do something at runtime.
Check your platform - on most platforms there are APIs for doing localization. They vary by platform, though, so if you are doing a cross platform app, then you might have to roll your own.