Search code examples
c++gettext

Static member variables are not translated by gettext


Problem

My software is translated via gettext. The locales are called at the very beginning of the main function. Unfortunately, the static member variables of my monostate "Messages" which contains all message strings are not translated as static member variables are processed before the main. The rest of the software (the static functions of the "Messages" class) is translated as expected.

I mean I could use functions instead but I would prefer a solution where the variables remain variables.

Question

How can I get the static member variables translated without making them functions?

Example

Messages.h

#include <boost/format.hpp>
#include <boost/locale.hpp>

#define _(STRING) boost::locale::translate(STRING)

class Messages
{
    const std::string example_var = _("This message is not translated.");

    void example_func(int i) noexcept
    {
        return boost::str(boost::format(_("Just use %1% somehow.")) % i);
    }
}

main.cpp

#include <iostream>
#include <boost/locale.hpp>
#include "Messages.h"

int main()
{
    boost::locale::generator gen;

    //Specify the location of dictionaries.
    gen.add_messages_path("./translations/");
    gen.add_messages_domain("de_DE");

    //Generate the locales and imbue them to the iostream.
    std::locale::global(gen(""));
    std::cout.imbue(std::locale());
    std::cerr.imbue(std::locale());

    //Not translated
    std::cout << Messages::example_var << std::endl;

    //Translated
    std::cout << Messages::example_func() << std::endl;
}

Solution

  • I got it with the comment of Reinstate Monica. Just put an unused variable before all static member variables and calculate its value in a lambda function. The value itself does not matter at all. The only thing that matter is that the lambda function makes the right locale function calls. See my solution below:

    #include <boost/format.hpp>
    #include <boost/locale.hpp>
    
    #define _(STRING) boost::locale::translate(STRING)
    
    class Messages
    {
        //Member variables
    private:
        int init_locales = []() -> int
                {
            //Localization
            if(!Settings::get_lang().empty())
            {
                boost::locale::generator gen;
    
                //Specify the location of dictionaries.
                gen.add_messages_path("./translations/");
                gen.add_messages_domain(Settings::get_lang());
    
                //Generate the locales and imbue them to the iostream.
                std::locale::global(gen(""));
                std::cout.imbue(std::locale());
                std::cerr.imbue(std::locale());
            }
    
            return 0;
                }();
    public:
        const std::string example_var = _("This message is translated now!");
    
        //Member functions
        void example_func(int i) noexcept
        {
            return boost::str(boost::format(_("Just use %1% somehow.")) % i);
        }
    }