静态成员变量不被gettext翻译
Static member variables are not translated by gettext
问题
我的软件是通过 gettext 翻译的。语言环境在 main 函数的最开始被调用。不幸的是,我的包含所有消息字符串的 monostate "Messages" 的静态成员变量没有被翻译为静态成员变量在 main 之前处理。软件的其余部分("Messages" class 的静态函数)按预期翻译。
我的意思是我可以改用函数,但我更喜欢变量仍然是变量的解决方案。
问题
如何在不使静态成员变量生效的情况下翻译它们?
例子
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;
}
我通过 Reinstate Monica 的评论得到了它。
只需将一个未使用的变量放在所有静态成员变量之前,然后在 lambda 函数中计算它的值。价值本身根本无关紧要。唯一重要的是 lambda 函数进行正确的语言环境函数调用。
请参阅下面的解决方案:
#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);
}
}
您必须牢记宏 _()
有双重用途:它在运行时翻译字符串,并在您调用构建系统内部的 gettext
程序时将字符串标记为可翻译用于字符串翻译。
对于这种情况,惯用的方法是定义另一个宏 N_()
:
#define N_(STRING) STRING
将其视为空操作 gettext。
然后通过使用选项 --keyword=N_
调用 xgettext
,确保这些字符串被构建系统中的 xgettext
识别和提取。在标准 Makefile 中,默认情况下应该是这种情况。
并且在运行时,只需对变量调用翻译函数:
std::cout << boost::locale::translate(Messages::example_var) << std::endl;
简而言之:不要更改程序的运行时行为,只是为了确保您的变量已使用所选区域设置的已翻译字符串常量进行初始化。那是没有必要的。相反,只需将字符串常量标记为可翻译并在运行时翻译它。
问题
我的软件是通过 gettext 翻译的。语言环境在 main 函数的最开始被调用。不幸的是,我的包含所有消息字符串的 monostate "Messages" 的静态成员变量没有被翻译为静态成员变量在 main 之前处理。软件的其余部分("Messages" class 的静态函数)按预期翻译。
我的意思是我可以改用函数,但我更喜欢变量仍然是变量的解决方案。
问题
如何在不使静态成员变量生效的情况下翻译它们?
例子
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;
}
我通过 Reinstate Monica 的评论得到了它。 只需将一个未使用的变量放在所有静态成员变量之前,然后在 lambda 函数中计算它的值。价值本身根本无关紧要。唯一重要的是 lambda 函数进行正确的语言环境函数调用。 请参阅下面的解决方案:
#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);
}
}
您必须牢记宏 _()
有双重用途:它在运行时翻译字符串,并在您调用构建系统内部的 gettext
程序时将字符串标记为可翻译用于字符串翻译。
对于这种情况,惯用的方法是定义另一个宏 N_()
:
#define N_(STRING) STRING
将其视为空操作 gettext。
然后通过使用选项 --keyword=N_
调用 xgettext
,确保这些字符串被构建系统中的 xgettext
识别和提取。在标准 Makefile 中,默认情况下应该是这种情况。
并且在运行时,只需对变量调用翻译函数:
std::cout << boost::locale::translate(Messages::example_var) << std::endl;
简而言之:不要更改程序的运行时行为,只是为了确保您的变量已使用所选区域设置的已翻译字符串常量进行初始化。那是没有必要的。相反,只需将字符串常量标记为可翻译并在运行时翻译它。