1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#include "services.h"
#include <stack>
std::vector<Anope::string> languages;
void InitLanguages()
{
#if GETTEXT_FOUND
languages.clear();
spacesepstream sep(Config->Languages);
Anope::string language;
while (sep.GetToken(language))
{
if (!IsFile("languages/" + language + "/LC_MESSAGES/anope.mo"))
{
Log() << "Error loading language " << language << ", file does not exist!";
}
else
{
Log(LOG_DEBUG) << "Found language file " << language;
languages.push_back(language);
}
}
if (!bindtextdomain("anope", (services_dir + "/languages/").c_str()))
Log() << "Error calling bindtextdomain, " << Anope::LastError();
else
Log(LOG_DEBUG) << "Successfully bound anope to " << services_dir << "/languages/";
#else
Log() << "Can not load languages, gettext is not installed";
#endif
}
const Anope::string GetString(NickCore *nc, const char *string)
{
return GetString("anope", nc ? nc->language : "", string);
}
const Anope::string GetString(const Anope::string &domain, const Anope::string &lang, const char *string)
{
PushLanguage(domain, lang);
const char *t_string = anope_gettext(string);
PopLanguage();
return t_string;
}
#if GETTEXT_FOUND
static std::stack<std::pair<Anope::string, Anope::string > > language_stack;
void PushLanguage(const Anope::string &domain, Anope::string language)
{
if (language.empty() && !Config->NSDefLanguage.empty())
language = Config->NSDefLanguage;
language_stack.push(std::make_pair(domain, language));
}
void PopLanguage()
{
language_stack.pop();
}
/* Used by gettext to make it always dynamically load language strings (so we can drop them in while Anope is running) */
extern "C" int _nl_msg_cat_cntr;
const char *anope_gettext(const char *string)
{
std::pair<Anope::string, Anope::string> lang_info;
if (!language_stack.empty())
lang_info = language_stack.top();
if (lang_info.first.empty() || lang_info.second.empty())
return string;
++_nl_msg_cat_cntr;
#ifdef _WIN32
SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang_info.second.c_str()), SUBLANG_DEFAULT), SORT_DEFAULT));
#else
/* First, set LANGUAGE env variable.
* Some systems (Debian) don't care about this, so we must setlocale LC_ALL aswell.
* BUT if this call fails because the LANGUAGE env variable is set, setlocale resets
* the locale to "C", which short circuits gettext and causes it to fail on systems that
* use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not
* C or POSIX) then.
*/
setenv("LANGUAGE", lang_info.second.c_str(), 1);
if (setlocale(LC_ALL, lang_info.second.c_str()) == NULL)
setlocale(LC_ALL, "en_US");
#endif
const char *translated_string = dgettext(lang_info.first.c_str(), string);
#ifdef _WIN32
SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT));
#else
unsetenv("LANGUAGE");
setlocale(LC_ALL, "");
#endif
Anope::string translated = translated_string ? translated_string : "";
if (Config->UseStrictPrivMsg)
translated = translated.replace_all_cs("%R", "/");
else
translated = translated.replace_all_cs("%R", "/msg ");
return translated.c_str();
}
#else
void PushLanguage(const Anope::string &, Anope::string)
{
}
void PopLanguage()
{
}
const char *anope_gettext(const char *string)
{
Anope::string translated = string ? string : "";
if (Config->UseStrictPrivMsg)
translated = translated.replace_all_cs("%R", "/");
else
translated = translated.replace_all_cs("%R", "/msg ");
return translated.c_str();
}
#endif
void SyntaxError(CommandSource &source, const Anope::string &command, const Anope::string &message)
{
source.Reply(_("Syntax: \002%s\002"), message.c_str());
source.Reply(_(LanguageString::MORE_INFO), source.owner->nick.c_str(), command.c_str());
}
|