myWallJSON
myWallJSON

Reputation: 9502

is it possible to compile separate apps for each language in Qt?

So I created translations for N languages (using Qt linguist). I want to compile my app into N apps that differ with prefix like _en_US or _fr_FR embedding into each one translated strings. Also I want to keep one version of app which will automatically determine current platform language having all translation versions inside. How shall I change my .pro file to achieve such results?

Upvotes: 2

Views: 218

Answers (1)

Claudio
Claudio

Reputation: 1706

I think it is much easier to embed all the translations and to decide at runtime which one to load. Perhaps you can provide a command line switch or an option to override the system locale. You do not even have to embed them in the executable, you may ship them in a "translations" directory. To get the system locale at runtime you can use QLocale class:

Application application(argc, argv);

QString locale = QLocale::system().name();
QString translationsDir = ":/translations";

QTranslator appTranslator;
QTranslator qtTranslator;

appTranslator.load(locale, translationsDir);
qtTranslator .load("qt_" + locale,
                    QLibraryInfo::location(QLibraryInfo::TranslationsPath));

application.installTranslator(& appTranslator);
application.installTranslator(& qtTranslator);

Anyway if you really want to do in your way you can rely on an environment variable LANGUAGE_ID to detect what language to embed in your build, and then rebuild your project for each of the available languages. It might take a lot of time, but maybe you can do that only for the final build.

Here is an example:

#include <iostream>

int main(int argc, char *argv[])
{
#ifdef EMBED_ONLY_ONE_LANGUAGE
    std::cout << "Embedded language is " << LANGUAGE_ID << std::endl;
#elif EMBED_ALL_LANGUAGES
    std::cout << "Embedded all languages" << std::endl;
#else
    std::cout << "What???" << std::endl;
#endif
}

And here is the .pro file:

TEMPLATE = app
DEPENDPATH += .
INCLUDEPATH += .
TARGET = SomeName

CONFIG -= qt
CONFIG += console

# Input
SOURCES += main.cpp

# It seems that "equals" does not work with environment variables so we
# first read it in a local variable.
LANGUAGE_ID=$$(LANGUAGE_ID)

equals(LANGUAGE_ID,) {
    # No language id specified. Add the build instructions to embed all the
    # translations and to decide at runtime which one to load.
    message(No language id specified)

    # This adds a preprocessor variable so that the program knows that it has
    # every language.
    DEFINES *= EMBED_ALL_LANGUAGES
} else {
    # A language id was specified. Add the build instructions to embed only
    # the relative translation.
    message(Specified language id: $$LANGUAGE_ID)

    # This adds a preprocessor variable LANGUAGE_ID whose value is the language.
    DEFINES *= LANGUAGE_ID=\\\"$$LANGUAGE_ID\\\"

    # This adds a preprocessor variable so that the program knows that it has
    # only one language.
    DEFINES *= EMBED_ONLY_ONE_LANGUAGE

    # This renames the executable.
    TARGET=$${TARGET}_$$(LANGUAGE_ID)
}

It makes use of the undocumented test function equals. Note that if you change the value of the environment variable LANGUAGE_ID you have to run qmake again (possibly after having deleted the Makefiles).

A (perhaps better) alternative is to use CMake and specify the language id as a CMake's command line variable:

cmake_minimum_required(VERSION 2.6)
project(SomeName)

set(SOURCES main.cpp)

add_executable(SomeName ${SOURCES})

if(${LANGUAGE_ID} MATCHES "[a-z][a-z]_[A-Z][A-Z]")
    # A language id was specified. Add the build instructions to embed only
    # the relative translation.
    message("Embedding language ${LANGUAGE_ID}")

    # This adds a preprocessor variable LANGUAGE_ID whose value is the language.
    add_definitions("-DLANGUAGE_ID=\"${LANGUAGE_ID}\"")

    # This adds a preprocessor variable so that the program knows that it has
    # only one language.
    add_definitions("-DEMBED_ONLY_ONE_LANGUAGE")

    # This renames the executable.
    set_target_properties(SomeName PROPERTIES OUTPUT_NAME "SomeName_${LANGUAGE_ID}")

else(${LANGUAGE_ID} MATCHES "[a-z][a-z]_[A-Z][A-Z]")
    # No language id specified. Add the build instructions to embed all the
    # translations and to decide at runtime which one to load.
    message("Not embedding any language")

    # This adds a preprocessor variable so that the program knows that it has
    # every language.
    add_definitions("-DEMBED_ALL_LANGUAGES")

endif(${LANGUAGE_ID} MATCHES "[a-z][a-z]_[A-Z][A-Z]")

Upvotes: 1

Related Questions