21 #include <boost/locale.hpp>
23 #include <boost/thread.hpp>
26 #define DBG_G LOG_STREAM(debug, lg::general())
27 #define LOG_G LOG_STREAM(info, lg::general())
28 #define WRN_G LOG_STREAM(warn, lg::general())
29 #define ERR_G LOG_STREAM(err, lg::general())
31 namespace bl = boost::locale;
34 class default_utf8_locale_name
40 static default_utf8_locale_name* lname =
new default_utf8_locale_name();
44 default_utf8_locale_name()
47 LOG_G <<
"Generating default locale\n";
52 const boost::locale::info& locale_info = std::use_facet< boost::locale::info >(default_locale);
53 name_ += locale_info.language();
54 if(!locale_info.country().empty())
55 name_ +=
"_" + locale_info.country();
57 if(!locale_info.variant().empty())
58 name_ +=
"@" + locale_info.variant();
60 catch(
const std::exception&
e)
62 ERR_G <<
"Failed to generate default locale string. message:" << e.what() << std::endl;
64 LOG_G <<
"Finished generating default locale, default is now '" << name_ <<
"'\n";
69 struct translation_manager
79 const bl::localization_backend_manager& g_mgr = bl::localization_backend_manager::global();
82 LOG_G <<
"Found boost locale backend: '" <<
name <<
"'\n";
85 generator_.use_ansi_encoding(
false);
86 generator_.categories(bl::message_facet | bl::information_facet | bl::collation_facet);
87 generator_.characters(bl::char_facet);
91 update_locale_internal();
96 if(loaded_domains_.find(domain) != loaded_domains_.end())
101 if(domain.find(
'/') != std::string::npos)
107 ERR_G <<
"illegal textdomain name '" << domain
108 <<
"', skipping textdomain\n";
112 generator_.add_messages_domain(domain);
113 loaded_domains_.insert(domain);
118 if(loaded_paths_.find(path) != loaded_paths_.end())
122 generator_.add_messages_path(path);
123 loaded_paths_.insert(path);
126 void set_default_messages_domain(
const std::string& domain)
128 generator_.set_default_messages_domain(domain);
134 std::string::size_type at_pos = language.rfind(
'@');
139 else if(at_pos != std::string::npos)
141 current_language_ = language.substr(0, at_pos) +
".UTF-8" + language.substr(at_pos);
145 current_language_ = language +
".UTF-8";
155 void update_locale_internal()
159 LOG_G <<
"attempting to generate locale by name '" << current_language_ <<
"'\n";
160 current_locale_ = generator_.generate(current_language_);
162 LOG_G <<
"updated locale to '" << current_language_ <<
"' locale is now '" << current_locale_.name() <<
"' ( "
163 <<
"name='" << info.name()
164 <<
"' country='" << info.country()
165 <<
"' language='" << info.language()
166 <<
"' encoding='" << info.encoding()
167 <<
"' variant='" << info.variant() <<
"')\n";
169 catch(
const boost::locale::conv::conversion_error&)
171 assert(std::has_facet<boost::locale::info>(current_locale_));
173 ERR_G <<
"Failed to update locale due to conversion error, locale is now: "
174 <<
"name='" << info.name()
175 <<
"' country='" << info.country()
176 <<
"' language='" << info.language()
177 <<
"' encoding='" << info.encoding()
178 <<
"' variant='" << info.variant()
188 update_locale_internal();
190 return current_locale_;
194 std::set<std::string> loaded_paths_;
195 std::set<std::string> loaded_domains_;
198 std::locale current_locale_;
202 translation_manager& get_manager()
204 static translation_manager* mng =
new translation_manager();
225 if (msgval == msgid) {
226 const char* firsthat = std::strrchr (msgid,
'^');
227 if (firsthat ==
nullptr)
230 msgval = firsthat + 1;
237 std::string msgval = boost::locale::dngettext(domainname, singular, plural, n, get_manager().
get_locale());
238 if (msgval == singular) {
239 const char* firsthat = std::strrchr (singular,
'^');
240 if (firsthat ==
nullptr)
243 msgval = firsthat + 1;
248 void bind_textdomain(
const char* domain,
const char* directory,
const char* )
250 LOG_G <<
"adding textdomain '" << domain <<
"' in directory '" << directory <<
"'\n";
251 get_manager().add_messages_domain(domain);
252 get_manager().add_messages_path(directory);
253 get_manager().update_locale();
258 LOG_G <<
"set_default_textdomain: '" << domain <<
"'\n";
259 get_manager().set_default_messages_domain(domain);
267 LOG_G <<
"setting language to '" << language <<
"' \n";
268 get_manager().set_language(language);
272 return std::use_facet<std::collate<char> >(get_manager().get_locale()).
compare(s1.c_str(), s1.c_str() + s1.size(), s2.c_str(), s2.c_str() + s2.size());
rng * generator
This generator is automatically synced during synced context.
int compare(const std::string &s1, const std::string &s2)
const language_def & get_locale()
std::string dsngettext(const char *domainname, const char *singular, const char *plural, int n)
std::string dgettext(const char *domain, const char *msgid)
void set_language(const std::string &slocale, const std::vector< std::string > *alternates)
std::string dsgettext(const char *domainname, const char *msgid)
void bind_textdomain(const char *domain, const char *directory, const char *encoding)
GLsizei const char ** path
void set_default_textdomain(const char *domain)
static UNUSEDNOWARN std::string gettext(const char *str)
std::string egettext(char const *msgid)
GLuint const GLchar * name
Standard logging facilities (interface).
GLsizei const GLcharARB ** string